Merge from Chromium at DEPS revision r198571

This commit was generated by merge_to_master.py.

Change-Id: I951118a03836157090561764dd2627f0add8118f
diff --git a/content/DEPS b/content/DEPS
index 79b961e..141bb04 100644
--- a/content/DEPS
+++ b/content/DEPS
@@ -20,6 +20,7 @@
   "+crypto",
   "+grit/content_resources.h",
   "+grit/ui_resources.h",
+  "+grit/ui_strings.h",
   "+grit/webkit_chromium_resources.h",
   "+grit/webkit_resources.h",
   "+grit/webkit_strings.h",
@@ -53,6 +54,7 @@
   "+third_party/angle",
   "+third_party/flac",
   "+third_party/gpsd",
+  "+third_party/libjingle",
   "+third_party/mozilla",
   "+third_party/npapi/bindings",
   "+third_party/skia",
@@ -60,6 +62,7 @@
   "+third_party/tcmalloc",
   "+third_party/khronos",
   "+third_party/webrtc",
+  "+third_party/zlib/google",
   "+third_party/WebKit/Source/Platform/chromium",
   "+third_party/WebKit/Source/WebKit/chromium",
 
diff --git a/content/OWNERS b/content/OWNERS
index 7a05d15..467710c 100644
--- a/content/OWNERS
+++ b/content/OWNERS
@@ -9,6 +9,8 @@
 per-file *.sb=set noparent
 per-file *.sb=jeremy@chromium.org
 
+per-file *.isolate=csharp@chromium.org
+per-file *.isolate=maruel@chromium.org
 per-file content_components_navigation_interception.gypi=jknotten@chromium.org
 per-file content_components_navigation_interception.gypi=joth@chromium.org
 per-file content_components_navigation_interception.gypi=mkosiba@chromium.org
diff --git a/content/app/android/child_process_service.cc b/content/app/android/child_process_service.cc
index c0deb83..99e801b 100644
--- a/content/app/android/child_process_service.cc
+++ b/content/app/android/child_process_service.cc
@@ -10,7 +10,6 @@
 #include "base/android/jni_array.h"
 #include "base/logging.h"
 #include "base/posix/global_descriptors.h"
-#include "content/common/android/scoped_java_surface.h"
 #include "content/common/android/surface_texture_peer.h"
 #include "content/common/child_process.h"
 #include "content/common/child_thread.h"
@@ -19,6 +18,7 @@
 #include "content/public/common/content_descriptors.h"
 #include "ipc/ipc_descriptors.h"
 #include "jni/ChildProcessService_jni.h"
+#include "ui/gl/android/scoped_java_surface.h"
 
 using base::android::AttachCurrentThread;
 using base::android::CheckException;
@@ -45,7 +45,7 @@
 
   virtual void EstablishSurfaceTexturePeer(
       base::ProcessHandle pid,
-      scoped_refptr<content::SurfaceTextureBridge> surface_texture_bridge,
+      scoped_refptr<gfx::SurfaceTextureBridge> surface_texture_bridge,
       int primary_id,
       int secondary_id) {
     JNIEnv* env = base::android::AttachCurrentThread();
@@ -58,7 +58,7 @@
 
   virtual gfx::AcceleratedWidget AcquireNativeWidget(int surface_id) OVERRIDE {
     JNIEnv* env = base::android::AttachCurrentThread();
-    ScopedJavaSurface surface(
+    gfx::ScopedJavaSurface surface(
         content::Java_ChildProcessService_getViewSurface(
         env, service_.obj(), surface_id));
 
@@ -105,7 +105,7 @@
 }
 
 void QuitMainThreadMessageLoop() {
-  MessageLoop::current()->Quit();
+  base::MessageLoop::current()->Quit();
 }
 
 }  // namespace <anonymous>
diff --git a/content/app/android/content_main.cc b/content/app/android/content_main.cc
index 4059de4..e9cd1fd 100644
--- a/content/app/android/content_main.cc
+++ b/content/app/android/content_main.cc
@@ -7,6 +7,7 @@
 #include "base/at_exit.h"
 #include "base/base_switches.h"
 #include "base/command_line.h"
+#include "base/debug/trace_event.h"
 #include "base/lazy_instance.h"
 #include "content/public/app/content_main.h"
 #include "content/public/app/content_main_delegate.h"
@@ -35,6 +36,7 @@
 }
 
 static jint Start(JNIEnv* env, jclass clazz) {
+  TRACE_EVENT0("startup", "content::Start");
   const CommandLine& parsed_command_line = *CommandLine::ForCurrentProcess();
 
   // This is only for browser process. We want to start waiting as early as
diff --git a/content/app/android/library_loader_hooks.cc b/content/app/android/library_loader_hooks.cc
index 93a9d07..3d0cb9c 100644
--- a/content/app/android/library_loader_hooks.cc
+++ b/content/app/android/library_loader_hooks.cc
@@ -27,6 +27,7 @@
 #include "media/base/android/media_jni_registrar.h"
 #include "net/android/net_jni_registrar.h"
 #include "ui/android/ui_jni_registrar.h"
+#include "ui/gl/android/gl_jni_registrar.h"
 #include "ui/shell_dialogs/android/shell_dialogs_jni_registrar.h"
 
 namespace {
@@ -42,8 +43,9 @@
   CommandLine* command_line = CommandLine::ForCurrentProcess();
 
   if (command_line->HasSwitch(switches::kTraceStartup)) {
-    base::debug::TraceLog::GetInstance()->SetEnabled(
-        command_line->GetSwitchValueASCII(switches::kTraceStartup),
+    base::debug::CategoryFilter category_filter(
+        command_line->GetSwitchValueASCII(switches::kTraceStartup));
+    base::debug::TraceLog::GetInstance()->SetEnabled(category_filter,
         base::debug::TraceLog::RECORD_UNTIL_FULL);
   }
 
@@ -79,6 +81,9 @@
   if (!ui::android::RegisterJni(env))
     return RESULT_CODE_FAILED_TO_REGISTER_JNI;
 
+  if (!ui::gl::android::RegisterJni(env))
+    return RESULT_CODE_FAILED_TO_REGISTER_JNI;
+
   if (!ui::shell_dialogs::RegisterJni(env))
     return RESULT_CODE_FAILED_TO_REGISTER_JNI;
 
diff --git a/content/app/content_main_runner.cc b/content/app/content_main_runner.cc
index 50930fa..9f1947a 100644
--- a/content/app/content_main_runner.cc
+++ b/content/app/content_main_runner.cc
@@ -66,8 +66,7 @@
 #elif defined(OS_MACOSX)
 #include "base/mac/scoped_nsautorelease_pool.h"
 #if !defined(OS_IOS)
-#include "base/mach_ipc_mac.h"
-#include "base/system_monitor/system_monitor.h"
+#include "base/power_monitor/power_monitor.h"
 #include "content/browser/mach_broker_mac.h"
 #include "content/common/sandbox_init_mac.h"
 #endif  // !OS_IOS
@@ -82,6 +81,9 @@
 #if !defined(OS_MACOSX)
 #include "content/public/common/zygote_fork_delegate_linux.h"
 #endif
+#if !defined(OS_MACOSX) && !defined(OS_ANDROID)
+#include "content/zygote/zygote_main.h"
+#endif
 
 #endif  // OS_POSIX
 
@@ -101,10 +103,6 @@
 extern int RendererMain(const content::MainFunctionParams&);
 extern int UtilityMain(const MainFunctionParams&);
 extern int WorkerMain(const MainFunctionParams&);
-#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
-extern int ZygoteMain(const MainFunctionParams&,
-                      ZygoteForkDelegate* forkdelegate);
-#endif
 }  // namespace content
 
 namespace {
@@ -126,7 +124,11 @@
   DCHECK(current_station);
 
   HWINSTA winsta0 = ::OpenWindowStationA("WinSta0", FALSE, GENERIC_READ);
-  if (!winsta0 || !::SetProcessWindowStation(winsta0)) {
+  if (!winsta0) {
+    DLOG(INFO) << "Unable to open to WinSta0, we: "<< ::GetLastError();
+    return;
+  }
+  if (!::SetProcessWindowStation(winsta0)) {
     // Could not set the alternate window station. There is a possibility
     // that the theme wont be correctly initialized.
     NOTREACHED() << "Unable to switch to WinSta0, we: "<< ::GetLastError();
@@ -176,32 +178,6 @@
 
 static CAppModule _Module;
 
-#elif defined(OS_MACOSX) && !defined(OS_IOS)
-
-// Completes the Mach IPC handshake by sending this process' task port to the
-// parent process.  The parent is listening on the Mach port given by
-// |GetMachPortName()|.  The task port is used by the parent to get CPU/memory
-// stats to display in the task manager.
-void SendTaskPortToParentProcess() {
-  const mach_msg_timeout_t kTimeoutMs = 100;
-  const int32_t kMessageId = 0;
-  std::string mach_port_name = MachBroker::GetMachPortName();
-
-  base::MachSendMessage child_message(kMessageId);
-  if (!child_message.AddDescriptor(mach_task_self())) {
-    LOG(ERROR) << "child AddDescriptor(mach_task_self()) failed.";
-    return;
-  }
-
-  base::MachPortSender child_sender(mach_port_name.c_str());
-  kern_return_t err = child_sender.SendMessage(child_message, kTimeoutMs);
-  if (err != KERN_SUCCESS) {
-    LOG(ERROR) <<
-        base::StringPrintf("child SendMessage() failed: 0x%x %s", err,
-                           mach_error_string(err));
-  }
-}
-
 #endif  // defined(OS_WIN)
 
 #if defined(OS_POSIX) && !defined(OS_IOS)
@@ -531,6 +507,13 @@
                          const char** argv,
                          ContentMainDelegate* delegate) OVERRIDE {
 
+#if defined(OS_ANDROID)
+    // See note at the initialization of ExitManager, below; basically,
+    // only Android builds have the ctor/dtor handlers set up to use
+    // TRACE_EVENT right away.
+    TRACE_EVENT0("startup", "ContentMainRunnerImpl::Initialize");
+#endif  // OS_ANDROID
+
     // NOTE(willchan): One might ask why these TCMalloc-related calls are done
     // here rather than in process_util_linux.cc with the definition of
     // EnableTerminationOnOutOfMemory().  That's because base shouldn't have a
@@ -600,6 +583,8 @@
     // The exit manager is in charge of calling the dtors of singleton objects.
     // On Android, AtExitManager is set up when library is loaded.
     // On iOS, it's set up in main(), which can't call directly through to here.
+    // A consequence of this is that you can't use the ctor/dtor-based
+    // TRACE_EVENT methods on Linux or iOS builds till after we set this up.
 #if !defined(OS_ANDROID) && !defined(OS_IOS)
     exit_manager_.reset(new base::AtExitManager);
 #endif  // !OS_ANDROID && !OS_IOS
@@ -612,10 +597,11 @@
     autorelease_pool_.reset(new base::mac::ScopedNSAutoreleasePool());
 #endif
 
-    // On Android, the command line is initialized when library is loaded.
+    // On Android, the command line is initialized when library is loaded and
+    // we have already started our TRACE_EVENT0.
 #if !defined(OS_ANDROID)
     CommandLine::Init(argc, argv);
-#endif
+#endif // !OS_ANDROID
 
     int exit_code;
     if (delegate && delegate->BasicStartupComplete(&exit_code))
@@ -640,16 +626,24 @@
     // Enable startup tracing asap to avoid early TRACE_EVENT calls being
     // ignored.
     if (command_line.HasSwitch(switches::kTraceStartup)) {
+      base::debug::CategoryFilter category_filter(
+          command_line.GetSwitchValueASCII(switches::kTraceStartup));
       base::debug::TraceLog::GetInstance()->SetEnabled(
-          command_line.GetSwitchValueASCII(switches::kTraceStartup),
+          category_filter,
           base::debug::TraceLog::RECORD_UNTIL_FULL);
     }
+#if !defined(OS_ANDROID)
+    // Android tracing started at the beginning of the method.
+    // Other OSes have to wait till we get here in order for all the memory
+    // management setup to be completed.
+    TRACE_EVENT0("startup", "ContentMainRunnerImpl::Initialize");
+#endif // !OS_ANDROID
 
 #if defined(OS_MACOSX) && !defined(OS_IOS)
     // We need to allocate the IO Ports before the Sandbox is initialized or
-    // the first instance of SystemMonitor is created.
+    // the first instance of PowerMonitor is created.
     // It's important not to allocate the ports for processes which don't
-    // register with the system monitor - see crbug.com/88867.
+    // register with the power monitor - see crbug.com/88867.
     if (process_type.empty() ||
         process_type == switches::kPluginProcess ||
         process_type == switches::kRendererProcess ||
@@ -657,12 +651,12 @@
         process_type == switches::kWorkerProcess ||
         (delegate &&
          delegate->ProcessRegistersWithSystemProcess(process_type))) {
-      base::SystemMonitor::AllocateSystemIOPorts();
+      base::PowerMonitor::AllocateSystemIOPorts();
     }
 
     if (!process_type.empty() &&
         (!delegate || delegate->ShouldSendMachPort(process_type))) {
-      SendTaskPortToParentProcess();
+      MachBroker::ChildSendTaskPortToParent();
     }
 #elif defined(OS_WIN)
     // This must be done early enough since some helper functions like
diff --git a/content/browser/DEPS b/content/browser/DEPS
index 9e0a508..200aada 100644
--- a/content/browser/DEPS
+++ b/content/browser/DEPS
@@ -5,6 +5,7 @@
   "+content/public/browser",
   "+media/audio",  # For audio input for speech input feature.
   "+media/base",  # For Android JNI registration and kDisableEncryptedMedia.
+  "+sql",
   "+ui/webui",
   "+win8/util",
 
diff --git a/content/browser/accessibility/accessibility_tree_formatter.cc b/content/browser/accessibility/accessibility_tree_formatter.cc
index f8b4cc7..84f200a 100644
--- a/content/browser/accessibility/accessibility_tree_formatter.cc
+++ b/content/browser/accessibility/accessibility_tree_formatter.cc
@@ -7,6 +7,7 @@
 #include "base/logging.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/string_util.h"
+#include "base/stringprintf.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/utf_string_conversions.h"
 #include "content/browser/accessibility/browser_accessibility_manager.h"
@@ -18,11 +19,12 @@
 namespace {
 const int kIndentSpaces = 4;
 const char* kSkipString = "@NO_DUMP";
+const char* kChildrenDictAttr = "children";
 }
 
 AccessibilityTreeFormatter::AccessibilityTreeFormatter(
-    BrowserAccessibility* node)
-    : node_(node) {
+    BrowserAccessibility* root)
+    : root_(root) {
   Initialize();
 }
 
@@ -45,33 +47,59 @@
 AccessibilityTreeFormatter::~AccessibilityTreeFormatter() {
 }
 
+scoped_ptr<DictionaryValue>
+AccessibilityTreeFormatter::BuildAccessibilityTree() {
+  scoped_ptr<DictionaryValue> dict(new DictionaryValue);
+  RecursiveBuildAccessibilityTree(*root_, dict.get());
+  return dict.Pass();
+}
+
 void AccessibilityTreeFormatter::FormatAccessibilityTree(
     string16* contents) {
-  RecursiveFormatAccessibilityTree(node_, contents, 0);
+  scoped_ptr<DictionaryValue> dict = BuildAccessibilityTree();
+  RecursiveFormatAccessibilityTree(*(dict.get()), contents);
+}
+
+void AccessibilityTreeFormatter::RecursiveBuildAccessibilityTree(
+    const BrowserAccessibility& node, DictionaryValue* dict) {
+  AddProperties(node, dict);
+  ListValue* children = new ListValue;
+  dict->Set(kChildrenDictAttr, children);
+  for (size_t i = 0; i < node.children().size(); ++i) {
+    BrowserAccessibility* child_node = node.children()[i];
+    DictionaryValue* child_dict = new DictionaryValue;
+    children->Append(child_dict);
+    RecursiveBuildAccessibilityTree(*child_node, child_dict);
+  }
 }
 
 void AccessibilityTreeFormatter::RecursiveFormatAccessibilityTree(
-    BrowserAccessibility* node, string16* contents, int indent) {
-  scoped_array<char> prefix(new char[indent + 1]);
-  for (int i = 0; i < indent; ++i)
-    prefix[i] = ' ';
-  prefix[indent] = '\0';
-
-  string16 line = ToString(node, prefix.get());
+    const DictionaryValue& dict, string16* contents, int depth) {
+  string16 line = ToString(dict, string16(depth * kIndentSpaces, ' '));
   if (line.find(ASCIIToUTF16(kSkipString)) != string16::npos)
     return;
 
   *contents += line;
-  for (size_t i = 0; i < node->children().size(); ++i) {
-    RecursiveFormatAccessibilityTree(node->children()[i], contents,
-                                     indent + kIndentSpaces);
+  const ListValue* children;
+  dict.GetList(kChildrenDictAttr, &children);
+  const DictionaryValue* child_dict;
+  for (size_t i = 0; i < children->GetSize(); i++) {
+    children->GetDictionary(i, &child_dict);
+    RecursiveFormatAccessibilityTree(*child_dict, contents, depth + 1);
   }
 }
 
 #if (!defined(OS_WIN) && !defined(OS_MACOSX))
-string16 AccessibilityTreeFormatter::ToString(BrowserAccessibility* node,
-                                              char* prefix) {
-  return UTF8ToUTF16(prefix) + base::IntToString16(node->renderer_id()) +
+void AccessibilityTreeFormatter::AddProperties(const BrowserAccessibility& node,
+                                               DictionaryValue* dict) {
+  dict->SetInteger("id", node.renderer_id());
+}
+
+string16 AccessibilityTreeFormatter::ToString(const DictionaryValue& node,
+                                              const string16& indent) {
+  int id_value;
+  node.GetInteger("id", &id_value);
+  return indent + base::IntToString16(id_value) +
        ASCIIToUTF16("\n");
 }
 
@@ -80,28 +108,28 @@
 // static
 const base::FilePath::StringType
 AccessibilityTreeFormatter::GetActualFileSuffix() {
-  return FILE_PATH_LITERAL("");
+  return base::FilePath::StringType();
 }
 
 // static
 const base::FilePath::StringType
 AccessibilityTreeFormatter::GetExpectedFileSuffix() {
-  return FILE_PATH_LITERAL("");
+  return base::FilePath::StringType();
 }
 
 // static
 const std::string AccessibilityTreeFormatter::GetAllowEmptyString() {
-  return "";
+  return std::string();
 }
 
 // static
 const std::string AccessibilityTreeFormatter::GetAllowString() {
-  return "";
+  return std::string();
 }
 
 // static
 const std::string AccessibilityTreeFormatter::GetDenyString() {
-  return "";
+  return std::string();
 }
 #endif
 
@@ -127,23 +155,31 @@
   return allow;
 }
 
-void AccessibilityTreeFormatter::StartLine() {
-  line_.clear();
+string16 AccessibilityTreeFormatter::FormatCoordinates(
+    const char* name, const char* x_name, const char* y_name,
+    const DictionaryValue& value) {
+  int x, y;
+  value.GetInteger(x_name, &x);
+  value.GetInteger(y_name, &y);
+  std::string xy_str(base::StringPrintf("%s=(%d, %d)", name, x, y));
+
+  return UTF8ToUTF16(xy_str);
 }
 
-void AccessibilityTreeFormatter::Add(
-    bool include_by_default, const string16& attr) {
+void AccessibilityTreeFormatter::WriteAttribute(
+    bool include_by_default, const std::string& attr, string16* line) {
+  WriteAttribute(include_by_default, UTF8ToUTF16(attr), line);
+}
+
+void AccessibilityTreeFormatter::WriteAttribute(
+    bool include_by_default, const string16& attr, string16* line) {
   if (attr.empty())
     return;
   if (!MatchesFilters(attr, include_by_default))
     return;
-  if (!line_.empty())
-    line_ += ASCIIToUTF16(" ");
-  line_ += attr;
-}
-
-string16 AccessibilityTreeFormatter::FinishLine() {
-  return line_;
+  if (!line->empty())
+    *line += ASCIIToUTF16(" ");
+  *line += attr;
 }
 
 }  // namespace content
diff --git a/content/browser/accessibility/accessibility_tree_formatter.h b/content/browser/accessibility/accessibility_tree_formatter.h
index ca51a68..17beff7 100644
--- a/content/browser/accessibility/accessibility_tree_formatter.h
+++ b/content/browser/accessibility/accessibility_tree_formatter.h
@@ -10,6 +10,7 @@
 #include "base/files/file_path.h"
 #include "base/string16.h"
 #include "base/utf_string_conversions.h"
+#include "base/values.h"
 #include "content/browser/accessibility/browser_accessibility.h"
 #include "content/common/content_export.h"
 
@@ -23,11 +24,33 @@
 // implemented.
 class CONTENT_EXPORT AccessibilityTreeFormatter {
  public:
-  explicit AccessibilityTreeFormatter(BrowserAccessibility* node);
+  explicit AccessibilityTreeFormatter(BrowserAccessibility* root);
   virtual ~AccessibilityTreeFormatter();
 
   static AccessibilityTreeFormatter* Create(RenderViewHost* rvh);
 
+  // Populates the given DictionaryValue with the accessibility tree.
+  // The dictionary contains a key/value pair for each attribute of the node,
+  // plus a "children" attribute containing a list of all child nodes.
+  // {
+  //   "AXName": "node",  /* actual attributes will vary by platform */
+  //   "position": {  /* some attributes may be dictionaries */
+  //     "x": 0,
+  //     "y": 0
+  //   },
+  //   /* ... more attributes of |node| */
+  //   "children": [ {  /* list of children created recursively */
+  //     "AXName": "child node 1",
+  //     /* ... more attributes */
+  //     "children": [ ]
+  //   }, {
+  //     "AXName": "child name 2",
+  //     /* ... more attributes */
+  //     "children": [ ]
+  //   } ]
+  // }
+  scoped_ptr<DictionaryValue> BuildAccessibilityTree();
+
   // Dumps a BrowserAccessibility tree into a string.
   void FormatAccessibilityTree(string16* contents);
 
@@ -76,25 +99,45 @@
   static const std::string GetDenyString();
 
  protected:
-  void RecursiveFormatAccessibilityTree(BrowserAccessibility* node,
+  void RecursiveFormatAccessibilityTree(const BrowserAccessibility& node,
                                         string16* contents,
                                         int indent);
+  void RecursiveBuildAccessibilityTree(const BrowserAccessibility& node,
+                                       DictionaryValue* tree_node);
+  void RecursiveFormatAccessibilityTree(const DictionaryValue& tree_node,
+                                        string16* contents,
+                                        int depth = 0);
+
+  // Overridden by each platform to add the required attributes for each node
+  // into the given dict.
+  void AddProperties(const BrowserAccessibility& node, DictionaryValue* dict);
+
+  string16 FormatCoordinates(const char* name,
+                             const char* x_name,
+                             const char* y_name,
+                             const DictionaryValue& value);
 
   // Returns a platform specific representation of a BrowserAccessibility.
   // Should be zero or more complete lines, each with |prefix| prepended
   // (to indent each line).
-  string16 ToString(BrowserAccessibility* node, char* prefix);
+  string16 ToString(const DictionaryValue& node, const string16& indent);
 
   void Initialize();
 
   bool MatchesFilters(const string16& text, bool default_result) const;
-  void StartLine();
-  void Add(bool include_by_default, const string16& attr);
-  string16 FinishLine();
 
-  BrowserAccessibility* node_;
+  // Writes the given attribute string out to |line| if it matches the filters.
+  void WriteAttribute(bool include_by_default,
+                      const string16& attr,
+                      string16* line);
+  void WriteAttribute(bool include_by_default,
+                      const std::string& attr,
+                      string16* line);
+
+  BrowserAccessibility* root_;
+
+  // Filters used when formatting the accessibility tree as text.
   std::vector<Filter> filters_;
-  string16 line_;
 
   DISALLOW_COPY_AND_ASSIGN(AccessibilityTreeFormatter);
 };
diff --git a/content/browser/accessibility/accessibility_tree_formatter_mac.mm b/content/browser/accessibility/accessibility_tree_formatter_mac.mm
index f5f1964..4e25596 100644
--- a/content/browser/accessibility/accessibility_tree_formatter_mac.mm
+++ b/content/browser/accessibility/accessibility_tree_formatter_mac.mm
@@ -6,69 +6,84 @@
 
 #import <Cocoa/Cocoa.h>
 
+#include "base/basictypes.h"
 #include "base/files/file_path.h"
+#include "base/json/json_writer.h"
+#include "base/stringprintf.h"
+#include "base/strings/sys_string_conversions.h"
 #include "base/utf_string_conversions.h"
 #include "content/browser/accessibility/browser_accessibility_cocoa.h"
 #include "content/browser/accessibility/browser_accessibility_mac.h"
 #include "content/browser/accessibility/browser_accessibility_manager.h"
 
+using base::StringPrintf;
+using base::SysNSStringToUTF8;
+using base::SysNSStringToUTF16;
+using std::string;
+
 namespace content {
 
 namespace {
 
-string16 Format(const char *prefix,
-                id value,
-                const char *suffix) {
-  if (value == nil)
-    return UTF8ToUTF16("");
-  NSString* format_str =
-      [NSString stringWithFormat:@"%s%%@%s", prefix, suffix];
-  NSString* tmp = [NSString stringWithFormat:format_str, value];
-  return UTF8ToUTF16([tmp cStringUsingEncoding:NSUTF8StringEncoding]);
-}
+const char* kPositionDictAttr = "position";
+const char* kXCoordDictAttr = "x";
+const char* kYCoordDictAttr = "y";
+const char* kSizeDictAttr = "size";
+const char* kWidthDictAttr = "width";
+const char* kHeightDictAttr = "height";
+const char* kRangeLocDictAttr = "loc";
+const char* kRangeLenDictAttr = "len";
 
-string16 FormatPosition(BrowserAccessibility* node) {
+scoped_ptr<DictionaryValue> PopulatePosition(const BrowserAccessibility& node) {
+  scoped_ptr<DictionaryValue> position(new DictionaryValue);
   // The NSAccessibility position of an object is in global coordinates and
   // based on the lower-left corner of the object. To make this easier and less
   // confusing, convert it to local window coordinates using the top-left
   // corner when dumping the position.
-  BrowserAccessibility* root = node->manager()->GetRoot();
+  BrowserAccessibility* root = node.manager()->GetRoot();
   BrowserAccessibilityCocoa* cocoa_root = root->ToBrowserAccessibilityCocoa();
   NSPoint root_position = [[cocoa_root position] pointValue];
   NSSize root_size = [[cocoa_root size] sizeValue];
   int root_top = -static_cast<int>(root_position.y + root_size.height);
   int root_left = static_cast<int>(root_position.x);
 
-  BrowserAccessibilityCocoa* cocoa_node = node->ToBrowserAccessibilityCocoa();
+  BrowserAccessibilityCocoa* cocoa_node =
+      const_cast<BrowserAccessibility*>(&node)->ToBrowserAccessibilityCocoa();
   NSPoint node_position = [[cocoa_node position] pointValue];
   NSSize node_size = [[cocoa_node size] sizeValue];
 
-  NSString* position_str =
-      [NSString stringWithFormat:@"position=(%d, %d)",
-                static_cast<int>(node_position.x - root_left),
-                static_cast<int>(
-                    -node_position.y - node_size.height - root_top)];
-  return UTF8ToUTF16([position_str cStringUsingEncoding:NSUTF8StringEncoding]);
+  position->SetInteger(kXCoordDictAttr,
+                       static_cast<int>(node_position.x - root_left));
+  position->SetInteger(kYCoordDictAttr,
+      static_cast<int>(-node_position.y - node_size.height - root_top));
+  return position.Pass();
 }
 
-string16 FormatSize(BrowserAccessibility* node) {
-  BrowserAccessibilityCocoa* cocoa_node = node->ToBrowserAccessibilityCocoa();
+scoped_ptr<DictionaryValue>
+PopulateSize(const BrowserAccessibilityCocoa* cocoa_node) {
+  scoped_ptr<DictionaryValue> size(new DictionaryValue);
   NSSize node_size = [[cocoa_node size] sizeValue];
-  NSString* size_str =
-      [NSString stringWithFormat:@"size=(%d, %d)",
-                static_cast<int>(node_size.width),
-                static_cast<int>(node_size.height)];
-  return UTF8ToUTF16([size_str cStringUsingEncoding:NSUTF8StringEncoding]);
+  size->SetInteger(kHeightDictAttr, static_cast<int>(node_size.height));
+  size->SetInteger(kWidthDictAttr, static_cast<int>(node_size.width));
+  return size.Pass();
 }
 
-}  // namespace
+scoped_ptr<DictionaryValue> PopulateRange(NSRange range) {
+  scoped_ptr<DictionaryValue> rangeDict(new DictionaryValue);
+  rangeDict->SetInteger(kRangeLocDictAttr, static_cast<int>(range.location));
+  rangeDict->SetInteger(kRangeLenDictAttr, static_cast<int>(range.length));
+  return rangeDict.Pass();
+}
 
-void AccessibilityTreeFormatter::Initialize() {}
+// Returns true if |value| is an NSValue containing a NSRange.
+bool IsRangeValue(id value) {
+  if (![value isKindOfClass:[NSValue class]])
+    return false;
+  return 0 == strcmp([value objCType], @encode(NSRange));
+}
 
-string16 AccessibilityTreeFormatter::ToString(BrowserAccessibility* node,
-                                               char* prefix) {
-  StartLine();
-  NSArray* requestedAttributes = [NSArray arrayWithObjects:
+NSArray* BuildAllAttributesArray() {
+  return [NSArray arrayWithObjects:
       NSAccessibilityRoleDescriptionAttribute,
       NSAccessibilityTitleAttribute,
       NSAccessibilityValueAttribute,
@@ -85,51 +100,122 @@
       @"AXARIABusy",
       @"AXARIALive",
       @"AXARIARelevant",
+      NSAccessibilityColumnIndexRangeAttribute,
       NSAccessibilityEnabledAttribute,
       NSAccessibilityFocusedAttribute,
+      NSAccessibilityIndexAttribute,
       @"AXLoaded",
       @"AXLoadingProcess",
       NSAccessibilityNumberOfCharactersAttribute,
       NSAccessibilityOrientationAttribute,
       @"AXRequired",
+      NSAccessibilityRowIndexRangeAttribute,
       NSAccessibilityURLAttribute,
       NSAccessibilityVisibleCharacterRangeAttribute,
       @"AXVisited",
       nil];
+}
 
-  NSArray* defaultAttributes = [NSArray arrayWithObjects:
-      NSAccessibilityTitleAttribute,
-      NSAccessibilityValueAttribute,
-      nil];
+}  // namespace
 
-  BrowserAccessibilityCocoa* cocoa_node = node->ToBrowserAccessibilityCocoa();
+void AccessibilityTreeFormatter::Initialize() {
+}
+
+
+void AccessibilityTreeFormatter::AddProperties(const BrowserAccessibility& node,
+                                               DictionaryValue* dict) {
+  BrowserAccessibilityCocoa* cocoa_node =
+      const_cast<BrowserAccessibility*>(&node)->ToBrowserAccessibilityCocoa();
   NSArray* supportedAttributes = [cocoa_node accessibilityAttributeNames];
 
-  Add(true,
-      Format("", [cocoa_node accessibilityAttributeValue:
-                      NSAccessibilityRoleAttribute],
-             ""));
-  Add(false,
-      Format("subrole=", [cocoa_node accessibilityAttributeValue:
-                              NSAccessibilitySubroleAttribute],
-             ""));
-  for (NSString* requestedAttribute in requestedAttributes) {
+  string role = SysNSStringToUTF8(
+      [cocoa_node accessibilityAttributeValue:NSAccessibilityRoleAttribute]);
+  dict->SetString(SysNSStringToUTF8(NSAccessibilityRoleAttribute), role);
+
+  NSString* subrole =
+      [cocoa_node accessibilityAttributeValue:NSAccessibilitySubroleAttribute];
+  if (subrole != nil) {
+    dict->SetString(SysNSStringToUTF8(NSAccessibilitySubroleAttribute),
+                    SysNSStringToUTF8(subrole));
+  }
+
+  CR_DEFINE_STATIC_LOCAL(NSArray*, all_attributes, (BuildAllAttributesArray()));
+  for (NSString* requestedAttribute in all_attributes) {
     if (![supportedAttributes containsObject:requestedAttribute]) {
       continue;
     }
-    NSString* methodName =
-        [cocoa_node methodNameForAttribute:requestedAttribute];
-    Add([defaultAttributes containsObject:requestedAttribute],
-        Format([[NSString stringWithFormat:@"%@='", methodName]
-                   cStringUsingEncoding:NSUTF8StringEncoding],
-               [cocoa_node accessibilityAttributeValue:
-                    requestedAttribute],
-               "'"));
+    id value = [cocoa_node accessibilityAttributeValue:requestedAttribute];
+    if (IsRangeValue(value)) {
+      dict->Set(
+          SysNSStringToUTF8(requestedAttribute),
+          PopulateRange([value rangeValue]).release());
+    } else if (value != nil) {
+      dict->SetString(
+          SysNSStringToUTF8(requestedAttribute),
+          SysNSStringToUTF16([NSString stringWithFormat:@"%@", value]));
+    }
   }
-  Add(false, FormatPosition(node));
-  Add(false, FormatSize(node));
+  dict->Set(kPositionDictAttr, PopulatePosition(node).release());
+  dict->Set(kSizeDictAttr, PopulateSize(cocoa_node).release());
+}
 
-  return ASCIIToUTF16(prefix) + FinishLine() + ASCIIToUTF16("\n");
+string16 AccessibilityTreeFormatter::ToString(const DictionaryValue& dict,
+                                              const string16& indent) {
+  string16 line;
+  NSArray* defaultAttributes =
+      [NSArray arrayWithObjects:NSAccessibilityTitleAttribute,
+                                NSAccessibilityValueAttribute,
+                                nil];
+  string s_value;
+  dict.GetString(SysNSStringToUTF8(NSAccessibilityRoleAttribute), &s_value);
+  WriteAttribute(true, UTF8ToUTF16(s_value), &line);
+
+  string subroleAttribute = SysNSStringToUTF8(NSAccessibilitySubroleAttribute);
+  if (dict.GetString(subroleAttribute, &s_value)) {
+    WriteAttribute(false,
+                   StringPrintf("%s=%s",
+                                subroleAttribute.c_str(), s_value.c_str()),
+                   &line);
+  }
+
+  CR_DEFINE_STATIC_LOCAL(NSArray*, all_attributes, (BuildAllAttributesArray()));
+  for (NSString* requestedAttribute in all_attributes) {
+    string requestedAttributeUTF8 = SysNSStringToUTF8(requestedAttribute);
+    const DictionaryValue* d_value;
+    if (dict.GetDictionary(requestedAttributeUTF8, &d_value)) {
+      std::string json_value;
+      base::JSONWriter::Write(d_value, &json_value);
+      WriteAttribute(
+          [defaultAttributes containsObject:requestedAttribute],
+          StringPrintf("%s=%s",
+                       requestedAttributeUTF8.c_str(),
+                       json_value.c_str()),
+          &line);
+    }
+    if (!dict.GetString(requestedAttributeUTF8, &s_value))
+      continue;
+    WriteAttribute([defaultAttributes containsObject:requestedAttribute],
+                   StringPrintf("%s='%s'",
+                                requestedAttributeUTF8.c_str(),
+                                s_value.c_str()),
+                   &line);
+  }
+  const DictionaryValue* d_value = NULL;
+  if (dict.GetDictionary(kPositionDictAttr, &d_value)) {
+    WriteAttribute(false,
+                   FormatCoordinates(kPositionDictAttr,
+                                     kXCoordDictAttr, kYCoordDictAttr,
+                                     *d_value),
+                   &line);
+  }
+  if (dict.GetDictionary(kSizeDictAttr, &d_value)) {
+    WriteAttribute(false,
+                   FormatCoordinates(kSizeDictAttr,
+                                     kWidthDictAttr, kHeightDictAttr, *d_value),
+                   &line);
+  }
+
+  return indent + line + ASCIIToUTF16("\n");
 }
 
 // static
@@ -145,17 +231,17 @@
 }
 
 // static
-const std::string AccessibilityTreeFormatter::GetAllowEmptyString() {
+const string AccessibilityTreeFormatter::GetAllowEmptyString() {
   return "@MAC-ALLOW-EMPTY:";
 }
 
 // static
-const std::string AccessibilityTreeFormatter::GetAllowString() {
+const string AccessibilityTreeFormatter::GetAllowString() {
   return "@MAC-ALLOW:";
 }
 
 // static
-const std::string AccessibilityTreeFormatter::GetDenyString() {
+const string AccessibilityTreeFormatter::GetDenyString() {
   return "@MAC-DENY:";
 }
 
diff --git a/content/browser/accessibility/accessibility_tree_formatter_utils_win.cc b/content/browser/accessibility/accessibility_tree_formatter_utils_win.cc
index 5e57954..334c8cf 100644
--- a/content/browser/accessibility/accessibility_tree_formatter_utils_win.cc
+++ b/content/browser/accessibility/accessibility_tree_formatter_utils_win.cc
@@ -183,6 +183,7 @@
   IA_STATE_MAP(MIXED)
   IA_STATE_MAP(MOVEABLE)
   IA_STATE_MAP(MULTISELECTABLE)
+  IA_STATE_MAP(OFFSCREEN)
   IA_STATE_MAP(PRESSED)
   IA_STATE_MAP(PROTECTED)
   IA_STATE_MAP(READONLY)
@@ -193,10 +194,6 @@
   IA_STATE_MAP(TRAVERSED)
   IA_STATE_MAP(UNAVAILABLE)
 
-  // Untested states include those that would be repeated on nearly every node,
-  // or would vary based on window size.
-  // IA_STATE_MAP(OFFSCREEN) // Untested.
-
   // IAccessible2 states.
   IA2_STATE_MAP(IA2_STATE_ACTIVE)
   IA2_STATE_MAP(IA2_STATE_ARMED)
diff --git a/content/browser/accessibility/accessibility_tree_formatter_win.cc b/content/browser/accessibility/accessibility_tree_formatter_win.cc
index 389c0e5..90bef99 100644
--- a/content/browser/accessibility/accessibility_tree_formatter_win.cc
+++ b/content/browser/accessibility/accessibility_tree_formatter_win.cc
@@ -19,144 +19,274 @@
 #include "third_party/iaccessible2/ia2_api_all.h"
 #include "ui/base/win/atl_module.h"
 
+using base::StringPrintf;
+
 namespace content {
 
+const char* ALL_ATTRIBUTES[] = {
+    "name",
+    "value",
+    "states",
+    "attributes",
+    "role_name",
+    "currentValue",
+    "minimumValue",
+    "maximumValue",
+    "description",
+    "default_action",
+    "keyboard_shortcut",
+    "location",
+    "size",
+    "index_in_parent",
+    "n_relations",
+    "group_level",
+    "similar_items_in_group",
+    "position_in_group",
+    "table_rows",
+    "table_columns",
+    "row_index",
+    "column_index",
+    "n_characters",
+    "caret_offset",
+    "n_selections",
+    "selection_start",
+    "selection_end"
+};
+
 void AccessibilityTreeFormatter::Initialize() {
   ui::win::CreateATLModuleIfNeeded();
 }
 
-string16 AccessibilityTreeFormatter::ToString(
-    BrowserAccessibility* node, char* prefix) {
-  BrowserAccessibilityWin* acc_obj = node->ToBrowserAccessibilityWin();
+void AccessibilityTreeFormatter::AddProperties(
+    const BrowserAccessibility& node, DictionaryValue* dict) {
+  BrowserAccessibilityWin* acc_obj =
+      const_cast<BrowserAccessibility*>(&node)->ToBrowserAccessibilityWin();
 
-  // Get the computed name.
   VARIANT variant_self;
   variant_self.vt = VT_I4;
   variant_self.lVal = CHILDID_SELF;
+
+  dict->SetString("role", IAccessible2RoleToString(acc_obj->ia2_role()));
+
   CComBSTR msaa_variant;
   HRESULT hresult = acc_obj->get_accName(variant_self, &msaa_variant);
-  string16 name;
-  if (S_OK == hresult)
-    name = msaa_variant.m_str;
-
+  if (hresult == S_OK)
+    dict->SetString("name", msaa_variant.m_str);
   hresult = acc_obj->get_accValue(variant_self, &msaa_variant);
-  string16 value;
-  if (S_OK == hresult)
-    value = msaa_variant.m_str;
+  if (hresult == S_OK)
+    dict->SetString("value", msaa_variant.m_str);
 
-  hresult = acc_obj->get_accDescription(variant_self, &msaa_variant);
-  string16 description;
-  if (S_OK == hresult)
-    description = msaa_variant.m_str;
-
-  hresult = acc_obj->get_accHelp(variant_self, &msaa_variant);
-  string16 help;
-  if (S_OK == hresult)
-    help = msaa_variant.m_str;
-
-  hresult = acc_obj->get_accDefaultAction(variant_self, &msaa_variant);
-  string16 default_action;
-  if (S_OK == hresult)
-    default_action = msaa_variant.m_str;
-
-  hresult = acc_obj->get_accKeyboardShortcut(variant_self, &msaa_variant);
-  string16 keyboard_shortcut;
-  if (S_OK == hresult)
-    keyboard_shortcut = msaa_variant.m_str;
-
-  // Get state strings.
   std::vector<string16> state_strings;
-  IAccessibleStateToStringVector(acc_obj->ia_state(), &state_strings);
+  int32 ia_state = acc_obj->ia_state();
+
+  // Avoid flakiness: these states depend on whether the window is focused
+  // and the position of the mouse cursor.
+  ia_state &= ~STATE_SYSTEM_HOTTRACKED;
+  ia_state &= ~STATE_SYSTEM_OFFSCREEN;
+
+  IAccessibleStateToStringVector(ia_state, &state_strings);
   IAccessible2StateToStringVector(acc_obj->ia2_state(), &state_strings);
-
-  // Get the attributes.
-  const std::vector<string16>& ia2_attributes = acc_obj->ia2_attributes();
-
-  // Build the line.
-  StartLine();
-  Add(true, IAccessible2RoleToString(acc_obj->ia2_role()));
-  Add(true, L"name='" + name + L"'");
-  Add(false, L"value='" + value + L"'");
+  ListValue* states = new ListValue;
   for (std::vector<string16>::const_iterator it = state_strings.begin();
        it != state_strings.end();
        ++it) {
-    Add(false, *it);
+    states->AppendString(UTF16ToUTF8(*it));
   }
+  dict->Set("states", states);
+
+  const std::vector<string16>& ia2_attributes = acc_obj->ia2_attributes();
+  ListValue* attributes = new ListValue;
   for (std::vector<string16>::const_iterator it = ia2_attributes.begin();
        it != ia2_attributes.end();
        ++it) {
-    Add(false, *it);
+    attributes->AppendString(UTF16ToUTF8(*it));
   }
-  Add(false, L"role_name='" + acc_obj->role_name() + L"'");
+  dict->Set("attributes", attributes);
+
+  dict->SetString("role_name", acc_obj->role_name());
+
   VARIANT currentValue;
   if (acc_obj->get_currentValue(&currentValue) == S_OK)
-    Add(false, base::StringPrintf(L"currentValue=%.2f", V_R8(&currentValue)));
+    dict->SetDouble("currentValue", V_R8(&currentValue));
+
   VARIANT minimumValue;
   if (acc_obj->get_minimumValue(&minimumValue) == S_OK)
-    Add(false, base::StringPrintf(L"minimumValue=%.2f", V_R8(&minimumValue)));
+    dict->SetDouble("minimumValue", V_R8(&minimumValue));
+
   VARIANT maximumValue;
   if (acc_obj->get_maximumValue(&maximumValue) == S_OK)
-    Add(false, base::StringPrintf(L"maximumValue=%.2f", V_R8(&maximumValue)));
-  Add(false, L"description='" + description + L"'");
-  Add(false, L"default_action='" + default_action + L"'");
-  Add(false, L"keyboard_shortcut='" + keyboard_shortcut + L"'");
-  BrowserAccessibility* root = node->manager()->GetRoot();
+    dict->SetDouble("maximumValue", V_R8(&maximumValue));
+
+  hresult = acc_obj->get_accDescription(variant_self, &msaa_variant);
+  if (hresult == S_OK)
+    dict->SetString("description", msaa_variant.m_str);
+
+  hresult = acc_obj->get_accDefaultAction(variant_self, &msaa_variant);
+  if (hresult == S_OK)
+    dict->SetString("default_action", msaa_variant.m_str);
+
+  hresult = acc_obj->get_accKeyboardShortcut(variant_self, &msaa_variant);
+  if (hresult == S_OK)
+    dict->SetString("keyboard_shortcut", msaa_variant.m_str);
+
+  hresult = acc_obj->get_accHelp(variant_self, &msaa_variant);
+  if (S_OK == hresult)
+    dict->SetString("help", msaa_variant.m_str);
+
+  BrowserAccessibility* root = node.manager()->GetRoot();
   LONG left, top, width, height;
   LONG root_left, root_top, root_width, root_height;
-  if (S_FALSE != acc_obj->accLocation(
-          &left, &top, &width, &height, variant_self) &&
-      S_FALSE != root->ToBrowserAccessibilityWin()->accLocation(
-          &root_left, &root_top, &root_width, &root_height, variant_self)) {
-    Add(false, base::StringPrintf(L"location=(%d, %d)",
-            left - root_left, top - root_top));
-    Add(false, base::StringPrintf(L"size=(%d, %d)", width, height));
+  if (acc_obj->accLocation(&left, &top, &width, &height, variant_self)
+      != S_FALSE
+      && root->ToBrowserAccessibilityWin()->accLocation(
+          &root_left, &root_top, &root_width, &root_height, variant_self)
+      != S_FALSE) {
+    DictionaryValue* location = new DictionaryValue;
+    location->SetInteger("x", left - root_left);
+    location->SetInteger("y", top - root_top);
+    dict->Set("location", location);
+
+    DictionaryValue* size = new DictionaryValue;
+    size->SetInteger("width", width);
+    size->SetInteger("height", height);
+    dict->Set("size", size);
   }
+
   LONG index_in_parent;
   if (acc_obj->get_indexInParent(&index_in_parent) == S_OK)
-    Add(false, base::StringPrintf(L"index_in_parent=%d", index_in_parent));
+    dict->SetInteger("index_in_parent", index_in_parent);
+
   LONG n_relations;
   if (acc_obj->get_nRelations(&n_relations) == S_OK)
-    Add(false, base::StringPrintf(L"n_relations=%d", n_relations));
+    dict->SetInteger("n_relations", n_relations);
+
   LONG group_level, similar_items_in_group, position_in_group;
   if (acc_obj->get_groupPosition(&group_level,
                                  &similar_items_in_group,
                                  &position_in_group) == S_OK) {
-    Add(false, base::StringPrintf(L"group_level=%d", group_level));
-    Add(false, base::StringPrintf(L"similar_items_in_group=%d",
-                            similar_items_in_group));
-    Add(false, base::StringPrintf(L"position_in_group=%d", position_in_group));
+    dict->SetInteger("group_level", group_level);
+    dict->SetInteger("similar_items_in_group", similar_items_in_group);
+    dict->SetInteger("position_in_group", position_in_group);
   }
   LONG table_rows;
   if (acc_obj->get_nRows(&table_rows) == S_OK)
-    Add(false, base::StringPrintf(L"table_rows=%d", table_rows));
+    dict->SetInteger("table_rows", table_rows);
   LONG table_columns;
   if (acc_obj->get_nRows(&table_columns) == S_OK)
-    Add(false, base::StringPrintf(L"table_columns=%d", table_columns));
+    dict->SetInteger("table_columns", table_columns);
   LONG row_index;
   if (acc_obj->get_rowIndex(&row_index) == S_OK)
-    Add(false, base::StringPrintf(L"row_index=%d", row_index));
+    dict->SetInteger("row_index", row_index);
   LONG column_index;
   if (acc_obj->get_columnIndex(&column_index) == S_OK)
-    Add(false, base::StringPrintf(L"column_index=%d", column_index));
+    dict->SetInteger("column_index", column_index);
   LONG n_characters;
   if (acc_obj->get_nCharacters(&n_characters) == S_OK)
-    Add(false, base::StringPrintf(L"n_characters=%d", n_characters));
+    dict->SetInteger("n_characters", n_characters);
   LONG caret_offset;
   if (acc_obj->get_caretOffset(&caret_offset) == S_OK)
-    Add(false, base::StringPrintf(L"caret_offset=%d", caret_offset));
+    dict->SetInteger("caret_offset", caret_offset);
   LONG n_selections;
   if (acc_obj->get_nSelections(&n_selections) == S_OK) {
-    Add(false, base::StringPrintf(L"n_selections=%d", n_selections));
+    dict->SetInteger("n_selections", n_selections);
     if (n_selections > 0) {
       LONG start, end;
       if (acc_obj->get_selection(0, &start, &end) == S_OK) {
-        Add(false, base::StringPrintf(L"selection_start=%d", start));
-        Add(false, base::StringPrintf(L"selection_end=%d", end));
+        dict->SetInteger("selection_start", start);
+        dict->SetInteger("selection_end", end);
       }
     }
   }
+}
 
-  return UTF8ToUTF16(prefix) + FinishLine() + ASCIIToUTF16("\n");
+string16 AccessibilityTreeFormatter::ToString(const DictionaryValue& dict,
+                                              const string16& indent) {
+  string16 line;
+
+  string16 role_value;
+  dict.GetString("role", &role_value);
+  WriteAttribute(true, UTF16ToUTF8(role_value), &line);
+
+  string16 name_value;
+  dict.GetString("name", &name_value);
+  WriteAttribute(true, base::StringPrintf(L"name='%ls'", name_value.c_str()),
+                 &line);
+
+  for (int i = 0; i < arraysize(ALL_ATTRIBUTES); i++) {
+    const char* attribute_name = ALL_ATTRIBUTES[i];
+    const Value* value;
+    if (!dict.Get(attribute_name, &value))
+      continue;
+
+    switch (value->GetType()) {
+      case Value::TYPE_STRING: {
+        string16 string_value;
+        value->GetAsString(&string_value);
+        WriteAttribute(false,
+                       StringPrintf(L"%ls='%ls'",
+                                    UTF8ToUTF16(attribute_name).c_str(),
+                                    string_value.c_str()),
+                       &line);
+        break;
+      }
+      case Value::TYPE_INTEGER: {
+        int int_value;
+        value->GetAsInteger(&int_value);
+        WriteAttribute(false,
+                       base::StringPrintf(L"%ls=%d",
+                                          UTF8ToUTF16(attribute_name).c_str(),
+                                          int_value),
+                       &line);
+        break;
+      }
+      case Value::TYPE_DOUBLE: {
+        double double_value;
+        value->GetAsDouble(&double_value);
+        WriteAttribute(false,
+                       base::StringPrintf(L"%ls=%.2f",
+                                          UTF8ToUTF16(attribute_name).c_str(),
+                                          double_value),
+                       &line);
+        break;
+      }
+      case Value::TYPE_LIST: {
+        // Currently all list values are string and are written without
+        // attribute names.
+        const ListValue* list_value;
+        value->GetAsList(&list_value);
+        for (ListValue::const_iterator it = list_value->begin();
+             it != list_value->end();
+             ++it) {
+          string16 string_value;
+          if ((*it)->GetAsString(&string_value))
+            WriteAttribute(false, string_value, &line);
+        }
+        break;
+      }
+      case Value::TYPE_DICTIONARY: {
+        // Currently all dictionary values are coordinates.
+        // Revisit this if that changes.
+        const DictionaryValue* dict_value;
+        value->GetAsDictionary(&dict_value);
+        if (strcmp(attribute_name, "size") == 0) {
+          WriteAttribute(false,
+                         FormatCoordinates("size", "width", "height",
+                                           *dict_value),
+                         &line);
+        } else if (strcmp(attribute_name, "location") == 0) {
+          WriteAttribute(false,
+                         FormatCoordinates("location", "x", "y", *dict_value),
+                         &line);
+        }
+        break;
+      }
+      default:
+        NOTREACHED();
+        break;
+    }
+  }
+
+  return indent + line + ASCIIToUTF16("\n");
 }
 
 // static
diff --git a/content/browser/accessibility/accessibility_ui.cc b/content/browser/accessibility/accessibility_ui.cc
index 88bc566..dfc7343 100644
--- a/content/browser/accessibility/accessibility_ui.cc
+++ b/content/browser/accessibility/accessibility_ui.cc
@@ -121,7 +121,7 @@
   scoped_ptr<DictionaryValue> data(new DictionaryValue());
   data->Set("list", rvh_list.release());
   scoped_ptr<FundamentalValue> a11y_mode(new FundamentalValue(
-      BrowserAccessibilityStateImpl::GetInstance()->GetAccessibilityMode()));
+      BrowserAccessibilityStateImpl::GetInstance()->accessibility_mode()));
   data->Set("global_a11y_mode", a11y_mode.release());
 
   std::string json_string;
@@ -146,7 +146,7 @@
   : WebUIController(web_ui) {
   // Set up the chrome://accessibility source.
   WebUIDataSource* html_source =
-      WebUIDataSource::Create(chrome::kChromeUIAccessibilityHost);
+      WebUIDataSource::Create(kChromeUIAccessibilityHost);
   html_source->SetUseJsonJSFormatV2();
 
   web_ui->RegisterMessageCallback(
@@ -205,32 +205,11 @@
 void AccessibilityUI::ToggleGlobalAccessibility(const base::ListValue* args) {
   BrowserAccessibilityStateImpl* state =
       BrowserAccessibilityStateImpl::GetInstance();
-  AccessibilityMode mode = state->GetAccessibilityMode();
+  AccessibilityMode mode = state->accessibility_mode();
   AccessibilityMode new_mode = (mode == AccessibilityModeOff
                                 ? AccessibilityModeComplete
                                 : AccessibilityModeOff);
   state->SetAccessibilityMode(new_mode);
-  for (RenderProcessHost::iterator it(RenderProcessHost::AllHostsIterator());
-       !it.IsAtEnd(); it.Advance()) {
-    RenderProcessHost* render_process_host = it.GetCurrentValue();
-    DCHECK(render_process_host);
-
-    // Ignore processes that don't have a connection, such as crashed tabs.
-    if (!render_process_host->HasConnection())
-      continue;
-
-    RenderProcessHost::RenderWidgetHostsIterator rwit(
-        render_process_host->GetRenderWidgetHostsIterator());
-    for (; !rwit.IsAtEnd(); rwit.Advance()) {
-      RenderWidgetHost* rwh = const_cast<RenderWidgetHost*>(
-          rwit.GetCurrentValue());
-      DCHECK(rwh);
-      if (!rwh || !rwh->IsRenderView())
-        continue;
-      RenderWidgetHostImpl* rwhi = RenderWidgetHostImpl::From(rwh);
-      rwhi->SetAccessibilityMode(new_mode);
-    }
-  }
 }
 
 void AccessibilityUI::RequestAccessibilityTree(const base::ListValue* args) {
diff --git a/content/browser/accessibility/accessibility_win_browsertest.cc b/content/browser/accessibility/accessibility_win_browsertest.cc
index 1158d7a..b099af9 100644
--- a/content/browser/accessibility/accessibility_win_browsertest.cc
+++ b/content/browser/accessibility/accessibility_win_browsertest.cc
@@ -2,13 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include <atlbase.h>
 #include <vector>
 
 #include "base/memory/scoped_ptr.h"
-#include "base/stringprintf.h"
 #include "base/utf_string_conversions.h"
+#include "base/win/scoped_bstr.h"
 #include "base/win/scoped_comptr.h"
+#include "base/win/scoped_variant.h"
 #include "content/browser/accessibility/accessibility_tree_formatter_utils_win.h"
 #include "content/browser/renderer_host/render_view_host_impl.h"
 #include "content/public/browser/notification_service.h"
@@ -24,11 +24,6 @@
 #include "third_party/iaccessible2/ia2_api_all.h"
 #include "third_party/isimpledom/ISimpleDOMNode.h"
 
-using std::auto_ptr;
-using std::string;
-using std::vector;
-using std::wstring;
-
 // TODO(dmazzoni): Disabled accessibility tests on Win64. crbug.com/179717
 #if defined(ARCH_CPU_X86_64)
 #define MAYBE(x) DISABLED_##x
@@ -40,105 +35,31 @@
 
 namespace {
 
-class AccessibilityWinBrowserTest : public ContentBrowserTest {
- public:
-  AccessibilityWinBrowserTest() {}
 
- protected:
-  void LoadInitialAccessibilityTreeFromHtml(string html);
-  IAccessible* GetRendererAccessible();
-  void ExecuteScript(wstring script);
-};
+// Helpers --------------------------------------------------------------------
 
-class AccessibleChecker {
- public:
-  AccessibleChecker(
-      wstring expected_name,
-      int32 expected_role,
-      wstring expected_value);
-  AccessibleChecker(
-      wstring expected_name,
-      wstring expected_role,
-      int32 expected_ia2_role,
-      wstring expected_value);
-  AccessibleChecker(
-      wstring expected_name,
-      int32 expected_role,
-      int32 expected_ia2_role,
-      wstring expected_value);
-
-  // Append an AccessibleChecker that verifies accessibility information for
-  // a child IAccessible. Order is important.
-  void AppendExpectedChild(AccessibleChecker* expected_child);
-
-  // Check that the name and role of the given IAccessible instance and its
-  // descendants match the expected names and roles that this object was
-  // initialized with.
-  void CheckAccessible(IAccessible* accessible);
-
-  // Set the expected value for this AccessibleChecker.
-  void SetExpectedValue(wstring expected_value);
-
-  // Set the expected state for this AccessibleChecker.
-  void SetExpectedState(LONG expected_state);
-
- private:
-  void CheckAccessibleName(IAccessible* accessible);
-  void CheckAccessibleRole(IAccessible* accessible);
-  void CheckIA2Role(IAccessible* accessible);
-  void CheckAccessibleValue(IAccessible* accessible);
-  void CheckAccessibleState(IAccessible* accessible);
-  void CheckAccessibleChildren(IAccessible* accessible);
-  string16 RoleVariantToString(VARIANT* role_variant);
-
- private:
-  typedef vector<AccessibleChecker*> AccessibleCheckerVector;
-
-  // Expected accessible name. Checked against IAccessible::get_accName.
-  wstring name_;
-
-  // Expected accessible role. Checked against IAccessible::get_accRole.
-  CComVariant role_;
-
-  // Expected IAccessible2 role. Checked against IAccessible2::role.
-  int32 ia2_role_;
-
-  // Expected accessible value. Checked against IAccessible::get_accValue.
-  wstring value_;
-
-  // Expected accessible state. Checked against IAccessible::get_accState.
-  LONG state_;
-
-  // Expected accessible children. Checked using IAccessible::get_accChildCount
-  // and ::AccessibleChildren.
-  AccessibleCheckerVector children_;
-};
-
-VARIANT CreateI4Variant(LONG value) {
-  VARIANT variant = {0};
-
-  V_VT(&variant) = VT_I4;
-  V_I4(&variant) = value;
-
-  return variant;
-}
-
-IAccessible* GetAccessibleFromResultVariant(IAccessible* parent, VARIANT *var) {
+base::win::ScopedComPtr<IAccessible> GetAccessibleFromResultVariant(
+    IAccessible* parent,
+    VARIANT* var) {
+  base::win::ScopedComPtr<IAccessible> ptr;
   switch (V_VT(var)) {
-    case VT_DISPATCH:
-      return CComQIPtr<IAccessible>(V_DISPATCH(var)).Detach();
+    case VT_DISPATCH: {
+      IDispatch* dispatch = V_DISPATCH(var);
+      if (dispatch)
+        ptr.QueryFrom(dispatch);
       break;
+    }
 
     case VT_I4: {
-      CComPtr<IDispatch> dispatch;
-      HRESULT hr = parent->get_accChild(CreateI4Variant(V_I4(var)), &dispatch);
+      base::win::ScopedComPtr<IDispatch> dispatch;
+      HRESULT hr = parent->get_accChild(*var, dispatch.Receive());
       EXPECT_TRUE(SUCCEEDED(hr));
-      return CComQIPtr<IAccessible>(dispatch).Detach();
+      if (dispatch)
+        dispatch.QueryInterface(ptr.Receive());
       break;
     }
   }
-
-  return NULL;
+  return ptr;
 }
 
 HRESULT QueryIAccessible2(IAccessible* accessible, IAccessible2** accessible2) {
@@ -146,36 +67,33 @@
   // IAccessible fails.
   base::win::ScopedComPtr<IServiceProvider> service_provider;
   HRESULT hr = accessible->QueryInterface(service_provider.Receive());
-  if (FAILED(hr))
-    return hr;
-
-  hr = service_provider->QueryService(IID_IAccessible2, accessible2);
-  return hr;
+  return SUCCEEDED(hr) ?
+      service_provider->QueryService(IID_IAccessible2, accessible2) : hr;
 }
 
 // Recursively search through all of the descendants reachable from an
 // IAccessible node and return true if we find one with the given role
 // and name.
-void RecursiveFindNodeInAccessibilityTree(
-    IAccessible* node,
-    int32 expected_role,
-    const wstring& expected_name,
-    int32 depth,
-    bool* found) {
-  CComBSTR name_bstr;
-  node->get_accName(CreateI4Variant(CHILDID_SELF), &name_bstr);
-  wstring name(name_bstr.m_str, SysStringLen(name_bstr));
-  VARIANT role = {0};
-  node->get_accRole(CreateI4Variant(CHILDID_SELF), &role);
+void RecursiveFindNodeInAccessibilityTree(IAccessible* node,
+                                          int32 expected_role,
+                                          const std::wstring& expected_name,
+                                          int32 depth,
+                                          bool* found) {
+  base::win::ScopedBstr name_bstr;
+  base::win::ScopedVariant childid_self(CHILDID_SELF);
+  node->get_accName(childid_self, name_bstr.Receive());
+  std::wstring name(name_bstr, name_bstr.Length());
+  base::win::ScopedVariant role;
+  node->get_accRole(childid_self, role.Receive());
+  ASSERT_EQ(VT_I4, role.type());
 
   // Print the accessibility tree as we go, because if this test fails
   // on the bots, this is really helpful in figuring out why.
-  for (int i = 0; i < depth; i++) {
+  for (int i = 0; i < depth; i++)
     printf("  ");
-  }
-  printf("role=%d name=%s\n", role.lVal, WideToUTF8(name).c_str());
+  printf("role=%d name=%s\n", V_I4(&role), WideToUTF8(name).c_str());
 
-  if (expected_role == role.lVal && expected_name == name) {
+  if (expected_role == V_I4(&role) && expected_name == name) {
     *found = true;
     return;
   }
@@ -184,7 +102,7 @@
   HRESULT hr = node->get_accChildCount(&child_count);
   ASSERT_EQ(S_OK, hr);
 
-  scoped_array<VARIANT> child_array(new VARIANT[child_count]);
+  scoped_ptr<VARIANT[]> child_array(new VARIANT[child_count]);
   LONG obtained_count = 0;
   hr = AccessibleChildren(
       node, 0, child_count, child_array.get(), &obtained_count);
@@ -194,7 +112,7 @@
   for (int index = 0; index < obtained_count; index++) {
     base::win::ScopedComPtr<IAccessible> child_accessible(
         GetAccessibleFromResultVariant(node, &child_array.get()[index]));
-    if (child_accessible.get()) {
+    if (child_accessible) {
       RecursiveFindNodeInAccessibilityTree(
           child_accessible.get(), expected_role, expected_name, depth + 1,
           found);
@@ -204,10 +122,33 @@
   }
 }
 
+
+// AccessibilityWinBrowserTest ------------------------------------------------
+
+class AccessibilityWinBrowserTest : public ContentBrowserTest {
+ public:
+  AccessibilityWinBrowserTest();
+  virtual ~AccessibilityWinBrowserTest();
+
+ protected:
+  void LoadInitialAccessibilityTreeFromHtml(const std::string& html);
+  IAccessible* GetRendererAccessible();
+  void ExecuteScript(const std::wstring& script);
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(AccessibilityWinBrowserTest);
+};
+
+AccessibilityWinBrowserTest::AccessibilityWinBrowserTest() {
+}
+
+AccessibilityWinBrowserTest::~AccessibilityWinBrowserTest() {
+}
+
 void AccessibilityWinBrowserTest::LoadInitialAccessibilityTreeFromHtml(
-    string html) {
+    const std::string& html) {
   // Load the html using a data url and wait for the navigation to finish.
-  GURL html_data_url(string("data:text/html,") + html);
+  GURL html_data_url("data:text/html," + html);
   NavigateToURL(shell(), html_data_url);
 
   // At this point, renderer accessibility is off and the page has completed
@@ -229,8 +170,7 @@
 
 // Retrieve the MSAA client accessibility object for the Render Widget Host View
 // of the selected tab.
-IAccessible*
-AccessibilityWinBrowserTest::GetRendererAccessible() {
+IAccessible* AccessibilityWinBrowserTest::GetRendererAccessible() {
   HWND hwnd_render_widget_host_view =
       shell()->web_contents()->GetRenderWidgetHostView()->GetNativeView();
 
@@ -251,41 +191,106 @@
   return accessible;
 }
 
-void AccessibilityWinBrowserTest::ExecuteScript(wstring script) {
-  shell()->web_contents()->GetRenderViewHost()->
-      ExecuteJavascriptInWebFrame(L"", script);
+void AccessibilityWinBrowserTest::ExecuteScript(const std::wstring& script) {
+  shell()->web_contents()->GetRenderViewHost()->ExecuteJavascriptInWebFrame(
+      std::wstring(), script);
 }
 
-// This constructor can be used if IA2 role will be the same as MSAA role
-AccessibleChecker::AccessibleChecker(
-    wstring expected_name, int32 expected_role, wstring expected_value) :
-    name_(expected_name),
-    role_(expected_role),
-    ia2_role_(expected_role),
-    value_(expected_value),
-    state_(-1) {
+
+// AccessibleChecker ----------------------------------------------------------
+
+class AccessibleChecker {
+ public:
+  // This constructor can be used if the IA2 role will be the same as the MSAA
+  // role.
+  AccessibleChecker(const std::wstring& expected_name,
+                    int32 expected_role,
+                    const std::wstring& expected_value);
+  AccessibleChecker(const std::wstring& expected_name,
+                    int32 expected_role,
+                    int32 expected_ia2_role,
+                    const std::wstring& expected_value);
+  AccessibleChecker(const std::wstring& expected_name,
+                    const std::wstring& expected_role,
+                    int32 expected_ia2_role,
+                    const std::wstring& expected_value);
+
+  // Append an AccessibleChecker that verifies accessibility information for
+  // a child IAccessible. Order is important.
+  void AppendExpectedChild(AccessibleChecker* expected_child);
+
+  // Check that the name and role of the given IAccessible instance and its
+  // descendants match the expected names and roles that this object was
+  // initialized with.
+  void CheckAccessible(IAccessible* accessible);
+
+  // Set the expected value for this AccessibleChecker.
+  void SetExpectedValue(const std::wstring& expected_value);
+
+  // Set the expected state for this AccessibleChecker.
+  void SetExpectedState(LONG expected_state);
+
+ private:
+  typedef std::vector<AccessibleChecker*> AccessibleCheckerVector;
+
+  void CheckAccessibleName(IAccessible* accessible);
+  void CheckAccessibleRole(IAccessible* accessible);
+  void CheckIA2Role(IAccessible* accessible);
+  void CheckAccessibleValue(IAccessible* accessible);
+  void CheckAccessibleState(IAccessible* accessible);
+  void CheckAccessibleChildren(IAccessible* accessible);
+  string16 RoleVariantToString(const base::win::ScopedVariant& role);
+
+  // Expected accessible name. Checked against IAccessible::get_accName.
+  std::wstring name_;
+
+  // Expected accessible role. Checked against IAccessible::get_accRole.
+  base::win::ScopedVariant role_;
+
+  // Expected IAccessible2 role. Checked against IAccessible2::role.
+  int32 ia2_role_;
+
+  // Expected accessible value. Checked against IAccessible::get_accValue.
+  std::wstring value_;
+
+  // Expected accessible state. Checked against IAccessible::get_accState.
+  LONG state_;
+
+  // Expected accessible children. Checked using IAccessible::get_accChildCount
+  // and ::AccessibleChildren.
+  AccessibleCheckerVector children_;
+};
+
+AccessibleChecker::AccessibleChecker(const std::wstring& expected_name,
+                                     int32 expected_role,
+                                     const std::wstring& expected_value)
+    : name_(expected_name),
+      role_(expected_role),
+      ia2_role_(expected_role),
+      value_(expected_value),
+      state_(-1) {
 }
 
-AccessibleChecker::AccessibleChecker(wstring expected_name,
+AccessibleChecker::AccessibleChecker(const std::wstring& expected_name,
                                      int32 expected_role,
                                      int32 expected_ia2_role,
-                                     wstring expected_value) :
-    name_(expected_name),
-    role_(expected_role),
-    ia2_role_(expected_ia2_role),
-    value_(expected_value),
-    state_(-1) {
+                                     const std::wstring& expected_value)
+    : name_(expected_name),
+      role_(expected_role),
+      ia2_role_(expected_ia2_role),
+      value_(expected_value),
+      state_(-1) {
 }
 
-AccessibleChecker::AccessibleChecker(wstring expected_name,
-                                     wstring expected_role,
+AccessibleChecker::AccessibleChecker(const std::wstring& expected_name,
+                                     const std::wstring& expected_role,
                                      int32 expected_ia2_role,
-                                     wstring expected_value) :
-    name_(expected_name),
-    role_(expected_role.c_str()),
-    ia2_role_(expected_ia2_role),
-    value_(expected_value),
-    state_(-1) {
+                                     const std::wstring& expected_value)
+    : name_(expected_name),
+      role_(expected_role.c_str()),
+      ia2_role_(expected_ia2_role),
+      value_(expected_value),
+      state_(-1) {
 }
 
 void AccessibleChecker::AppendExpectedChild(
@@ -294,9 +299,7 @@
 }
 
 void AccessibleChecker::CheckAccessible(IAccessible* accessible) {
-  SCOPED_TRACE(base::StringPrintf(
-      "while checking %s",
-      UTF16ToUTF8(RoleVariantToString(&role_)).c_str()));
+  SCOPED_TRACE("while checking " + UTF16ToUTF8(RoleVariantToString(role_)));
   CheckAccessibleName(accessible);
   CheckAccessibleRole(accessible);
   CheckIA2Role(accessible);
@@ -305,7 +308,7 @@
   CheckAccessibleChildren(accessible);
 }
 
-void AccessibleChecker::SetExpectedValue(wstring expected_value) {
+void AccessibleChecker::SetExpectedValue(const std::wstring& expected_value) {
   value_ = expected_value;
 }
 
@@ -314,31 +317,28 @@
 }
 
 void AccessibleChecker::CheckAccessibleName(IAccessible* accessible) {
-  CComBSTR name;
-  HRESULT hr =
-      accessible->get_accName(CreateI4Variant(CHILDID_SELF), &name);
+  base::win::ScopedBstr name;
+  base::win::ScopedVariant childid_self(CHILDID_SELF);
+  HRESULT hr = accessible->get_accName(childid_self, name.Receive());
 
   if (name_.empty()) {
     // If the object doesn't have name S_FALSE should be returned.
-    EXPECT_EQ(hr, S_FALSE);
+    EXPECT_EQ(S_FALSE, hr);
   } else {
     // Test that the correct string was returned.
     EXPECT_EQ(S_OK, hr);
-    EXPECT_STREQ(name_.c_str(),
-                 wstring(name.m_str, SysStringLen(name)).c_str());
+    EXPECT_EQ(name_, std::wstring(name, name.Length()));
   }
 }
 
 void AccessibleChecker::CheckAccessibleRole(IAccessible* accessible) {
-  VARIANT var_role = {0};
-  HRESULT hr =
-      accessible->get_accRole(CreateI4Variant(CHILDID_SELF), &var_role);
+  base::win::ScopedVariant role;
+  base::win::ScopedVariant childid_self(CHILDID_SELF);
+  HRESULT hr = accessible->get_accRole(childid_self, role.Receive());
   ASSERT_EQ(S_OK, hr);
-  EXPECT_EQ(role_, var_role);
-  if (role_ != var_role) {
-    LOG(ERROR) << "Expected role: " << RoleVariantToString(&role_);
-    LOG(ERROR) << "Got role: " << RoleVariantToString(&var_role);
-  }
+  EXPECT_EQ(0, role_.Compare(role))
+      << "Expected role: " << RoleVariantToString(role_)
+      << "\nGot role: " << RoleVariantToString(role);
 }
 
 void AccessibleChecker::CheckIA2Role(IAccessible* accessible) {
@@ -348,54 +348,48 @@
   long ia2_role = 0;
   hr = accessible2->role(&ia2_role);
   ASSERT_EQ(S_OK, hr);
-  EXPECT_EQ(ia2_role_, ia2_role);
-  if (ia2_role_ != ia2_role) {
-    LOG(ERROR) << "Expected ia2 role: " <<
-        IAccessible2RoleToString(ia2_role_);
-    LOG(ERROR) << "Got ia2 role: " <<
-        IAccessible2RoleToString(ia2_role);
-  }
+  EXPECT_EQ(ia2_role_, ia2_role)
+    << "Expected ia2 role: " << IAccessible2RoleToString(ia2_role_)
+    << "\nGot ia2 role: " << IAccessible2RoleToString(ia2_role);
 }
 
 void AccessibleChecker::CheckAccessibleValue(IAccessible* accessible) {
   // Don't check the value if if's a DOCUMENT role, because the value
   // is supposed to be the url (and we don't keep track of that in the
   // test expectations).
-  VARIANT var_role = {0};
-  HRESULT hr =
-      accessible->get_accRole(CreateI4Variant(CHILDID_SELF), &var_role);
+  base::win::ScopedVariant role;
+  base::win::ScopedVariant childid_self(CHILDID_SELF);
+  HRESULT hr = accessible->get_accRole(childid_self, role.Receive());
   ASSERT_EQ(S_OK, hr);
-  if (V_VT(&var_role) == VT_I4 &&
-      V_I4(&var_role) == ROLE_SYSTEM_DOCUMENT) {
+  if (role.type() == VT_I4 && V_I4(&role) == ROLE_SYSTEM_DOCUMENT)
     return;
-  }
 
   // Get the value.
-  CComBSTR value;
-  hr = accessible->get_accValue(CreateI4Variant(CHILDID_SELF), &value);
+  base::win::ScopedBstr value;
+  hr = accessible->get_accValue(childid_self, value.Receive());
   EXPECT_EQ(S_OK, hr);
 
   // Test that the correct string was returned.
-  EXPECT_STREQ(value_.c_str(),
-               wstring(value.m_str, SysStringLen(value)).c_str());
+  EXPECT_EQ(value_, std::wstring(value, value.Length()));
 }
 
 void AccessibleChecker::CheckAccessibleState(IAccessible* accessible) {
   if (state_ < 0)
     return;
 
-  VARIANT var_state = {0};
-  HRESULT hr =
-      accessible->get_accState(CreateI4Variant(CHILDID_SELF), &var_state);
+  base::win::ScopedVariant state;
+  base::win::ScopedVariant childid_self(CHILDID_SELF);
+  HRESULT hr = accessible->get_accState(childid_self, state.Receive());
   EXPECT_EQ(S_OK, hr);
-  ASSERT_EQ(VT_I4, V_VT(&var_state));
-  EXPECT_EQ(state_, V_I4(&var_state));
-  if (state_ != V_I4(&var_state)) {
-    LOG(ERROR) << "Expected state: " <<
-        IAccessibleStateToString(state_);
-    LOG(ERROR) << "Got state: " <<
-        IAccessibleStateToString(V_I4(&var_state));
-  }
+  ASSERT_EQ(VT_I4, state.type());
+  LONG obj_state = V_I4(&state);
+  // Avoid flakiness. The "offscreen" state depends on whether the browser
+  // window is frontmost or not, and "hottracked" depends on whether the
+  // mouse cursor happens to be over the element.
+  obj_state &= ~(STATE_SYSTEM_OFFSCREEN | STATE_SYSTEM_HOTTRACKED);
+  EXPECT_EQ(state_, obj_state)
+    << "Expected state: " << IAccessibleStateToString(state_)
+    << "\nGot state: " << IAccessibleStateToString(obj_state);
 }
 
 void AccessibleChecker::CheckAccessibleChildren(IAccessible* parent) {
@@ -404,7 +398,7 @@
   EXPECT_EQ(S_OK, hr);
   ASSERT_EQ(child_count, children_.size());
 
-  auto_ptr<VARIANT> child_array(new VARIANT[child_count]);
+  scoped_ptr<VARIANT[]> child_array(new VARIANT[child_count]);
   LONG obtained_count = 0;
   hr = AccessibleChildren(parent, 0, child_count,
                           child_array.get(), &obtained_count);
@@ -415,28 +409,35 @@
   for (AccessibleCheckerVector::iterator child_checker = children_.begin();
        child_checker != children_.end();
        ++child_checker, ++child) {
-    base::win::ScopedComPtr<IAccessible> child_accessible;
-    child_accessible.Attach(GetAccessibleFromResultVariant(parent, child));
+    base::win::ScopedComPtr<IAccessible> child_accessible(
+        GetAccessibleFromResultVariant(parent, child));
     ASSERT_TRUE(child_accessible.get());
     (*child_checker)->CheckAccessible(child_accessible);
   }
 }
 
-string16 AccessibleChecker::RoleVariantToString(VARIANT* role_variant) {
-  if (V_VT(role_variant) == VT_I4)
-    return IAccessibleRoleToString(V_I4(role_variant));
-  else if (V_VT(role_variant) == VT_BSTR)
-    return string16(V_BSTR(role_variant), SysStringLen(V_BSTR(role_variant)));
+string16 AccessibleChecker::RoleVariantToString(
+    const base::win::ScopedVariant& role) {
+  if (role.type() == VT_I4)
+    return IAccessibleRoleToString(V_I4(&role));
+  if (role.type() == VT_BSTR)
+    return string16(V_BSTR(&role), SysStringLen(V_BSTR(&role)));
   return string16();
 }
 
+}  // namespace
+
+
+// Tests ----------------------------------------------------------------------
+
 IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
                        MAYBE(TestBusyAccessibilityTree)) {
   NavigateToURL(shell(), GURL(chrome::kAboutBlankURL));
 
   // The initial accessible returned should have state STATE_SYSTEM_BUSY while
   // the accessibility tree is being requested from the renderer.
-  AccessibleChecker document1_checker(L"", ROLE_SYSTEM_DOCUMENT, L"");
+  AccessibleChecker document1_checker(std::wstring(), ROLE_SYSTEM_DOCUMENT,
+                                      std::wstring());
   document1_checker.SetExpectedState(
       STATE_SYSTEM_READONLY | STATE_SYSTEM_FOCUSABLE | STATE_SYSTEM_FOCUSED |
       STATE_SYSTEM_BUSY);
@@ -452,11 +453,14 @@
       "</body></html>");
 
   // Check the browser's copy of the renderer accessibility tree.
-  AccessibleChecker button_checker(L"push", ROLE_SYSTEM_PUSHBUTTON, L"");
-  AccessibleChecker checkbox_checker(L"", ROLE_SYSTEM_CHECKBUTTON, L"");
-  AccessibleChecker body_checker(L"", L"body", IA2_ROLE_SECTION, L"");
-  AccessibleChecker document2_checker(
-      L"Accessibility Win Test", ROLE_SYSTEM_DOCUMENT, L"");
+  AccessibleChecker button_checker(L"push", ROLE_SYSTEM_PUSHBUTTON,
+                                   std::wstring());
+  AccessibleChecker checkbox_checker(std::wstring(), ROLE_SYSTEM_CHECKBUTTON,
+                                     std::wstring());
+  AccessibleChecker body_checker(std::wstring(), L"body", IA2_ROLE_SECTION,
+                                 std::wstring());
+  AccessibleChecker document2_checker(L"Accessibility Win Test",
+                                      ROLE_SYSTEM_DOCUMENT, std::wstring());
   body_checker.AppendExpectedChild(&button_checker);
   body_checker.AppendExpectedChild(&checkbox_checker);
   document2_checker.AppendExpectedChild(&body_checker);
@@ -477,8 +481,9 @@
   // Verify that the IAccessible reference still points to a valid object and
   // that calls to its methods fail since the tree is no longer valid after
   // the page navagation.
-  CComBSTR name;
-  hr = document_accessible->get_accName(CreateI4Variant(CHILDID_SELF), &name);
+  base::win::ScopedBstr name;
+  base::win::ScopedVariant childid_self(CHILDID_SELF);
+  hr = document_accessible->get_accName(childid_self, name.Receive());
   ASSERT_EQ(E_FAIL, hr);
 }
 
@@ -490,15 +495,18 @@
       "<li id='li'>li</li></ul>");
 
   // Check the browser's copy of the renderer accessibility tree.
-  AccessibleChecker list_marker_checker(L"\x2022", ROLE_SYSTEM_TEXT, L"");
-  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);
+  AccessibleChecker list_marker_checker(L"\x2022", ROLE_SYSTEM_TEXT,
+                                        std::wstring());
+  AccessibleChecker static_text_checker(L"li", ROLE_SYSTEM_TEXT,
+                                        std::wstring());
+  AccessibleChecker list_item_checker(std::wstring(), ROLE_SYSTEM_LISTITEM,
+                                      std::wstring());
+  list_item_checker.SetExpectedState(STATE_SYSTEM_READONLY);
   AccessibleChecker radio_group_checker(L"ul", ROLE_SYSTEM_GROUPING,
-      IA2_ROLE_SECTION, L"");
+                                        IA2_ROLE_SECTION, std::wstring());
   radio_group_checker.SetExpectedState(STATE_SYSTEM_FOCUSABLE);
-  AccessibleChecker document_checker(L"", ROLE_SYSTEM_DOCUMENT, L"");
+  AccessibleChecker document_checker(std::wstring(), ROLE_SYSTEM_DOCUMENT,
+                                     std::wstring());
   list_item_checker.AppendExpectedChild(&list_marker_checker);
   list_item_checker.AppendExpectedChild(&static_text_checker);
   radio_group_checker.AppendExpectedChild(&list_item_checker);
@@ -541,10 +549,13 @@
       "<body><input type='checkbox' /></body>");
 
   // Check the browser's copy of the renderer accessibility tree.
-  AccessibleChecker checkbox_checker(L"", ROLE_SYSTEM_CHECKBUTTON, L"");
+  AccessibleChecker checkbox_checker(std::wstring(), ROLE_SYSTEM_CHECKBUTTON,
+                                     std::wstring());
   checkbox_checker.SetExpectedState(STATE_SYSTEM_FOCUSABLE);
-  AccessibleChecker body_checker(L"", L"body", IA2_ROLE_SECTION, L"");
-  AccessibleChecker document_checker(L"", ROLE_SYSTEM_DOCUMENT, L"");
+  AccessibleChecker body_checker(std::wstring(), L"body", IA2_ROLE_SECTION,
+                                 std::wstring());
+  AccessibleChecker document_checker(std::wstring(), ROLE_SYSTEM_DOCUMENT,
+                                     std::wstring());
   body_checker.AppendExpectedChild(&checkbox_checker);
   document_checker.AppendExpectedChild(&body_checker);
   document_checker.CheckAccessible(GetRendererAccessible());
@@ -571,8 +582,10 @@
   LoadInitialAccessibilityTreeFromHtml("<body role=group></body>");
 
   // Check the browser's copy of the renderer accessibility tree.
-  AccessibleChecker group_checker(L"", ROLE_SYSTEM_GROUPING, L"");
-  AccessibleChecker document_checker(L"", ROLE_SYSTEM_DOCUMENT, L"");
+  AccessibleChecker group_checker(std::wstring(), ROLE_SYSTEM_GROUPING,
+                                  std::wstring());
+  AccessibleChecker document_checker(std::wstring(), ROLE_SYSTEM_DOCUMENT,
+                                     std::wstring());
   document_checker.AppendExpectedChild(&group_checker);
   document_checker.CheckAccessible(GetRendererAccessible());
 
@@ -587,7 +600,7 @@
   loop_runner->Run();
 
   // Check that the accessibility tree of the browser has been updated.
-  AccessibleChecker text_checker(L"new text", ROLE_SYSTEM_TEXT, L"");
+  AccessibleChecker text_checker(L"new text", ROLE_SYSTEM_TEXT, std::wstring());
   group_checker.AppendExpectedChild(&text_checker);
   document_checker.CheckAccessible(GetRendererAccessible());
 }
@@ -599,7 +612,8 @@
       "<div role=group style='visibility: hidden'>text</div>");
 
   // Check the accessible tree of the browser.
-  AccessibleChecker document_checker(L"", ROLE_SYSTEM_DOCUMENT, L"");
+  AccessibleChecker document_checker(std::wstring(), ROLE_SYSTEM_DOCUMENT,
+                                     std::wstring());
   document_checker.CheckAccessible(GetRendererAccessible());
 
   // Change the children of the document body.
@@ -613,8 +627,10 @@
   loop_runner->Run();
 
   // Check that the accessibility tree of the browser has been updated.
-  AccessibleChecker static_text_checker(L"text", ROLE_SYSTEM_TEXT, L"");
-  AccessibleChecker group_checker(L"", ROLE_SYSTEM_GROUPING, L"");
+  AccessibleChecker static_text_checker(L"text", ROLE_SYSTEM_TEXT,
+                                        std::wstring());
+  AccessibleChecker group_checker(std::wstring(), ROLE_SYSTEM_GROUPING,
+                                  std::wstring());
   document_checker.AppendExpectedChild(&group_checker);
   group_checker.AppendExpectedChild(&static_text_checker);
   document_checker.CheckAccessible(GetRendererAccessible());
@@ -627,10 +643,11 @@
 
   // Check the browser's copy of the renderer accessibility tree.
   SCOPED_TRACE("Check initial tree");
-  AccessibleChecker group_checker(L"", ROLE_SYSTEM_GROUPING, L"");
-  group_checker.SetExpectedState(
-      STATE_SYSTEM_FOCUSABLE | STATE_SYSTEM_OFFSCREEN);
-  AccessibleChecker document_checker(L"", ROLE_SYSTEM_DOCUMENT, L"");
+  AccessibleChecker group_checker(std::wstring(), ROLE_SYSTEM_GROUPING,
+                                  std::wstring());
+  group_checker.SetExpectedState(STATE_SYSTEM_FOCUSABLE);
+  AccessibleChecker document_checker(std::wstring(), ROLE_SYSTEM_DOCUMENT,
+                                     std::wstring());
   document_checker.AppendExpectedChild(&group_checker);
   document_checker.CheckAccessible(GetRendererAccessible());
 
@@ -657,8 +674,8 @@
   base::win::ScopedComPtr<IAccessible> document_accessible(
       GetRendererAccessible());
   ASSERT_NE(document_accessible.get(), reinterpret_cast<IAccessible*>(NULL));
-  HRESULT hr = document_accessible->accSelect(
-    SELFLAG_TAKEFOCUS, CreateI4Variant(CHILDID_SELF));
+  base::win::ScopedVariant childid_self(CHILDID_SELF);
+  HRESULT hr = document_accessible->accSelect(SELFLAG_TAKEFOCUS, childid_self);
   ASSERT_EQ(S_OK, hr);
   loop_runner->Run();
 
@@ -674,10 +691,13 @@
       "<body><input type='text' value='old value'/></body>");
 
   // Check the browser's copy of the renderer accessibility tree.
-  AccessibleChecker text_field_checker(L"", ROLE_SYSTEM_TEXT, L"old value");
+  AccessibleChecker text_field_checker(std::wstring(), ROLE_SYSTEM_TEXT,
+                                       L"old value");
   text_field_checker.SetExpectedState(STATE_SYSTEM_FOCUSABLE);
-  AccessibleChecker body_checker(L"", L"body", IA2_ROLE_SECTION, L"");
-  AccessibleChecker document_checker(L"", ROLE_SYSTEM_DOCUMENT, L"");
+  AccessibleChecker body_checker(std::wstring(), L"body", IA2_ROLE_SECTION,
+                                 std::wstring());
+  AccessibleChecker document_checker(std::wstring(), ROLE_SYSTEM_DOCUMENT,
+                                     std::wstring());
   body_checker.AppendExpectedChild(&text_field_checker);
   document_checker.AppendExpectedChild(&body_checker);
   document_checker.CheckAccessible(GetRendererAccessible());
@@ -732,15 +752,17 @@
                        DISABLED_TestToggleButtonRoleAndStates) {
   AccessibleChecker* button_checker;
   std::string button_html("data:text/html,");
-  AccessibleChecker document_checker(L"", ROLE_SYSTEM_DOCUMENT, L"");
-  AccessibleChecker body_checker(L"", L"body", IA2_ROLE_SECTION, L"");
+  AccessibleChecker document_checker(std::wstring(), ROLE_SYSTEM_DOCUMENT,
+                                     std::wstring());
+  AccessibleChecker body_checker(std::wstring(), L"body", IA2_ROLE_SECTION,
+                                 std::wstring());
   document_checker.AppendExpectedChild(&body_checker);
 
 // Temporary macro
 #define ADD_BUTTON(html, ia2_role, state) \
     button_html += html; \
     button_checker = new AccessibleChecker(L"x", ROLE_SYSTEM_PUSHBUTTON, \
-      ia2_role, L""); \
+      ia2_role, std::wstring()); \
     button_checker->SetExpectedState(state); \
     body_checker.AppendExpectedChild(button_checker)
 
@@ -823,40 +845,44 @@
       reinterpret_cast<void**>(document_isimpledomnode.Receive()));
   ASSERT_EQ(S_OK, hr);
 
-  BSTR node_name;
+  base::win::ScopedBstr node_name;
   short name_space_id;  // NOLINT
-  BSTR node_value;
+  base::win::ScopedBstr 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);
+      node_name.Receive(), &name_space_id, node_value.Receive(), &num_children,
+      &unique_id, &node_type);
   ASSERT_EQ(S_OK, hr);
   EXPECT_EQ(NODETYPE_DOCUMENT, node_type);
   EXPECT_EQ(1, num_children);
+  node_name.Reset();
+  node_value.Reset();
 
   base::win::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);
+      node_name.Receive(), &name_space_id, node_value.Receive(), &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(L"body", std::wstring(node_name, node_name.Length()));
   EXPECT_EQ(NODETYPE_ELEMENT, node_type);
   EXPECT_EQ(1, num_children);
+  node_name.Reset();
+  node_value.Reset();
 
   base::win::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);
+      node_name.Receive(), &name_space_id, node_value.Receive(), &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(L"input", std::wstring(node_name, node_name.Length()));
   EXPECT_EQ(NODETYPE_ELEMENT, node_type);
   EXPECT_EQ(0, num_children);
 }
@@ -866,13 +892,15 @@
       "<fieldset></fieldset><div role=group></div>");
 
   // Check the browser's copy of the renderer accessibility tree.
-  AccessibleChecker grouping1_checker(L"", ROLE_SYSTEM_GROUPING, L"");
-  AccessibleChecker grouping2_checker(L"", ROLE_SYSTEM_GROUPING, L"");
-  AccessibleChecker document_checker(L"", ROLE_SYSTEM_DOCUMENT, L"");
+  AccessibleChecker grouping1_checker(std::wstring(), ROLE_SYSTEM_GROUPING,
+                                      std::wstring());
+  AccessibleChecker grouping2_checker(std::wstring(), ROLE_SYSTEM_GROUPING,
+                                      std::wstring());
+  AccessibleChecker document_checker(std::wstring(), ROLE_SYSTEM_DOCUMENT,
+                                     std::wstring());
   document_checker.AppendExpectedChild(&grouping1_checker);
   document_checker.AppendExpectedChild(&grouping2_checker);
   document_checker.CheckAccessible(GetRendererAccessible());
 }
-}  // namespace.
 
 }  // namespace content
diff --git a/content/browser/accessibility/browser_accessibility.cc b/content/browser/accessibility/browser_accessibility.cc
index 2c4b078..fcfd365 100644
--- a/content/browser/accessibility/browser_accessibility.cc
+++ b/content/browser/accessibility/browser_accessibility.cc
@@ -31,7 +31,6 @@
 BrowserAccessibility::BrowserAccessibility()
     : manager_(NULL),
       parent_(NULL),
-      child_id_(0),
       index_in_parent_(0),
       renderer_id_(0),
       role_(0),
@@ -54,12 +53,10 @@
 void BrowserAccessibility::InitializeTreeStructure(
     BrowserAccessibilityManager* manager,
     BrowserAccessibility* parent,
-    int32 child_id,
     int32 renderer_id,
     int32 index_in_parent) {
   manager_ = manager;
   parent_ = parent;
-  child_id_ = child_id;
   renderer_id_ = renderer_id;
   index_in_parent_ = index_in_parent;
 }
@@ -100,6 +97,10 @@
   index_in_parent_ = index_in_parent;
 }
 
+void BrowserAccessibility::SetLocation(const gfx::Rect& new_location) {
+  location_ = new_location;
+}
+
 bool BrowserAccessibility::IsDescendantOf(
     BrowserAccessibility* ancestor) {
   if (this == ancestor) {
@@ -205,7 +206,7 @@
       AccessibilityNotificationObjectHide, this);
 
   instance_active_ = false;
-  manager_->Remove(this);
+  manager_->RemoveNode(this);
   NativeReleaseReference();
 }
 
diff --git a/content/browser/accessibility/browser_accessibility.h b/content/browser/accessibility/browser_accessibility.h
index 62fff55..d70124a 100644
--- a/content/browser/accessibility/browser_accessibility.h
+++ b/content/browser/accessibility/browser_accessibility.h
@@ -70,7 +70,6 @@
   void InitializeTreeStructure(
       BrowserAccessibilityManager* manager,
       BrowserAccessibility* parent,
-      int32 child_id,
       int32 renderer_id,
       int32 index_in_parent);
 
@@ -82,6 +81,9 @@
   // Update the parent and index in parent if this node has been moved.
   void UpdateParent(BrowserAccessibility* parent, int index_in_parent);
 
+  // Update this node's location, leaving everything else the same.
+  virtual void SetLocation(const gfx::Rect& new_location);
+
   // Return true if this object is equal to or a descendant of |ancestor|.
   bool IsDescendantOf(BrowserAccessibility* ancestor);
 
@@ -150,7 +152,6 @@
     return string_attributes_;
   }
 
-  int32 child_id() const { return child_id_; }
   const std::vector<BrowserAccessibility*>& children() const {
     return children_;
   }
@@ -253,9 +254,6 @@
   // The parent of this object, may be NULL if we're the root object.
   BrowserAccessibility* parent_;
 
-  // The ID of this object; globally unique within the browser process.
-  int32 child_id_;
-
   // The index of this within its parent object.
   int32 index_in_parent_;
 
diff --git a/content/browser/accessibility/browser_accessibility_cocoa.h b/content/browser/accessibility/browser_accessibility_cocoa.h
index 9733e0c..0d401a0 100644
--- a/content/browser/accessibility/browser_accessibility_cocoa.h
+++ b/content/browser/accessibility/browser_accessibility_cocoa.h
@@ -52,6 +52,8 @@
 @property(nonatomic, readonly) NSString* ariaRelevant;
 @property(nonatomic, readonly) NSArray* children;
 @property(nonatomic, readonly) NSArray* columns;
+@property(nonatomic, readonly) NSArray* columnHeaders;
+@property(nonatomic, readonly) NSValue* columnIndexRange;
 @property(nonatomic, readonly) NSString* description;
 @property(nonatomic, readonly) NSNumber* disclosing;
 @property(nonatomic, readonly) id disclosedByRow;
@@ -63,6 +65,8 @@
 // isIgnored returns whether or not the accessibility object
 // should be ignored by the accessibility hierarchy.
 @property(nonatomic, readonly, getter=isIgnored) BOOL ignored;
+// Index of a row, column, or tree item.
+@property(nonatomic, readonly) NSNumber* index;
 @property(nonatomic, readonly) NSString* invalid;
 @property(nonatomic, readonly) NSNumber* loaded;
 @property(nonatomic, readonly) NSNumber* loadingProgress;
@@ -77,6 +81,8 @@
 // is concerned.
 @property(nonatomic, readonly) NSString* role;
 @property(nonatomic, readonly) NSString* roleDescription;
+@property(nonatomic, readonly) NSArray* rowHeaders;
+@property(nonatomic, readonly) NSValue* rowIndexRange;
 @property(nonatomic, readonly) NSArray* rows;
 // The size of this object.
 @property(nonatomic, readonly) NSValue* size;
@@ -91,6 +97,9 @@
 @property(nonatomic, readonly) NSString* value;
 @property(nonatomic, readonly) NSString* valueDescription;
 @property(nonatomic, readonly) NSValue* visibleCharacterRange;
+@property(nonatomic, readonly) NSArray* visibleCells;
+@property(nonatomic, readonly) NSArray* visibleColumns;
+@property(nonatomic, readonly) NSArray* visibleRows;
 @property(nonatomic, readonly) NSNumber* visited;
 @property(nonatomic, readonly) id window;
 @end
diff --git a/content/browser/accessibility/browser_accessibility_cocoa.mm b/content/browser/accessibility/browser_accessibility_cocoa.mm
index e4d695a..f53cb5a 100644
--- a/content/browser/accessibility/browser_accessibility_cocoa.mm
+++ b/content/browser/accessibility/browser_accessibility_cocoa.mm
@@ -10,7 +10,7 @@
 
 #include "base/basictypes.h"
 #include "base/string16.h"
-#include "base/sys_string_conversions.h"
+#include "base/strings/sys_string_conversions.h"
 #include "base/utf_string_conversions.h"
 #include "content/browser/accessibility/browser_accessibility_manager.h"
 #include "content/browser/accessibility/browser_accessibility_manager_mac.h"
@@ -275,6 +275,9 @@
   } attributeToMethodNameContainer[] = {
     { NSAccessibilityChildrenAttribute, @"children" },
     { NSAccessibilityColumnsAttribute, @"columns" },
+    { NSAccessibilityColumnHeaderUIElementsAttribute, @"columnHeaders" },
+    { NSAccessibilityColumnIndexRangeAttribute, @"columnIndexRange" },
+    { NSAccessibilityContentsAttribute, @"contents" },
     { NSAccessibilityDescriptionAttribute, @"description" },
     { NSAccessibilityDisclosingAttribute, @"disclosing" },
     { NSAccessibilityDisclosedByRowAttribute, @"disclosedByRow" },
@@ -282,7 +285,9 @@
     { NSAccessibilityDisclosedRowsAttribute, @"disclosedRows" },
     { NSAccessibilityEnabledAttribute, @"enabled" },
     { NSAccessibilityFocusedAttribute, @"focused" },
+    { NSAccessibilityHeaderAttribute, @"header" },
     { NSAccessibilityHelpAttribute, @"help" },
+    { NSAccessibilityIndexAttribute, @"index" },
     { NSAccessibilityMaxValueAttribute, @"maxValue" },
     { NSAccessibilityMinValueAttribute, @"minValue" },
     { NSAccessibilityNumberOfCharactersAttribute, @"numberOfCharacters" },
@@ -291,6 +296,8 @@
     { NSAccessibilityPositionAttribute, @"position" },
     { NSAccessibilityRoleAttribute, @"role" },
     { NSAccessibilityRoleDescriptionAttribute, @"roleDescription" },
+    { NSAccessibilityRowHeaderUIElementsAttribute, @"rowHeaders" },
+    { NSAccessibilityRowIndexRangeAttribute, @"rowIndexRange" },
     { NSAccessibilityRowsAttribute, @"rows" },
     { NSAccessibilitySizeAttribute, @"size" },
     { NSAccessibilitySubroleAttribute, @"subrole" },
@@ -302,6 +309,9 @@
     { NSAccessibilityValueAttribute, @"value" },
     { NSAccessibilityValueDescriptionAttribute, @"valueDescription" },
     { NSAccessibilityVisibleCharacterRangeAttribute, @"visibleCharacterRange" },
+    { NSAccessibilityVisibleCellsAttribute, @"visibleCells" },
+    { NSAccessibilityVisibleColumnsAttribute, @"visibleColumns" },
+    { NSAccessibilityVisibleRowsAttribute, @"visibleRows" },
     { NSAccessibilityWindowAttribute, @"window" },
     { @"AXAccessKey", @"accessKey" },
     { @"AXARIAAtomic", @"ariaAtomic" },
@@ -381,7 +391,7 @@
 // Returns an array of BrowserAccessibilityCocoa objects, representing the
 // accessibility children of this object.
 - (NSArray*)children {
-  if (!children_.get()) {
+  if (!children_) {
     children_.reset([[NSMutableArray alloc]
         initWithCapacity:browserAccessibility_->child_count()] );
     for (uint32 index = 0;
@@ -424,6 +434,40 @@
   }
 }
 
+- (NSArray*)columnHeaders {
+  if ([self internalRole] != AccessibilityNodeData::ROLE_TABLE &&
+      [self internalRole] != AccessibilityNodeData::ROLE_GRID) {
+    return nil;
+  }
+
+  NSMutableArray* ret = [[[NSMutableArray alloc] init] autorelease];
+  const std::vector<int32>& uniqueCellIds =
+      browserAccessibility_->unique_cell_ids();
+  for (size_t i = 0; i < uniqueCellIds.size(); ++i) {
+    int id = uniqueCellIds[i];
+    BrowserAccessibility* cell =
+        browserAccessibility_->manager()->GetFromRendererID(id);
+    if (cell && cell->role() == AccessibilityNodeData::ROLE_COLUMN_HEADER)
+      [ret addObject:cell->ToBrowserAccessibilityCocoa()];
+  }
+  return ret;
+}
+
+- (NSValue*)columnIndexRange {
+  if ([self internalRole] != AccessibilityNodeData::ROLE_CELL)
+    return nil;
+
+  int column = -1;
+  int colspan = -1;
+  browserAccessibility_->GetIntAttribute(
+      AccessibilityNodeData::ATTR_TABLE_CELL_COLUMN_INDEX, &column);
+  browserAccessibility_->GetIntAttribute(
+      AccessibilityNodeData::ATTR_TABLE_CELL_COLUMN_SPAN, &colspan);
+  if (column >= 0 && colspan >= 1)
+    return [NSValue valueWithRange:NSMakeRange(column, colspan)];
+  return nil;
+}
+
 - (NSArray*)columns {
   NSMutableArray* ret = [[[NSMutableArray alloc] init] autorelease];
   for (BrowserAccessibilityCocoa* child in [self children]) {
@@ -517,12 +561,53 @@
   return ret;
 }
 
+- (id)header {
+  int headerElementId = -1;
+  if ([self internalRole] == AccessibilityNodeData::ROLE_TABLE ||
+      [self internalRole] == AccessibilityNodeData::ROLE_GRID) {
+    browserAccessibility_->GetIntAttribute(
+        AccessibilityNodeData::ATTR_TABLE_HEADER_ID, &headerElementId);
+  } else if ([self internalRole] == AccessibilityNodeData::ROLE_COLUMN) {
+    browserAccessibility_->GetIntAttribute(
+        AccessibilityNodeData::ATTR_TABLE_COLUMN_HEADER_ID, &headerElementId);
+  } else if ([self internalRole] == AccessibilityNodeData::ROLE_ROW) {
+    browserAccessibility_->GetIntAttribute(
+        AccessibilityNodeData::ATTR_TABLE_ROW_HEADER_ID, &headerElementId);
+  }
+
+  if (headerElementId > 0) {
+    BrowserAccessibility* headerObject =
+        browserAccessibility_->manager()->GetFromRendererID(headerElementId);
+    if (headerObject)
+      return headerObject->ToBrowserAccessibilityCocoa();
+  }
+  return nil;
+}
+
 - (NSString*)help {
   return NSStringForStringAttribute(
       browserAccessibility_->string_attributes(),
       AccessibilityNodeData::ATTR_HELP);
 }
 
+- (NSNumber*)index {
+  if ([self internalRole] == AccessibilityNodeData::ROLE_COLUMN) {
+    int columnIndex;
+    if (browserAccessibility_->GetIntAttribute(
+            AccessibilityNodeData::ATTR_TABLE_COLUMN_INDEX, &columnIndex)) {
+      return [NSNumber numberWithInt:columnIndex];
+    }
+  } else if ([self internalRole] == AccessibilityNodeData::ROLE_ROW) {
+    int rowIndex;
+    if (browserAccessibility_->GetIntAttribute(
+            AccessibilityNodeData::ATTR_TABLE_ROW_INDEX, &rowIndex)) {
+      return [NSNumber numberWithInt:rowIndex];
+    }
+  }
+
+  return nil;
+}
+
 // Returns whether or not this node should be ignored in the
 // accessibility tree.
 - (BOOL)isIgnored {
@@ -679,11 +764,59 @@
   return NSAccessibilityRoleDescription(role, nil);
 }
 
+- (NSArray*)rowHeaders {
+  if ([self internalRole] != AccessibilityNodeData::ROLE_TABLE &&
+      [self internalRole] != AccessibilityNodeData::ROLE_GRID) {
+    return nil;
+  }
+
+  NSMutableArray* ret = [[[NSMutableArray alloc] init] autorelease];
+  const std::vector<int32>& uniqueCellIds =
+      browserAccessibility_->unique_cell_ids();
+  for (size_t i = 0; i < uniqueCellIds.size(); ++i) {
+    int id = uniqueCellIds[i];
+    BrowserAccessibility* cell =
+        browserAccessibility_->manager()->GetFromRendererID(id);
+    if (cell && cell->role() == AccessibilityNodeData::ROLE_ROW_HEADER)
+      [ret addObject:cell->ToBrowserAccessibilityCocoa()];
+  }
+  return ret;
+}
+
+- (NSValue*)rowIndexRange {
+  if ([self internalRole] != AccessibilityNodeData::ROLE_CELL)
+    return nil;
+
+  int row = -1;
+  int rowspan = -1;
+  browserAccessibility_->GetIntAttribute(
+      AccessibilityNodeData::ATTR_TABLE_CELL_ROW_INDEX, &row);
+  browserAccessibility_->GetIntAttribute(
+      AccessibilityNodeData::ATTR_TABLE_CELL_ROW_SPAN, &rowspan);
+  if (row >= 0 && rowspan >= 1)
+    return [NSValue valueWithRange:NSMakeRange(row, rowspan)];
+  return nil;
+}
+
 - (NSArray*)rows {
   NSMutableArray* ret = [[[NSMutableArray alloc] init] autorelease];
-  for (BrowserAccessibilityCocoa* child in [self children]) {
-    if ([[child role] isEqualToString:NSAccessibilityRowRole])
-      [ret addObject:child];
+
+  if ([self internalRole] == AccessibilityNodeData::ROLE_TABLE||
+      [self internalRole] == AccessibilityNodeData::ROLE_GRID) {
+    for (BrowserAccessibilityCocoa* child in [self children]) {
+      if ([[child role] isEqualToString:NSAccessibilityRowRole])
+        [ret addObject:child];
+    }
+  } else if ([self internalRole] == AccessibilityNodeData::ROLE_COLUMN) {
+    const std::vector<int32>& indirectChildIds =
+        browserAccessibility_->indirect_child_ids();
+    for (uint32 i = 0; i < indirectChildIds.size(); ++i) {
+      int id = indirectChildIds[i];
+      BrowserAccessibility* rowElement =
+          browserAccessibility_->manager()->GetFromRendererID(id);
+      if (rowElement)
+        [ret addObject:rowElement->ToBrowserAccessibilityCocoa()];
+    }
   }
 
   return ret;
@@ -827,6 +960,28 @@
       NSMakeRange(0, browserAccessibility_->value().length())];
 }
 
+- (NSArray*)visibleCells {
+  NSMutableArray* ret = [[[NSMutableArray alloc] init] autorelease];
+  const std::vector<int32>& uniqueCellIds =
+      browserAccessibility_->unique_cell_ids();
+  for (size_t i = 0; i < uniqueCellIds.size(); ++i) {
+    int id = uniqueCellIds[i];
+    BrowserAccessibility* cell =
+        browserAccessibility_->manager()->GetFromRendererID(id);
+    if (cell)
+      [ret addObject:cell->ToBrowserAccessibilityCocoa()];
+  }
+  return ret;
+}
+
+- (NSArray*)visibleColumns {
+  return [self columns];
+}
+
+- (NSArray*)visibleRows {
+  return [self rows];
+}
+
 - (NSNumber*)visited {
   return [NSNumber numberWithBool:
       GetState(browserAccessibility_, AccessibilityNodeData::STATE_TRAVERSED)];
@@ -914,6 +1069,63 @@
         NSMakeRange(start, end - start)];
   }
 
+  if ([attribute isEqualToString:
+      NSAccessibilityCellForColumnAndRowParameterizedAttribute]) {
+    if ([self internalRole] != AccessibilityNodeData::ROLE_TABLE &&
+        [self internalRole] != AccessibilityNodeData::ROLE_GRID) {
+      return nil;
+    }
+    if (![parameter isKindOfClass:[NSArray self]])
+      return nil;
+    NSArray* array = parameter;
+    int column = [[array objectAtIndex:0] intValue];
+    int row = [[array objectAtIndex:1] intValue];
+    int num_columns = 0;
+    int num_rows = 0;
+    browserAccessibility_->GetIntAttribute(
+        AccessibilityNodeData::ATTR_TABLE_COLUMN_COUNT, &num_columns);
+    browserAccessibility_->GetIntAttribute(
+        AccessibilityNodeData::ATTR_TABLE_ROW_COUNT, &num_rows);
+    if (column < 0 || column >= num_columns ||
+        row < 0 || row >= num_rows) {
+      return nil;
+    }
+    for (size_t i = 0;
+         i < browserAccessibility_->child_count();
+         ++i) {
+      BrowserAccessibility* child = browserAccessibility_->GetChild(i);
+      if (child->role() != AccessibilityNodeData::ROLE_ROW)
+        continue;
+      int rowIndex;
+      if (!child->GetIntAttribute(
+              AccessibilityNodeData::ATTR_TABLE_ROW_INDEX, &rowIndex)) {
+        continue;
+      }
+      if (rowIndex < row)
+        continue;
+      if (rowIndex > row)
+        break;
+      for (size_t j = 0;
+           j < child->child_count();
+           ++j) {
+        BrowserAccessibility* cell = child->GetChild(j);
+        if (cell->role() != AccessibilityNodeData::ROLE_CELL)
+          continue;
+        int colIndex;
+        if (!cell->GetIntAttribute(
+                AccessibilityNodeData::ATTR_TABLE_CELL_COLUMN_INDEX,
+                &colIndex)) {
+          continue;
+        }
+        if (colIndex == column)
+          return cell->ToBrowserAccessibilityCocoa();
+        if (colIndex > column)
+          break;
+      }
+    }
+    return nil;
+  }
+
   // TODO(dtseng): support the following attributes.
   if ([attribute isEqualTo:
           NSAccessibilityRangeForPositionParameterizedAttribute] ||
@@ -932,6 +1144,12 @@
 // Returns an array of parameterized attributes names that this object will
 // respond to.
 - (NSArray*)accessibilityParameterizedAttributeNames {
+  if ([[self role] isEqualToString:NSAccessibilityTableRole] ||
+      [[self role] isEqualToString:NSAccessibilityGridRole]) {
+    return [NSArray arrayWithObjects:
+        NSAccessibilityCellForColumnAndRowParameterizedAttribute,
+        nil];
+  }
   if ([[self role] isEqualToString:NSAccessibilityTextFieldRole] ||
       [[self role] isEqualToString:NSAccessibilityTextAreaRole]) {
     return [NSArray arrayWithObjects:
@@ -1023,10 +1241,29 @@
   // Specific role attributes.
   NSString* role = [self role];
   NSString* subrole = [self subrole];
-  if ([role isEqualToString:NSAccessibilityTableRole]) {
+  if ([role isEqualToString:NSAccessibilityTableRole] ||
+      [role isEqualToString:NSAccessibilityGridRole]) {
     [ret addObjectsFromArray:[NSArray arrayWithObjects:
         NSAccessibilityColumnsAttribute,
+        NSAccessibilityVisibleColumnsAttribute,
         NSAccessibilityRowsAttribute,
+        NSAccessibilityVisibleRowsAttribute,
+        NSAccessibilityVisibleCellsAttribute,
+        NSAccessibilityHeaderAttribute,
+        NSAccessibilityColumnHeaderUIElementsAttribute,
+        NSAccessibilityRowHeaderUIElementsAttribute,
+        nil]];
+  } else if ([role isEqualToString:NSAccessibilityColumnRole]) {
+    [ret addObjectsFromArray:[NSArray arrayWithObjects:
+        NSAccessibilityIndexAttribute,
+        NSAccessibilityHeaderAttribute,
+        NSAccessibilityRowsAttribute,
+        NSAccessibilityVisibleRowsAttribute,
+        nil]];
+  } else if ([role isEqualToString:NSAccessibilityCellRole]) {
+    [ret addObjectsFromArray:[NSArray arrayWithObjects:
+        NSAccessibilityColumnIndexRangeAttribute,
+        NSAccessibilityRowIndexRangeAttribute,
         nil]];
   } else if ([role isEqualToString:@"AXWebArea"]) {
     [ret addObjectsFromArray:[NSArray arrayWithObjects:
@@ -1073,11 +1310,14 @@
             NSAccessibilityDisclosureLevelAttribute,
             NSAccessibilityDisclosedRowsAttribute,
             nil]];
+      } else {
+        [ret addObjectsFromArray:[NSArray arrayWithObjects:
+            NSAccessibilityIndexAttribute,
+            nil]];
       }
     }
   }
 
-
   // Live regions.
   string16 s;
   if (browserAccessibility_->GetStringAttribute(
diff --git a/content/browser/accessibility/browser_accessibility_manager.cc b/content/browser/accessibility/browser_accessibility_manager.cc
index ca02fa5..498d853 100644
--- a/content/browser/accessibility/browser_accessibility_manager.cc
+++ b/content/browser/accessibility/browser_accessibility_manager.cc
@@ -15,13 +15,6 @@
   return BrowserAccessibility::Create();
 }
 
-// Start child IDs at -1 and decrement each time, because clients use
-// child IDs of 1, 2, 3, ... to access the children of an object by
-// index, so we use negative IDs to clearly distinguish between indices
-// and unique IDs.
-// static
-int32 BrowserAccessibilityManager::next_child_id_ = -1;
-
 #if !defined(OS_MACOSX) && \
     !defined(OS_WIN) && \
     !defined(TOOLKIT_GTK)
@@ -53,19 +46,6 @@
     SetFocus(root_, false);
 }
 
-// static
-int32 BrowserAccessibilityManager::GetNextChildID() {
-  // Get the next child ID, and wrap around when we get near the end
-  // of a 32-bit integer range. It's okay to wrap around; we just want
-  // to avoid it as long as possible because clients may cache the ID of
-  // an object for a while to determine if they've seen it before.
-  next_child_id_--;
-  if (next_child_id_ == -2000000000)
-    next_child_id_ = -1;
-
-  return next_child_id_;
-}
-
 BrowserAccessibilityManager::~BrowserAccessibilityManager() {
   if (root_)
     root_->Destroy();
@@ -75,26 +55,13 @@
   return root_;
 }
 
-BrowserAccessibility* BrowserAccessibilityManager::GetFromChildID(
-    int32 child_id) {
-  base::hash_map<int32, BrowserAccessibility*>::iterator iter =
-      child_id_map_.find(child_id);
-  if (iter != child_id_map_.end()) {
-    return iter->second;
-  } else {
-    return NULL;
-  }
-}
-
 BrowserAccessibility* BrowserAccessibilityManager::GetFromRendererID(
     int32 renderer_id) {
-  base::hash_map<int32, int32>::iterator iter =
-      renderer_id_to_child_id_map_.find(renderer_id);
-  if (iter == renderer_id_to_child_id_map_.end())
-    return NULL;
-
-  int32 child_id = iter->second;
-  return GetFromChildID(child_id);
+  base::hash_map<int32, BrowserAccessibility*>::iterator iter =
+      renderer_id_map_.find(renderer_id);
+  if (iter != renderer_id_map_.end())
+    return iter->second;
+  return NULL;
 }
 
 void BrowserAccessibilityManager::GotFocus(bool touch_event_context) {
@@ -124,17 +91,11 @@
   return bounds.Contains(touch_point);
 }
 
-void BrowserAccessibilityManager::Remove(BrowserAccessibility* node) {
+void BrowserAccessibilityManager::RemoveNode(BrowserAccessibility* node) {
   if (node == focus_)
     SetFocus(root_, false);
-  int child_id = node->child_id();
   int renderer_id = node->renderer_id();
-  child_id_map_.erase(child_id);
-  DCHECK(renderer_id_to_child_id_map_[renderer_id] == child_id);
-  // Make sure we don't overwrite a newer entry (see UpdateNode for a possible
-  // corner case).
-  if (renderer_id_to_child_id_map_[renderer_id] == child_id)
-    renderer_id_to_child_id_map_.erase(renderer_id);
+  renderer_id_map_.erase(renderer_id);
 }
 
 void BrowserAccessibilityManager::OnAccessibilityNotifications(
@@ -269,12 +230,30 @@
   // In a second pass, call PostInitialize on each one - this must
   // be called after all of each node's children are initialized too.
   for (size_t i = 0; i < nodes.size() && success; i++) {
+    // Note: it's not a bug for nodes[i].id to not be found in the tree.
+    // Consider this example:
+    // Before:
+    // A
+    //   B
+    //     C
+    //   D
+    //     E
+    //       F
+    // After:
+    // A
+    //   B
+    //     C
+    //       F
+    //   D
+    // In this example, F is being reparented. The renderer scans the tree
+    // in order. If can't update "C" to add "F" as a child, when "F" is still
+    // a child of "E". So it first updates "E", to remove "F" as a child.
+    // Later, it ends up deleting "E". So when we get here, "E" was updated as
+    // part of this sequence but it no longer exists in the final tree, so
+    // there's nothing to postinitialize.
     BrowserAccessibility* instance = GetFromRendererID(nodes[i].id);
-    if (instance) {
+    if (instance)
       instance->PostInitialize();
-    } else {
-      success = false;
-    }
   }
 
   if (!success) {
@@ -294,13 +273,15 @@
     BrowserAccessibility* parent,
     int32 renderer_id,
     int32 index_in_parent) {
-  BrowserAccessibility* instance = factory_->Create();
-  int32 child_id = GetNextChildID();
-  instance->InitializeTreeStructure(
-      this, parent, child_id, renderer_id, index_in_parent);
-  child_id_map_[child_id] = instance;
-  renderer_id_to_child_id_map_[renderer_id] = child_id;
-  return instance;
+  BrowserAccessibility* node = factory_->Create();
+  node->InitializeTreeStructure(
+      this, parent, renderer_id, index_in_parent);
+  AddNodeToMap(node);
+  return node;
+}
+
+void BrowserAccessibilityManager::AddNodeToMap(BrowserAccessibility* node) {
+  renderer_id_map_[node->renderer_id()] = node;
 }
 
 bool BrowserAccessibilityManager::UpdateNode(const AccessibilityNodeData& src) {
@@ -326,6 +307,13 @@
     instance = CreateNode(NULL, src.id, 0);
   }
 
+  if (src.bool_attributes.find(
+          AccessibilityNodeData::ATTR_UPDATE_LOCATION_ONLY) !=
+              src.bool_attributes.end()) {
+    instance->SetLocation(src.location);
+    return true;
+  }
+
   // Update all of the node-specific data, like its role, state, name, etc.
   instance->InitializeData(src);
 
diff --git a/content/browser/accessibility/browser_accessibility_manager.h b/content/browser/accessibility/browser_accessibility_manager.h
index a9e7a64..ec1df1b 100644
--- a/content/browser/accessibility/browser_accessibility_manager.h
+++ b/content/browser/accessibility/browser_accessibility_manager.h
@@ -68,18 +68,11 @@
       int type,
       BrowserAccessibility* node) { }
 
-  // Returns the next unique child id.
-  static int32 GetNextChildID();
-
   // Return a pointer to the root of the tree, does not make a new reference.
   BrowserAccessibility* GetRoot();
 
   // Removes a node from the manager.
-  void Remove(BrowserAccessibility* node);
-
-  // Return a pointer to the object corresponding to the given child_id,
-  // does not make a new reference.
-  BrowserAccessibility* GetFromChildID(int32 child_id);
+  virtual void RemoveNode(BrowserAccessibility* node);
 
   // Return a pointer to the object corresponding to the given renderer_id,
   // does not make a new reference.
@@ -163,6 +156,8 @@
       BrowserAccessibilityDelegate* delegate,
       BrowserAccessibilityFactory* factory);
 
+  virtual void AddNodeToMap(BrowserAccessibility* node);
+
  private:
   // The following states keep track of whether or not the
   // on-screen keyboard is allowed to be shown.
@@ -200,9 +195,6 @@
       int32 index_in_parent);
 
  protected:
-  // The next unique id for a BrowserAccessibility instance.
-  static int32 next_child_id_;
-
   // The object that can perform actions on our behalf.
   BrowserAccessibilityDelegate* delegate_;
 
@@ -217,12 +209,8 @@
   // The on-screen keyboard state.
   OnScreenKeyboardState osk_state_;
 
-  // A mapping from the IDs of objects in the renderer, to the child IDs
-  // we use internally here.
-  base::hash_map<int32, int32> renderer_id_to_child_id_map_;
-
-  // A mapping from child IDs to BrowserAccessibility objects.
-  base::hash_map<int32, BrowserAccessibility*> child_id_map_;
+  // A mapping from renderer IDs to BrowserAccessibility objects.
+  base::hash_map<int32, BrowserAccessibility*> renderer_id_map_;
 
   DISALLOW_COPY_AND_ASSIGN(BrowserAccessibilityManager);
 };
diff --git a/content/browser/accessibility/browser_accessibility_manager_win.cc b/content/browser/accessibility/browser_accessibility_manager_win.cc
index ba0dee5..33e4614 100644
--- a/content/browser/accessibility/browser_accessibility_manager_win.cc
+++ b/content/browser/accessibility/browser_accessibility_manager_win.cc
@@ -53,6 +53,22 @@
   return empty_document;
 }
 
+void BrowserAccessibilityManagerWin::AddNodeToMap(BrowserAccessibility* node) {
+  BrowserAccessibilityManager::AddNodeToMap(node);
+  LONG unique_id_win = node->ToBrowserAccessibilityWin()->unique_id_win();
+  unique_id_to_renderer_id_map_[unique_id_win] = node->renderer_id();
+}
+
+void BrowserAccessibilityManagerWin::RemoveNode(BrowserAccessibility* node) {
+  unique_id_to_renderer_id_map_.erase(
+      node->ToBrowserAccessibilityWin()->unique_id_win());
+  BrowserAccessibilityManager::RemoveNode(node);
+  if (node == tracked_scroll_object_) {
+    tracked_scroll_object_->Release();
+    tracked_scroll_object_ = NULL;
+  }
+}
+
 void BrowserAccessibilityManagerWin::NotifyAccessibilityEvent(
     int type,
     BrowserAccessibility* node) {
@@ -135,8 +151,14 @@
       break;
   }
 
+  // Pass the node's unique id in the |child_id| argument to NotifyWinEvent;
+  // the AT client will then call get_accChild on the HWND's accessibility
+  // object and pass it that same id, which we can use to retrieve the
+  // IAccessible for this node.
+  LONG child_id = node->ToBrowserAccessibilityWin()->unique_id_win();
+
   if (event_id != EVENT_MIN)
-    NotifyWinEvent(event_id, parent_hwnd(), OBJID_CLIENT, node->child_id());
+    NotifyWinEvent(event_id, parent_hwnd(), OBJID_CLIENT, child_id);
 
   // If this is a layout complete notification (sent when a container scrolls)
   // and there is a descendant tracked object, send a notification on it.
@@ -144,10 +166,11 @@
   if (type == AccessibilityNotificationLayoutComplete &&
       tracked_scroll_object_ &&
       tracked_scroll_object_->IsDescendantOf(node)) {
-    NotifyWinEvent(IA2_EVENT_VISIBLE_DATA_CHANGED,
-                   parent_hwnd(),
-                   OBJID_CLIENT,
-                   tracked_scroll_object_->child_id());
+    NotifyWinEvent(
+        IA2_EVENT_VISIBLE_DATA_CHANGED,
+        parent_hwnd(),
+        OBJID_CLIENT,
+        tracked_scroll_object_->ToBrowserAccessibilityWin()->unique_id_win());
     tracked_scroll_object_->Release();
     tracked_scroll_object_ = NULL;
   }
@@ -161,4 +184,16 @@
   tracked_scroll_object_->AddRef();
 }
 
+BrowserAccessibilityWin* BrowserAccessibilityManagerWin::GetFromUniqueIdWin(
+    LONG unique_id_win) {
+  base::hash_map<LONG, int32>::iterator iter =
+      unique_id_to_renderer_id_map_.find(unique_id_win);
+  if (iter != unique_id_to_renderer_id_map_.end()) {
+    BrowserAccessibility* result = GetFromRendererID(iter->second);
+    if (result)
+      return result->ToBrowserAccessibilityWin();
+  }
+  return NULL;
+}
+
 }  // namespace content
diff --git a/content/browser/accessibility/browser_accessibility_manager_win.h b/content/browser/accessibility/browser_accessibility_manager_win.h
index 2eefae9..e82f065 100644
--- a/content/browser/accessibility/browser_accessibility_manager_win.h
+++ b/content/browser/accessibility/browser_accessibility_manager_win.h
@@ -38,13 +38,20 @@
   }
 
   // BrowserAccessibilityManager methods
-  virtual void NotifyAccessibilityEvent(int type, BrowserAccessibility* node);
+  virtual void AddNodeToMap(BrowserAccessibility* node);
+  virtual void RemoveNode(BrowserAccessibility* node) OVERRIDE;
+  virtual void NotifyAccessibilityEvent(int type, BrowserAccessibility* node)
+      OVERRIDE;
 
   // Track this object and post a VISIBLE_DATA_CHANGED notification when
   // its container scrolls.
   // TODO(dmazzoni): remove once http://crbug.com/113483 is fixed.
   void TrackScrollingObject(BrowserAccessibilityWin* node);
 
+  // Return a pointer to the object corresponding to the given windows-specific
+  // unique id, does not make a new reference.
+  BrowserAccessibilityWin* GetFromUniqueIdWin(LONG unique_id_win);
+
  private:
   // The closest ancestor HWND.
   HWND parent_hwnd_;
@@ -60,6 +67,10 @@
   // TODO(dmazzoni): remove once http://crbug.com/113483 is fixed.
   BrowserAccessibilityWin* tracked_scroll_object_;
 
+  // A mapping from the Windows-specific unique IDs (unique within the
+  // browser process) to renderer ids within this page.
+  base::hash_map<long, int32> unique_id_to_renderer_id_map_;
+
   DISALLOW_COPY_AND_ASSIGN(BrowserAccessibilityManagerWin);
 };
 
diff --git a/content/browser/accessibility/browser_accessibility_state_impl.cc b/content/browser/accessibility/browser_accessibility_state_impl.cc
index 3cb73fe..92bc94e 100644
--- a/content/browser/accessibility/browser_accessibility_state_impl.cc
+++ b/content/browser/accessibility/browser_accessibility_state_impl.cc
@@ -7,7 +7,9 @@
 #include "base/command_line.h"
 #include "base/metrics/histogram.h"
 #include "base/timer.h"
+#include "content/browser/renderer_host/render_widget_host_impl.h"
 #include "content/public/browser/browser_thread.h"
+#include "content/public/browser/render_process_host.h"
 #include "content/public/common/content_switches.h"
 #include "ui/gfx/sys_color_change_listener.h"
 
@@ -80,11 +82,15 @@
   SetAccessibilityMode(AccessibilityModeComplete);
 }
 
-void BrowserAccessibilityStateImpl::OnAccessibilityEnabledManually() {
+void BrowserAccessibilityStateImpl::EnableAccessibility() {
   // We may want to do something different with this later.
   SetAccessibilityMode(AccessibilityModeComplete);
 }
 
+void BrowserAccessibilityStateImpl::DisableAccessibility() {
+  SetAccessibilityMode(AccessibilityModeOff);
+}
+
 bool BrowserAccessibilityStateImpl::IsAccessibleBrowser() {
   return (accessibility_mode_ == AccessibilityModeComplete);
 }
@@ -117,13 +123,33 @@
 }
 #endif
 
-AccessibilityMode BrowserAccessibilityStateImpl::GetAccessibilityMode() {
-  return accessibility_mode_;
-}
-
 void BrowserAccessibilityStateImpl::SetAccessibilityMode(
     AccessibilityMode mode) {
+  if (accessibility_mode_ == mode)
+    return;
   accessibility_mode_ = mode;
+  for (RenderProcessHost::iterator it(RenderProcessHost::AllHostsIterator());
+       !it.IsAtEnd(); it.Advance()) {
+    RenderProcessHost* render_process_host = it.GetCurrentValue();
+    DCHECK(render_process_host);
+
+    // Ignore processes that don't have a connection, such as crashed tabs.
+    if (!render_process_host->HasConnection())
+      continue;
+
+    for (RenderProcessHost::RenderWidgetHostsIterator rwit(
+             render_process_host->GetRenderWidgetHostsIterator());
+         !rwit.IsAtEnd();
+         rwit.Advance()) {
+      RenderWidgetHost* rwh = const_cast<RenderWidgetHost*>(
+          rwit.GetCurrentValue());
+      DCHECK(rwh);
+      if (!rwh || !rwh->IsRenderView())
+        continue;
+      RenderWidgetHostImpl* rwhi = RenderWidgetHostImpl::From(rwh);
+      rwhi->SetAccessibilityMode(mode);
+    }
+  }
 }
 
 }  // namespace content
diff --git a/content/browser/accessibility/browser_accessibility_state_impl.h b/content/browser/accessibility/browser_accessibility_state_impl.h
index 46621ea..3098341 100644
--- a/content/browser/accessibility/browser_accessibility_state_impl.h
+++ b/content/browser/accessibility/browser_accessibility_state_impl.h
@@ -40,14 +40,15 @@
 
   static BrowserAccessibilityStateImpl* GetInstance();
 
-  virtual void OnAccessibilityEnabledManually() OVERRIDE;
+  virtual void EnableAccessibility() OVERRIDE;
+  virtual void DisableAccessibility() OVERRIDE;
   virtual void OnScreenReaderDetected() OVERRIDE;
   virtual bool IsAccessibleBrowser() OVERRIDE;
   virtual void AddHistogramCallback(base::Closure callback) OVERRIDE;
 
   virtual void UpdateHistogramsForTesting() OVERRIDE;
 
-  AccessibilityMode GetAccessibilityMode();
+  AccessibilityMode accessibility_mode() const { return accessibility_mode_; };
   void SetAccessibilityMode(AccessibilityMode mode);
 
  private:
diff --git a/content/browser/accessibility/browser_accessibility_state_impl_win.cc b/content/browser/accessibility/browser_accessibility_state_impl_win.cc
index 3290355..e968d99 100644
--- a/content/browser/accessibility/browser_accessibility_state_impl_win.cc
+++ b/content/browser/accessibility/browser_accessibility_state_impl_win.cc
@@ -42,7 +42,7 @@
   if (!EnumProcessModules(process, modules, 0, &bytes_required))
     return;
 
-  scoped_array<char> buffer(new char[bytes_required]);
+  scoped_ptr<char[]> buffer(new char[bytes_required]);
   modules = reinterpret_cast<HMODULE*>(buffer.get());
   DWORD ignore;
   if (!EnumProcessModules(process, modules, bytes_required, &ignore))
diff --git a/content/browser/accessibility/browser_accessibility_win.cc b/content/browser/accessibility/browser_accessibility_win.cc
index a7b8843..7f5bc01 100644
--- a/content/browser/accessibility/browser_accessibility_win.cc
+++ b/content/browser/accessibility/browser_accessibility_win.cc
@@ -15,7 +15,9 @@
 #include "base/win/windows_version.h"
 #include "content/browser/accessibility/browser_accessibility_manager_win.h"
 #include "content/common/accessibility_messages.h"
+#include "content/public/common/content_client.h"
 #include "ui/base/accessibility/accessible_text_utils.h"
+#include "ui/base/win/accessibility_ids_win.h"
 #include "ui/base/win/accessibility_misc_utils.h"
 
 namespace content {
@@ -32,6 +34,10 @@
 
 const char16 BrowserAccessibilityWin::kEmbeddedCharacter[] = L"\xfffc";
 
+// static
+LONG BrowserAccessibilityWin::next_unique_id_win_ =
+    base::win::kFirstBrowserAccessibilityManagerAccessibilityId;
+
 //
 // BrowserAccessibilityRelation
 //
@@ -188,6 +194,16 @@
       ia2_state_(0),
       first_time_(true),
       old_ia_state_(0) {
+  // Start unique IDs at -1 and decrement each time, because get_accChild
+  // uses positive IDs to enumerate children, so we use negative IDs to
+  // clearly distinguish between indices and unique IDs.
+  unique_id_win_ = next_unique_id_win_;
+  if (next_unique_id_win_ ==
+          base::win::kLastBrowserAccessibilityManagerAccessibilityId) {
+    next_unique_id_win_ =
+        base::win::kFirstBrowserAccessibilityManagerAccessibilityId;
+  }
+  next_unique_id_win_--;
 }
 
 BrowserAccessibilityWin::~BrowserAccessibilityWin() {
@@ -668,7 +684,7 @@
   if (!unique_id)
     return E_INVALIDARG;
 
-  *unique_id = child_id_;
+  *unique_id = unique_id_win_;
   return S_OK;
 }
 
@@ -837,6 +853,65 @@
 }
 
 //
+// IAccessibleApplication methods.
+//
+
+STDMETHODIMP BrowserAccessibilityWin::get_appName(BSTR* app_name) {
+  // No need to check |instance_active_| because this interface is
+  // global, and doesn't depend on any local state.
+
+  if (!app_name)
+    return E_INVALIDARG;
+
+  std::string product_name = GetContentClient()->GetProduct();
+  *app_name = SysAllocString(UTF8ToUTF16(product_name).c_str());
+  DCHECK(*app_name);
+  return *app_name ? S_OK : E_FAIL;
+}
+
+STDMETHODIMP BrowserAccessibilityWin::get_appVersion(BSTR* app_version) {
+  // No need to check |instance_active_| because this interface is
+  // global, and doesn't depend on any local state.
+
+  if (!app_version)
+    return E_INVALIDARG;
+
+  std::string user_agent = GetContentClient()->GetUserAgent();
+  *app_version = SysAllocString(UTF8ToUTF16(user_agent).c_str());
+  DCHECK(*app_version);
+  return *app_version ? S_OK : E_FAIL;
+}
+
+STDMETHODIMP BrowserAccessibilityWin::get_toolkitName(BSTR* toolkit_name) {
+  // No need to check |instance_active_| because this interface is
+  // global, and doesn't depend on any local state.
+
+  if (!toolkit_name)
+    return E_INVALIDARG;
+
+  // This is hard-coded; all products based on the Chromium engine
+  // will have the same toolkit name, so that assistive technology can
+  // detect any Chrome-based product.
+  *toolkit_name = SysAllocString(L"Chrome");
+  DCHECK(*toolkit_name);
+  return *toolkit_name ? S_OK : E_FAIL;
+}
+
+STDMETHODIMP BrowserAccessibilityWin::get_toolkitVersion(
+    BSTR* toolkit_version) {
+  // No need to check |instance_active_| because this interface is
+  // global, and doesn't depend on any local state.
+
+  if (!toolkit_version)
+    return E_INVALIDARG;
+
+  std::string user_agent = GetContentClient()->GetUserAgent();
+  *toolkit_version = SysAllocString(UTF8ToUTF16(user_agent).c_str());
+  DCHECK(*toolkit_version);
+  return *toolkit_version ? S_OK : E_FAIL;
+}
+
+//
 // IAccessibleImage methods.
 //
 
@@ -2250,7 +2325,7 @@
   *name_space_id = 0;
   *node_value = SysAllocString(value_.c_str());
   *num_children = children_.size();
-  *unique_id = child_id_;
+  *unique_id = unique_id_win_;
 
   if (ia_role_ == ROLE_SYSTEM_DOCUMENT) {
     *node_type = NODETYPE_DOCUMENT;
@@ -2516,6 +2591,7 @@
   if (guidService == IID_IAccessible ||
       guidService == IID_IAccessible2 ||
       guidService == IID_IAccessibleAction ||
+      guidService == IID_IAccessibleApplication ||
       guidService == IID_IAccessibleHyperlink ||
       guidService == IID_IAccessibleHypertext ||
       guidService == IID_IAccessibleImage ||
@@ -2879,17 +2955,17 @@
         (ia_state_ & STATE_SYSTEM_FOCUSED) &&
         !(old_ia_state_ & STATE_SYSTEM_FOCUSED)) {
       ::NotifyWinEvent(EVENT_OBJECT_FOCUS, hwnd,
-                       OBJID_CLIENT, child_id());
+                       OBJID_CLIENT, unique_id_win());
     }
 
     if ((ia_state_ & STATE_SYSTEM_SELECTED) &&
         !(old_ia_state_ & STATE_SYSTEM_SELECTED)) {
       ::NotifyWinEvent(EVENT_OBJECT_SELECTIONADD, hwnd,
-                       OBJID_CLIENT, child_id());
+                       OBJID_CLIENT, unique_id_win());
     } else if (!(ia_state_ & STATE_SYSTEM_SELECTED) &&
                (old_ia_state_ & STATE_SYSTEM_SELECTED)) {
       ::NotifyWinEvent(EVENT_OBJECT_SELECTIONREMOVE, hwnd,
-                       OBJID_CLIENT, child_id());
+                       OBJID_CLIENT, unique_id_win());
     }
 
     old_ia_state_ = ia_state_;
@@ -2910,6 +2986,13 @@
   return true;
 }
 
+void BrowserAccessibilityWin::SetLocation(const gfx::Rect& new_location) {
+  BrowserAccessibility::SetLocation(new_location);
+  HWND hwnd = manager_->ToBrowserAccessibilityManagerWin()->parent_hwnd();
+  ::NotifyWinEvent(EVENT_OBJECT_LOCATIONCHANGE, hwnd,
+                   OBJID_CLIENT, unique_id_win());
+}
+
 BrowserAccessibilityWin* BrowserAccessibilityWin::NewReference() {
   AddRef();
   return this;
@@ -2927,7 +3010,8 @@
   if (child_id >= 1 && child_id <= static_cast<LONG>(children_.size()))
     return children_[child_id - 1]->ToBrowserAccessibilityWin();
 
-  return manager_->GetFromChildID(child_id)->ToBrowserAccessibilityWin();
+  return manager_->ToBrowserAccessibilityManagerWin()->
+      GetFromUniqueIdWin(child_id);
 }
 
 HRESULT BrowserAccessibilityWin::GetStringAttributeAsBstr(
diff --git a/content/browser/accessibility/browser_accessibility_win.h b/content/browser/accessibility/browser_accessibility_win.h
index ce1dbe1..b659932 100644
--- a/content/browser/accessibility/browser_accessibility_win.h
+++ b/content/browser/accessibility/browser_accessibility_win.h
@@ -43,6 +43,7 @@
       public CComObjectRootEx<CComMultiThreadModel>,
       public IDispatchImpl<IAccessible2, &IID_IAccessible2,
                            &LIBID_IAccessible2Lib>,
+      public IAccessibleApplication,
       public IAccessibleHyperlink,
       public IAccessibleHypertext,
       public IAccessibleImage,
@@ -62,6 +63,7 @@
     COM_INTERFACE_ENTRY2(IAccessible, IAccessible2)
     COM_INTERFACE_ENTRY2(IAccessibleText, IAccessibleHypertext)
     COM_INTERFACE_ENTRY(IAccessible2)
+    COM_INTERFACE_ENTRY(IAccessibleApplication)
     COM_INTERFACE_ENTRY(IAccessibleHyperlink)
     COM_INTERFACE_ENTRY(IAccessibleHypertext)
     COM_INTERFACE_ENTRY(IAccessibleImage)
@@ -91,6 +93,10 @@
 
   CONTENT_EXPORT virtual ~BrowserAccessibilityWin();
 
+  // The Windows-specific unique ID, used as the child ID for MSAA methods
+  // like NotifyWinEvent, and as the unique ID for IAccessible2 and ISimpleDOM.
+  LONG unique_id_win() const { return unique_id_win_; }
+
   //
   // BrowserAccessibility methods.
   //
@@ -99,6 +105,8 @@
   CONTENT_EXPORT virtual void NativeAddReference() OVERRIDE;
   CONTENT_EXPORT virtual void NativeReleaseReference() OVERRIDE;
   CONTENT_EXPORT virtual bool IsNative() const OVERRIDE;
+  CONTENT_EXPORT virtual void SetLocation(const gfx::Rect& new_location)
+      OVERRIDE;
 
   //
   // IAccessible methods.
@@ -251,6 +259,17 @@
   }
 
   //
+  // IAccessibleApplication methods.
+  //
+  CONTENT_EXPORT STDMETHODIMP get_appName(BSTR* app_name);
+
+  CONTENT_EXPORT STDMETHODIMP get_appVersion(BSTR* app_version);
+
+  CONTENT_EXPORT STDMETHODIMP get_toolkitName(BSTR* toolkit_name);
+
+  CONTENT_EXPORT STDMETHODIMP get_toolkitVersion(BSTR* toolkit_version);
+
+  //
   // IAccessibleImage methods.
   //
   CONTENT_EXPORT STDMETHODIMP get_description(BSTR* description);
@@ -820,6 +839,11 @@
   // does not make a new reference.
   BrowserAccessibilityWin* GetFromRendererID(int32 renderer_id);
 
+  // Windows-specific unique ID (unique within the browser process),
+  // used for get_accChild, NotifyWinEvent, and as the unique ID for
+  // IAccessible2 and ISimpleDOM.
+  LONG unique_id_win_;
+
   // IAccessible role and state.
   int32 ia_role_;
   int32 ia_state_;
@@ -860,6 +884,9 @@
   // a hyperlink.
   std::vector<int32> hyperlinks_;
 
+  // The next unique id to use.
+  static LONG next_unique_id_win_;
+
   // Give BrowserAccessibility::Create access to our constructor.
   friend class BrowserAccessibility;
   friend class BrowserAccessibilityRelation;
diff --git a/content/browser/accessibility/browser_accessibility_win_unittest.cc b/content/browser/accessibility/browser_accessibility_win_unittest.cc
index cbf5b82..98a5d40 100644
--- a/content/browser/accessibility/browser_accessibility_win_unittest.cc
+++ b/content/browser/accessibility/browser_accessibility_win_unittest.cc
@@ -3,7 +3,9 @@
 // found in the LICENSE file.
 
 #include "base/memory/scoped_ptr.h"
+#include "base/win/scoped_bstr.h"
 #include "base/win/scoped_comptr.h"
+#include "base/win/scoped_variant.h"
 #include "content/browser/accessibility/browser_accessibility_manager.h"
 #include "content/browser/accessibility/browser_accessibility_manager_win.h"
 #include "content/browser/accessibility/browser_accessibility_win.h"
@@ -14,54 +16,95 @@
 namespace content {
 namespace {
 
+
+// CountedBrowserAccessibility ------------------------------------------------
+
 // Subclass of BrowserAccessibilityWin that counts the number of instances.
 class CountedBrowserAccessibility : public BrowserAccessibilityWin {
  public:
-  CountedBrowserAccessibility() { global_obj_count_++; }
-  virtual ~CountedBrowserAccessibility() { global_obj_count_--; }
-  static int global_obj_count_;
+  CountedBrowserAccessibility();
+  virtual ~CountedBrowserAccessibility();
+
+  static void reset() { num_instances_ = 0; }
+  static int num_instances() { return num_instances_; }
+
+ private:
+  static int num_instances_;
+
+  DISALLOW_COPY_AND_ASSIGN(CountedBrowserAccessibility);
 };
 
-int CountedBrowserAccessibility::global_obj_count_ = 0;
+// static
+int CountedBrowserAccessibility::num_instances_ = 0;
+
+CountedBrowserAccessibility::CountedBrowserAccessibility() {
+  ++num_instances_;
+}
+
+CountedBrowserAccessibility::~CountedBrowserAccessibility() {
+  --num_instances_;
+}
+
+
+// CountedBrowserAccessibilityFactory -----------------------------------------
 
 // Factory that creates a CountedBrowserAccessibility.
-class CountedBrowserAccessibilityFactory
-    : public BrowserAccessibilityFactory {
+class CountedBrowserAccessibilityFactory : public BrowserAccessibilityFactory {
  public:
-  virtual ~CountedBrowserAccessibilityFactory() {}
-  virtual BrowserAccessibility* Create() {
-    CComObject<CountedBrowserAccessibility>* instance;
-    HRESULT hr = CComObject<CountedBrowserAccessibility>::CreateInstance(
-        &instance);
-    DCHECK(SUCCEEDED(hr));
-    instance->AddRef();
-    return instance;
-  }
+  CountedBrowserAccessibilityFactory();
+
+ private:
+  virtual ~CountedBrowserAccessibilityFactory();
+
+  virtual BrowserAccessibility* Create() OVERRIDE;
+
+  DISALLOW_COPY_AND_ASSIGN(CountedBrowserAccessibilityFactory);
 };
 
-}  // anonymous namespace
-
-VARIANT CreateI4Variant(LONG value) {
-  VARIANT variant = {0};
-
-  V_VT(&variant) = VT_I4;
-  V_I4(&variant) = value;
-
-  return variant;
+CountedBrowserAccessibilityFactory::CountedBrowserAccessibilityFactory() {
 }
 
+CountedBrowserAccessibilityFactory::~CountedBrowserAccessibilityFactory() {
+}
+
+BrowserAccessibility* CountedBrowserAccessibilityFactory::Create() {
+  CComObject<CountedBrowserAccessibility>* instance;
+  HRESULT hr = CComObject<CountedBrowserAccessibility>::CreateInstance(
+      &instance);
+  DCHECK(SUCCEEDED(hr));
+  instance->AddRef();
+  return instance;
+}
+
+}  // namespace
+
+
+// BrowserAccessibilityTest ---------------------------------------------------
+
 class BrowserAccessibilityTest : public testing::Test {
  public:
-  BrowserAccessibilityTest() {}
+  BrowserAccessibilityTest();
+  virtual ~BrowserAccessibilityTest();
 
  private:
-  virtual void SetUp() {
-    ui::win::CreateATLModuleIfNeeded();
-  }
+  virtual void SetUp() OVERRIDE;
 
   DISALLOW_COPY_AND_ASSIGN(BrowserAccessibilityTest);
 };
 
+BrowserAccessibilityTest::BrowserAccessibilityTest() {
+}
+
+BrowserAccessibilityTest::~BrowserAccessibilityTest() {
+}
+
+void BrowserAccessibilityTest::SetUp() {
+  ui::win::CreateATLModuleIfNeeded();
+}
+
+
+// Actual tests ---------------------------------------------------------------
+
 // Test that BrowserAccessibilityManager correctly releases the tree of
 // BrowserAccessibility instances upon delete.
 TEST_F(BrowserAccessibilityTest, TestNoLeaks) {
@@ -92,52 +135,45 @@
   // AccessibilityNodeData tree and a factory for an instance-counting
   // BrowserAccessibility, and ensure that exactly 3 instances were
   // created. Note that the manager takes ownership of the factory.
-  CountedBrowserAccessibility::global_obj_count_ = 0;
-  BrowserAccessibilityManager* manager =
+  CountedBrowserAccessibility::reset();
+  scoped_ptr<BrowserAccessibilityManager> manager(
       BrowserAccessibilityManager::Create(
-          root,
-          NULL,
-          new CountedBrowserAccessibilityFactory());
+          root, NULL, new CountedBrowserAccessibilityFactory()));
   manager->UpdateNodesForTesting(button, checkbox);
-  ASSERT_EQ(3, CountedBrowserAccessibility::global_obj_count_);
+  ASSERT_EQ(3, CountedBrowserAccessibility::num_instances());
 
   // Delete the manager and test that all 3 instances are deleted.
-  delete manager;
-  ASSERT_EQ(0, CountedBrowserAccessibility::global_obj_count_);
+  manager.reset();
+  ASSERT_EQ(0, CountedBrowserAccessibility::num_instances());
 
   // Construct a manager again, and this time use the IAccessible interface
   // to get new references to two of the three nodes in the tree.
-  manager =
-      BrowserAccessibilityManager::Create(
-          root,
-          NULL,
-          new CountedBrowserAccessibilityFactory());
+  manager.reset(BrowserAccessibilityManager::Create(
+      root, NULL, new CountedBrowserAccessibilityFactory()));
   manager->UpdateNodesForTesting(button, checkbox);
-  ASSERT_EQ(3, CountedBrowserAccessibility::global_obj_count_);
+  ASSERT_EQ(3, CountedBrowserAccessibility::num_instances());
   IAccessible* root_accessible =
       manager->GetRoot()->ToBrowserAccessibilityWin();
   IDispatch* root_iaccessible = NULL;
   IDispatch* child1_iaccessible = NULL;
-  VARIANT var_child;
-  var_child.vt = VT_I4;
-  var_child.lVal = CHILDID_SELF;
-  HRESULT hr = root_accessible->get_accChild(var_child, &root_iaccessible);
+  base::win::ScopedVariant childid_self(CHILDID_SELF);
+  HRESULT hr = root_accessible->get_accChild(childid_self, &root_iaccessible);
   ASSERT_EQ(S_OK, hr);
-  var_child.lVal = 1;
-  hr = root_accessible->get_accChild(var_child, &child1_iaccessible);
+  base::win::ScopedVariant one(1);
+  hr = root_accessible->get_accChild(one, &child1_iaccessible);
   ASSERT_EQ(S_OK, hr);
 
   // Now delete the manager, and only one of the three nodes in the tree
   // should be released.
-  delete manager;
-  ASSERT_EQ(2, CountedBrowserAccessibility::global_obj_count_);
+  manager.reset();
+  ASSERT_EQ(2, CountedBrowserAccessibility::num_instances());
 
   // Release each of our references and make sure that each one results in
   // the instance being deleted as its reference count hits zero.
   root_iaccessible->Release();
-  ASSERT_EQ(1, CountedBrowserAccessibility::global_obj_count_);
+  ASSERT_EQ(1, CountedBrowserAccessibility::num_instances());
   child1_iaccessible->Release();
-  ASSERT_EQ(0, CountedBrowserAccessibility::global_obj_count_);
+  ASSERT_EQ(0, CountedBrowserAccessibility::num_instances());
 }
 
 TEST_F(BrowserAccessibilityTest, TestChildrenChange) {
@@ -160,29 +196,30 @@
   // Construct a BrowserAccessibilityManager with this
   // AccessibilityNodeData tree and a factory for an instance-counting
   // BrowserAccessibility.
-  CountedBrowserAccessibility::global_obj_count_ = 0;
-  BrowserAccessibilityManager* manager =
+  CountedBrowserAccessibility::reset();
+  scoped_ptr<BrowserAccessibilityManager> manager(
       BrowserAccessibilityManager::Create(
-          root,
-          NULL,
-          new CountedBrowserAccessibilityFactory());
+          root, NULL, new CountedBrowserAccessibilityFactory()));
   manager->UpdateNodesForTesting(text);
 
   // Query for the text IAccessible and verify that it returns "old text" as its
   // value.
+  base::win::ScopedVariant one(1);
   base::win::ScopedComPtr<IDispatch> text_dispatch;
   HRESULT hr = manager->GetRoot()->ToBrowserAccessibilityWin()->get_accChild(
-      CreateI4Variant(1), text_dispatch.Receive());
+      one, text_dispatch.Receive());
   ASSERT_EQ(S_OK, hr);
 
   base::win::ScopedComPtr<IAccessible> text_accessible;
   hr = text_dispatch.QueryInterface(text_accessible.Receive());
   ASSERT_EQ(S_OK, hr);
 
-  CComBSTR name;
-  hr = text_accessible->get_accName(CreateI4Variant(CHILDID_SELF), &name);
+  base::win::ScopedVariant childid_self(CHILDID_SELF);
+  base::win::ScopedBstr name;
+  hr = text_accessible->get_accName(childid_self, name.Receive());
   ASSERT_EQ(S_OK, hr);
-  EXPECT_STREQ(L"old text", name.m_str);
+  EXPECT_EQ(L"old text", string16(name));
+  name.Reset();
 
   text_dispatch.Release();
   text_accessible.Release();
@@ -200,24 +237,23 @@
   // Query for the text IAccessible and verify that it now returns "new text"
   // as its value.
   hr = manager->GetRoot()->ToBrowserAccessibilityWin()->get_accChild(
-      CreateI4Variant(1),
-      text_dispatch.Receive());
+      one, text_dispatch.Receive());
   ASSERT_EQ(S_OK, hr);
 
   hr = text_dispatch.QueryInterface(text_accessible.Receive());
   ASSERT_EQ(S_OK, hr);
 
-  hr = text_accessible->get_accName(CreateI4Variant(CHILDID_SELF), &name);
+  hr = text_accessible->get_accName(childid_self, name.Receive());
   ASSERT_EQ(S_OK, hr);
-  EXPECT_STREQ(L"new text", name.m_str);
+  EXPECT_EQ(L"new text", string16(name));
 
   text_dispatch.Release();
   text_accessible.Release();
 
   // Delete the manager and test that all BrowserAccessibility instances are
   // deleted.
-  delete manager;
-  ASSERT_EQ(0, CountedBrowserAccessibility::global_obj_count_);
+  manager.reset();
+  ASSERT_EQ(0, CountedBrowserAccessibility::num_instances());
 }
 
 TEST_F(BrowserAccessibilityTest, TestChildrenChangeNoLeaks) {
@@ -252,14 +288,12 @@
   // AccessibilityNodeData tree and a factory for an instance-counting
   // BrowserAccessibility and ensure that exactly 4 instances were
   // created. Note that the manager takes ownership of the factory.
-  CountedBrowserAccessibility::global_obj_count_ = 0;
-  BrowserAccessibilityManager* manager =
+  CountedBrowserAccessibility::reset();
+  scoped_ptr<BrowserAccessibilityManager> manager(
       BrowserAccessibilityManager::Create(
-          root,
-          NULL,
-          new CountedBrowserAccessibilityFactory());
+          root, NULL, new CountedBrowserAccessibilityFactory()));
   manager->UpdateNodesForTesting(div, text3, text4);
-  ASSERT_EQ(4, CountedBrowserAccessibility::global_obj_count_);
+  ASSERT_EQ(4, CountedBrowserAccessibility::num_instances());
 
   // Notify the BrowserAccessibilityManager that the div node and its children
   // were removed and ensure that only one BrowserAccessibility instance exists.
@@ -271,12 +305,12 @@
   std::vector<AccessibilityHostMsg_NotificationParams> notifications;
   notifications.push_back(param);
   manager->OnAccessibilityNotifications(notifications);
-  ASSERT_EQ(1, CountedBrowserAccessibility::global_obj_count_);
+  ASSERT_EQ(1, CountedBrowserAccessibility::num_instances());
 
   // Delete the manager and test that all BrowserAccessibility instances are
   // deleted.
-  delete manager;
-  ASSERT_EQ(0, CountedBrowserAccessibility::global_obj_count_);
+  manager.reset();
+  ASSERT_EQ(0, CountedBrowserAccessibility::num_instances());
 }
 
 TEST_F(BrowserAccessibilityTest, TestTextBoundaries) {
@@ -293,81 +327,81 @@
   root.state = 0;
   root.child_ids.push_back(11);
 
-  CountedBrowserAccessibility::global_obj_count_ = 0;
-  BrowserAccessibilityManager* manager = BrowserAccessibilityManager::Create(
-      root, NULL,
-      new CountedBrowserAccessibilityFactory());
+  CountedBrowserAccessibility::reset();
+  scoped_ptr<BrowserAccessibilityManager> manager(
+      BrowserAccessibilityManager::Create(
+          root, NULL, new CountedBrowserAccessibilityFactory()));
   manager->UpdateNodesForTesting(text1);
-  ASSERT_EQ(2, CountedBrowserAccessibility::global_obj_count_);
+  ASSERT_EQ(2, CountedBrowserAccessibility::num_instances());
 
   BrowserAccessibilityWin* root_obj =
       manager->GetRoot()->ToBrowserAccessibilityWin();
   BrowserAccessibilityWin* text1_obj =
       root_obj->GetChild(0)->ToBrowserAccessibilityWin();
 
-  BSTR text;
-  long start;
-  long end;
-
   long text1_len;
   ASSERT_EQ(S_OK, text1_obj->get_nCharacters(&text1_len));
 
-  ASSERT_EQ(S_OK, text1_obj->get_text(0, text1_len, &text));
-  ASSERT_EQ(text, text1.value);
-  SysFreeString(text);
+  base::win::ScopedBstr text;
+  ASSERT_EQ(S_OK, text1_obj->get_text(0, text1_len, text.Receive()));
+  ASSERT_EQ(text1.value, string16(text));
+  text.Reset();
 
-  ASSERT_EQ(S_OK, text1_obj->get_text(0, 4, &text));
-  ASSERT_EQ(text, string16(L"One "));
-  SysFreeString(text);
+  ASSERT_EQ(S_OK, text1_obj->get_text(0, 4, text.Receive()));
+  ASSERT_STREQ(L"One ", text);
+  text.Reset();
 
+  long start;
+  long end;
   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, string16(L"n"));
-  SysFreeString(text);
+      1, IA2_TEXT_BOUNDARY_CHAR, &start, &end, text.Receive()));
+  ASSERT_EQ(1, start);
+  ASSERT_EQ(2, end);
+  ASSERT_STREQ(L"n", text);
+  text.Reset();
 
   ASSERT_EQ(S_FALSE, text1_obj->get_textAtOffset(
-      text1_len, IA2_TEXT_BOUNDARY_CHAR, &start, &end, &text));
-  ASSERT_EQ(start, text1_len);
-  ASSERT_EQ(end, text1_len);
+      text1_len, IA2_TEXT_BOUNDARY_CHAR, &start, &end, text.Receive()));
+  ASSERT_EQ(text1_len, start);
+  ASSERT_EQ(text1_len, end);
+  text.Reset();
 
   ASSERT_EQ(S_OK, text1_obj->get_textAtOffset(
-      1, IA2_TEXT_BOUNDARY_WORD, &start, &end, &text));
-  ASSERT_EQ(start, 0);
-  ASSERT_EQ(end, 3);
-  ASSERT_EQ(text, string16(L"One"));
-  SysFreeString(text);
+      1, IA2_TEXT_BOUNDARY_WORD, &start, &end, text.Receive()));
+  ASSERT_EQ(0, start);
+  ASSERT_EQ(3, end);
+  ASSERT_STREQ(L"One", text);
+  text.Reset();
 
   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, string16(L"two"));
-  SysFreeString(text);
+      6, IA2_TEXT_BOUNDARY_WORD, &start, &end, text.Receive()));
+  ASSERT_EQ(4, start);
+  ASSERT_EQ(7, end);
+  ASSERT_STREQ(L"two", text);
+  text.Reset();
 
   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, string16(L"six."));
-  SysFreeString(text);
+      text1_len, IA2_TEXT_BOUNDARY_WORD, &start, &end, text.Receive()));
+  ASSERT_EQ(25, start);
+  ASSERT_EQ(29, end);
+  ASSERT_STREQ(L"six.", text);
+  text.Reset();
 
   ASSERT_EQ(S_OK, text1_obj->get_textAtOffset(
-      1, IA2_TEXT_BOUNDARY_LINE, &start, &end, &text));
-  ASSERT_EQ(start, 0);
-  ASSERT_EQ(end, 15);
-  ASSERT_EQ(text, string16(L"One two three.\n"));
-  SysFreeString(text);
+      1, IA2_TEXT_BOUNDARY_LINE, &start, &end, text.Receive()));
+  ASSERT_EQ(0, start);
+  ASSERT_EQ(15, end);
+  ASSERT_STREQ(L"One two three.\n", text);
+  text.Reset();
 
-  ASSERT_EQ(S_OK, text1_obj->get_text(0, IA2_TEXT_OFFSET_LENGTH, &text));
-  ASSERT_EQ(text, string16(L"One two three.\nFour five six."));
-  SysFreeString(text);
+  ASSERT_EQ(S_OK,
+            text1_obj->get_text(0, IA2_TEXT_OFFSET_LENGTH, text.Receive()));
+  ASSERT_STREQ(L"One two three.\nFour five six.", text);
 
   // Delete the manager and test that all BrowserAccessibility instances are
   // deleted.
-  delete manager;
-  ASSERT_EQ(0, CountedBrowserAccessibility::global_obj_count_);
+  manager.reset();
+  ASSERT_EQ(0, CountedBrowserAccessibility::num_instances());
 }
 
 TEST_F(BrowserAccessibilityTest, TestSimpleHypertext) {
@@ -390,24 +424,22 @@
   root.child_ids.push_back(11);
   root.child_ids.push_back(12);
 
-  CountedBrowserAccessibility::global_obj_count_ = 0;
-  BrowserAccessibilityManager* manager = BrowserAccessibilityManager::Create(
-      root, NULL,
-      new CountedBrowserAccessibilityFactory());
+  CountedBrowserAccessibility::reset();
+  scoped_ptr<BrowserAccessibilityManager> manager(
+      BrowserAccessibilityManager::Create(
+          root, NULL, new CountedBrowserAccessibilityFactory()));
   manager->UpdateNodesForTesting(root, text1, text2);
-  ASSERT_EQ(3, CountedBrowserAccessibility::global_obj_count_);
+  ASSERT_EQ(3, CountedBrowserAccessibility::num_instances());
 
   BrowserAccessibilityWin* root_obj =
       manager->GetRoot()->ToBrowserAccessibilityWin();
 
-  BSTR text;
-
   long text_len;
   ASSERT_EQ(S_OK, root_obj->get_nCharacters(&text_len));
 
-  ASSERT_EQ(S_OK, root_obj->get_text(0, text_len, &text));
-  EXPECT_EQ(text, text1.name + text2.name);
-  SysFreeString(text);
+  base::win::ScopedBstr text;
+  ASSERT_EQ(S_OK, root_obj->get_text(0, text_len, text.Receive()));
+  EXPECT_EQ(text1.name + text2.name, string16(text));
 
   long hyperlink_count;
   ASSERT_EQ(S_OK, root_obj->get_nHyperlinks(&hyperlink_count));
@@ -431,8 +463,8 @@
 
   // Delete the manager and test that all BrowserAccessibility instances are
   // deleted.
-  delete manager;
-  ASSERT_EQ(0, CountedBrowserAccessibility::global_obj_count_);
+  manager.reset();
+  ASSERT_EQ(0, CountedBrowserAccessibility::num_instances());
 }
 
 TEST_F(BrowserAccessibilityTest, TestComplexHypertext) {
@@ -477,28 +509,27 @@
   root.child_ids.push_back(12);
   root.child_ids.push_back(14);
 
-  CountedBrowserAccessibility::global_obj_count_ = 0;
-  BrowserAccessibilityManager* manager = BrowserAccessibilityManager::Create(
-      root, NULL,
-      new CountedBrowserAccessibilityFactory());
+  CountedBrowserAccessibility::reset();
+  scoped_ptr<BrowserAccessibilityManager> manager(
+      BrowserAccessibilityManager::Create(
+          root, NULL, new CountedBrowserAccessibilityFactory()));
   manager->UpdateNodesForTesting(root,
                                  text1, button1, button1_text,
                                  text2, link1, link1_text);
 
-  ASSERT_EQ(7, CountedBrowserAccessibility::global_obj_count_);
+  ASSERT_EQ(7, CountedBrowserAccessibility::num_instances());
 
   BrowserAccessibilityWin* root_obj =
       manager->GetRoot()->ToBrowserAccessibilityWin();
 
-  BSTR text;
-
   long text_len;
   ASSERT_EQ(S_OK, root_obj->get_nCharacters(&text_len));
 
-  ASSERT_EQ(S_OK, root_obj->get_text(0, text_len, &text));
+  base::win::ScopedBstr text;
+  ASSERT_EQ(S_OK, root_obj->get_text(0, text_len, text.Receive()));
   const string16 embed = BrowserAccessibilityWin::kEmbeddedCharacter;
-  EXPECT_EQ(text, text1.name + embed + text2.name + embed);
-  SysFreeString(text);
+  EXPECT_EQ(text1.name + embed + text2.name + embed, string16(text));
+  text.Reset();
 
   long hyperlink_count;
   ASSERT_EQ(S_OK, root_obj->get_nHyperlinks(&hyperlink_count));
@@ -513,18 +544,18 @@
   EXPECT_EQ(S_OK, root_obj->get_hyperlink(0, hyperlink.Receive()));
   EXPECT_EQ(S_OK,
             hyperlink.QueryInterface<IAccessibleText>(hypertext.Receive()));
-  EXPECT_EQ(S_OK, hypertext->get_text(0, 3, &text));
-  EXPECT_EQ(text, string16(L"red"));
-  SysFreeString(text);
+  EXPECT_EQ(S_OK, hypertext->get_text(0, 3, text.Receive()));
+  EXPECT_STREQ(L"red", text);
+  text.Reset();
   hyperlink.Release();
   hypertext.Release();
 
   EXPECT_EQ(S_OK, root_obj->get_hyperlink(1, hyperlink.Receive()));
   EXPECT_EQ(S_OK,
             hyperlink.QueryInterface<IAccessibleText>(hypertext.Receive()));
-  EXPECT_EQ(S_OK, hypertext->get_text(0, 4, &text));
-  EXPECT_EQ(text, string16(L"blue"));
-  SysFreeString(text);
+  EXPECT_EQ(S_OK, hypertext->get_text(0, 4, text.Receive()));
+  EXPECT_STREQ(L"blue", text);
+  text.Reset();
   hyperlink.Release();
   hypertext.Release();
 
@@ -540,22 +571,23 @@
 
   // Delete the manager and test that all BrowserAccessibility instances are
   // deleted.
-  delete manager;
-  ASSERT_EQ(0, CountedBrowserAccessibility::global_obj_count_);
+  manager.reset();
+  ASSERT_EQ(0, CountedBrowserAccessibility::num_instances());
 }
 
 TEST_F(BrowserAccessibilityTest, TestCreateEmptyDocument) {
   // Try creating an empty document with busy state. Readonly is
   // set automatically.
+  CountedBrowserAccessibility::reset();
   const int32 busy_state = 1 << AccessibilityNodeData::STATE_BUSY;
   const int32 readonly_state = 1 << AccessibilityNodeData::STATE_READONLY;
-  scoped_ptr<BrowserAccessibilityManager> manager;
-  manager.reset(new BrowserAccessibilityManagerWin(
-      GetDesktopWindow(),
-      NULL,
-      BrowserAccessibilityManagerWin::GetEmptyDocument(),
-      NULL,
-      new CountedBrowserAccessibilityFactory()));
+  scoped_ptr<BrowserAccessibilityManager> manager(
+      new BrowserAccessibilityManagerWin(
+          GetDesktopWindow(),
+          NULL,
+          BrowserAccessibilityManagerWin::GetEmptyDocument(),
+          NULL,
+          new CountedBrowserAccessibilityFactory()));
 
   // Verify the root is as we expect by default.
   BrowserAccessibility* root = manager->GetRoot();
@@ -622,7 +654,7 @@
 
   // Ensure we properly cleaned up.
   manager.reset();
-  ASSERT_EQ(0, CountedBrowserAccessibility::global_obj_count_);
+  ASSERT_EQ(0, CountedBrowserAccessibility::num_instances());
 }
 
 }  // namespace content
diff --git a/content/browser/accessibility/cross_platform_accessibility_browsertest.cc b/content/browser/accessibility/cross_platform_accessibility_browsertest.cc
index 9fe99c4..ff5789a 100644
--- a/content/browser/accessibility/cross_platform_accessibility_browsertest.cc
+++ b/content/browser/accessibility/cross_platform_accessibility_browsertest.cc
@@ -107,7 +107,7 @@
   if (iter != node.string_attributes.end())
     return UTF16ToUTF8(iter->second);
   else
-    return "";
+    return std::string();
 }
 
 // Convenience method to get the value of a particular AccessibilityNodeData
diff --git a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
index f5f05a9..08635d2 100644
--- a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
+++ b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
@@ -372,8 +372,9 @@
   RunTest(FILE_PATH_LITERAL("hr.html"));
 }
 
+// crbug.com/179717 and crbug.com/224659
 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
-                       MAYBE(AccessibilityIframeCoordinates)) {
+                       DISABLED_AccessibilityIframeCoordinates) {
   RunTest(FILE_PATH_LITERAL("iframe-coordinates.html"));
 }
 
@@ -436,6 +437,14 @@
   RunTest(FILE_PATH_LITERAL("tab.html"));
 }
 
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityTableSimple) {
+  RunTest(FILE_PATH_LITERAL("table-simple.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityTableSpans) {
+  RunTest(FILE_PATH_LITERAL("table-spans.html"));
+}
+
 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
                        AccessibilityToggleButton) {
   RunTest(FILE_PATH_LITERAL("togglebutton.html"));
diff --git a/content/browser/android/browser_jni_registrar.cc b/content/browser/android/browser_jni_registrar.cc
index 1915337..4aa5c86 100644
--- a/content/browser/android/browser_jni_registrar.cc
+++ b/content/browser/android/browser_jni_registrar.cc
@@ -17,6 +17,7 @@
 #include "content/browser/android/download_controller_android_impl.h"
 #include "content/browser/android/interstitial_page_delegate_android.h"
 #include "content/browser/android/load_url_params.h"
+#include "content/browser/android/media_resource_getter_impl.h"
 #include "content/browser/android/surface_texture_peer_browser_impl.h"
 #include "content/browser/android/touch_point.h"
 #include "content/browser/android/tracing_intent_handler.h"
@@ -44,6 +45,8 @@
   { "InterstitialPageDelegateAndroid",
     content::InterstitialPageDelegateAndroid
         ::RegisterInterstitialPageDelegateAndroid },
+  { "MediaResourceGetterImpl",
+    content::MediaResourceGetterImpl::RegisterMediaResourceGetter },
   { "LoadUrlParams", content::RegisterLoadUrlParams },
   { "RegisterImeAdapter", content::RegisterImeAdapter },
   { "TouchPoint", content::RegisterTouchPoint },
diff --git a/content/browser/android/child_process_launcher_android.cc b/content/browser/android/child_process_launcher_android.cc
index 3a954dc..b3fb563 100644
--- a/content/browser/android/child_process_launcher_android.cc
+++ b/content/browser/android/child_process_launcher_android.cc
@@ -8,14 +8,14 @@
 #include "base/android/jni_array.h"
 #include "base/logging.h"
 #include "base/memory/scoped_ptr.h"
-#include "content/browser/android/media_player_manager_android.h"
+#include "content/browser/android/media_player_manager_impl.h"
 #include "content/browser/renderer_host/compositor_impl_android.h"
 #include "content/browser/renderer_host/render_view_host_impl.h"
-#include "content/common/android/scoped_java_surface.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/render_process_host.h"
 #include "jni/ChildProcessLauncher_jni.h"
 #include "media/base/android/media_player_bridge.h"
+#include "ui/gl/android/scoped_java_surface.h"
 
 using base::android::AttachCurrentThread;
 using base::android::ToJavaArrayOfStrings;
@@ -52,7 +52,7 @@
           host->media_player_manager()->GetPlayer(player_id);
       if (player &&
           player != host->media_player_manager()->GetFullscreenPlayer()) {
-        ScopedJavaSurface scoped_surface(surface);
+        gfx::ScopedJavaSurface scoped_surface(surface);
         player->SetVideoSurface(scoped_surface.j_surface().obj());
       }
     }
diff --git a/content/browser/android/content_settings.cc b/content/browser/android/content_settings.cc
index 60a6e23..15600fb 100644
--- a/content/browser/android/content_settings.cc
+++ b/content/browser/android/content_settings.cc
@@ -5,128 +5,19 @@
 #include "content/browser/android/content_settings.h"
 
 #include "base/android/jni_android.h"
-#include "base/android/jni_string.h"
 #include "content/browser/android/content_view_core_impl.h"
 #include "content/browser/renderer_host/render_view_host_delegate.h"
 #include "content/browser/renderer_host/render_view_host_impl.h"
 #include "content/public/browser/web_contents.h"
-#include "content/public/common/content_client.h"
 #include "jni/ContentSettings_jni.h"
-#include "webkit/glue/webkit_glue.h"
 #include "webkit/glue/webpreferences.h"
-#include "webkit/user_agent/user_agent.h"
-
-using base::android::CheckException;
-using base::android::ConvertJavaStringToUTF16;
-using base::android::ConvertUTF16ToJavaString;
-using base::android::ConvertUTF8ToJavaString;
-using base::android::GetClass;
-using base::android::GetFieldID;
-using base::android::GetMethodIDFromClassName;
-using base::android::ScopedJavaLocalRef;
-using webkit_glue::WebPreferences;
 
 namespace content {
 
-struct ContentSettings::FieldIds {
-  // Note on speed. One may think that an approach that reads field values via
-  // JNI is ineffective and should not be used. Please keep in mind that in the
-  // legacy WebView the whole Sync method took <1ms on Xoom, and no one is
-  // expected to modify settings in performance-critical code.
-  FieldIds() { }
-
-  FieldIds(JNIEnv* env) {
-    const char* kStringClassName = "Ljava/lang/String;";
-
-    // FIXME: we should be using a new GetFieldIDFromClassName() with caching.
-    ScopedJavaLocalRef<jclass> clazz(
-        GetClass(env, "org/chromium/content/browser/ContentSettings"));
-    text_size_percent = GetFieldID(env, clazz, "mTextSizePercent", "I");
-    standard_fond_family =
-        GetFieldID(env, clazz, "mStandardFontFamily", kStringClassName);
-    fixed_font_family =
-        GetFieldID(env, clazz, "mFixedFontFamily", kStringClassName);
-    sans_serif_font_family =
-        GetFieldID(env, clazz, "mSansSerifFontFamily", kStringClassName);
-    serif_font_family =
-        GetFieldID(env, clazz, "mSerifFontFamily", kStringClassName);
-    cursive_font_family =
-        GetFieldID(env, clazz, "mCursiveFontFamily", kStringClassName);
-    fantasy_font_family =
-        GetFieldID(env, clazz, "mFantasyFontFamily", kStringClassName);
-    default_text_encoding =
-        GetFieldID(env, clazz, "mDefaultTextEncoding", kStringClassName);
-    user_agent =
-        GetFieldID(env, clazz, "mUserAgent", kStringClassName);
-    minimum_font_size = GetFieldID(env, clazz, "mMinimumFontSize", "I");
-    minimum_logical_font_size =
-        GetFieldID(env, clazz, "mMinimumLogicalFontSize", "I");
-    default_font_size = GetFieldID(env, clazz, "mDefaultFontSize", "I");
-    default_fixed_font_size =
-        GetFieldID(env, clazz, "mDefaultFixedFontSize", "I");
-    load_images_automatically =
-        GetFieldID(env, clazz, "mLoadsImagesAutomatically", "Z");
-    images_enabled =
-        GetFieldID(env, clazz, "mImagesEnabled", "Z");
-    java_script_enabled =
-        GetFieldID(env, clazz, "mJavaScriptEnabled", "Z");
-    allow_universal_access_from_file_urls =
-        GetFieldID(env, clazz, "mAllowUniversalAccessFromFileURLs", "Z");
-    allow_file_access_from_file_urls =
-        GetFieldID(env, clazz, "mAllowFileAccessFromFileURLs", "Z");
-    java_script_can_open_windows_automatically =
-        GetFieldID(env, clazz, "mJavaScriptCanOpenWindowsAutomatically", "Z");
-    support_multiple_windows =
-        GetFieldID(env, clazz, "mSupportMultipleWindows", "Z");
-    dom_storage_enabled =
-        GetFieldID(env, clazz, "mDomStorageEnabled", "Z");
-    database_enabled =
-        GetFieldID(env, clazz, "mDatabaseEnabled", "Z");
-    use_wide_viewport =
-        GetFieldID(env, clazz, "mUseWideViewport", "Z");
-    load_with_overview_mode =
-        GetFieldID(env, clazz, "mLoadWithOverviewMode", "Z");
-    media_playback_requires_user_gesture =
-        GetFieldID(env, clazz, "mMediaPlaybackRequiresUserGesture", "Z");
-    default_video_poster_url =
-        GetFieldID(env, clazz, "mDefaultVideoPosterURL", kStringClassName);
-  }
-
-  // Field ids
-  jfieldID text_size_percent;
-  jfieldID standard_fond_family;
-  jfieldID fixed_font_family;
-  jfieldID sans_serif_font_family;
-  jfieldID serif_font_family;
-  jfieldID cursive_font_family;
-  jfieldID fantasy_font_family;
-  jfieldID default_text_encoding;
-  jfieldID user_agent;
-  jfieldID minimum_font_size;
-  jfieldID minimum_logical_font_size;
-  jfieldID default_font_size;
-  jfieldID default_fixed_font_size;
-  jfieldID load_images_automatically;
-  jfieldID images_enabled;
-  jfieldID java_script_enabled;
-  jfieldID allow_universal_access_from_file_urls;
-  jfieldID allow_file_access_from_file_urls;
-  jfieldID java_script_can_open_windows_automatically;
-  jfieldID support_multiple_windows;
-  jfieldID dom_storage_enabled;
-  jfieldID database_enabled;
-  jfieldID use_wide_viewport;
-  jfieldID load_with_overview_mode;
-  jfieldID media_playback_requires_user_gesture;
-  jfieldID default_video_poster_url;
-};
-
 ContentSettings::ContentSettings(JNIEnv* env,
                          jobject obj,
-                         WebContents* contents,
-                         bool is_master_mode)
+                         WebContents* contents)
     : WebContentsObserver(contents),
-      is_master_mode_(is_master_mode),
       content_settings_(env, obj) {
 }
 
@@ -144,323 +35,24 @@
   return RegisterNativesImpl(env);
 }
 
-void ContentSettings::SyncFromNativeImpl() {
-  JNIEnv* env = base::android::AttachCurrentThread();
-  CHECK(env);
-  if (!field_ids_.get())
-    field_ids_.reset(new FieldIds(env));
-
-  ScopedJavaLocalRef<jobject> scoped_obj = content_settings_.get(env);
-  jobject obj = scoped_obj.obj();
-  if (!obj)
-    return;
+bool ContentSettings::GetJavaScriptEnabled(JNIEnv* env, jobject obj) {
   RenderViewHost* render_view_host = web_contents()->GetRenderViewHost();
-  WebPreferences prefs = render_view_host->GetDelegate()->GetWebkitPrefs();
-
-  Java_ContentSettings_setTextAutosizingEnabled(
-      env, obj, prefs.text_autosizing_enabled);
-  CheckException(env);
-
-  env->SetIntField(
-      obj,
-      field_ids_->text_size_percent,
-      prefs.font_scale_factor * 100.0f);
-  CheckException(env);
-
-  ScopedJavaLocalRef<jstring> str =
-      ConvertUTF16ToJavaString(env,
-          prefs.standard_font_family_map[WebPreferences::kCommonScript]);
-  env->SetObjectField(obj, field_ids_->standard_fond_family, str.obj());
-  CheckException(env);
-
-  str.Reset(ConvertUTF16ToJavaString(env,
-      prefs.fixed_font_family_map[WebPreferences::kCommonScript]));
-  env->SetObjectField(obj, field_ids_->fixed_font_family, str.obj());
-  CheckException(env);
-
-  str.Reset(ConvertUTF16ToJavaString(env,
-      prefs.sans_serif_font_family_map[WebPreferences::kCommonScript]));
-  env->SetObjectField(obj, field_ids_->sans_serif_font_family, str.obj());
-  CheckException(env);
-
-  str.Reset(ConvertUTF16ToJavaString(env,
-      prefs.serif_font_family_map[WebPreferences::kCommonScript]));
-  env->SetObjectField(obj, field_ids_->serif_font_family, str.obj());
-  CheckException(env);
-
-  str.Reset(ConvertUTF16ToJavaString(env,
-      prefs.cursive_font_family_map[WebPreferences::kCommonScript]));
-  env->SetObjectField(obj, field_ids_->cursive_font_family, str.obj());
-  CheckException(env);
-
-  str.Reset(ConvertUTF16ToJavaString(env,
-      prefs.fantasy_font_family_map[WebPreferences::kCommonScript]));
-  env->SetObjectField(obj, field_ids_->fantasy_font_family, str.obj());
-  CheckException(env);
-
-  str.Reset(ConvertUTF8ToJavaString(env, prefs.default_encoding));
-  env->SetObjectField(obj, field_ids_->default_text_encoding, str.obj());
-  CheckException(env);
-
-  str.Reset(ConvertUTF8ToJavaString(env, webkit_glue::GetUserAgent(GURL(""))));
-  env->SetObjectField(obj, field_ids_->user_agent, str.obj());
-  CheckException(env);
-
-  env->SetIntField(obj, field_ids_->minimum_font_size,
-                   prefs.minimum_font_size);
-  CheckException(env);
-
-  env->SetIntField(
-      obj,
-      field_ids_->minimum_logical_font_size, prefs.minimum_logical_font_size);
-  CheckException(env);
-
-  env->SetIntField(obj, field_ids_->default_font_size,
-                   prefs.default_font_size);
-  CheckException(env);
-
-  env->SetIntField(
-      obj, field_ids_->default_fixed_font_size, prefs.default_fixed_font_size);
-  CheckException(env);
-
-  env->SetBooleanField(
-      obj,
-      field_ids_->load_images_automatically, prefs.loads_images_automatically);
-  CheckException(env);
-
-  env->SetBooleanField(
-      obj,
-      field_ids_->images_enabled, prefs.images_enabled);
-  CheckException(env);
-
-  env->SetBooleanField(
-      obj, field_ids_->java_script_enabled, prefs.javascript_enabled);
-  CheckException(env);
-
-  env->SetBooleanField(
-      obj,
-      field_ids_->allow_universal_access_from_file_urls,
-      prefs.allow_universal_access_from_file_urls);
-  CheckException(env);
-
-  env->SetBooleanField(
-      obj,
-      field_ids_->allow_file_access_from_file_urls,
-      prefs.allow_file_access_from_file_urls);
-  CheckException(env);
-
-  env->SetBooleanField(
-      obj,
-      field_ids_->java_script_can_open_windows_automatically,
-      prefs.javascript_can_open_windows_automatically);
-  CheckException(env);
-
-  env->SetBooleanField(
-      obj,
-      field_ids_->support_multiple_windows,
-      prefs.supports_multiple_windows);
-  CheckException(env);
-
-  Java_ContentSettings_setPluginsDisabled(env, obj, !prefs.plugins_enabled);
-  CheckException(env);
-
-  // We don't need to sync AppCache settings to Java, because there are
-  // no getters for them in the API.
-
-  env->SetBooleanField(
-      obj,
-      field_ids_->dom_storage_enabled,
-      prefs.local_storage_enabled);
-  CheckException(env);
-
-  env->SetBooleanField(
-      obj,
-      field_ids_->database_enabled,
-      prefs.databases_enabled);
-  CheckException(env);
-
-  env->SetBooleanField(
-      obj,
-      field_ids_->use_wide_viewport,
-      prefs.viewport_enabled);
-  CheckException(env);
-
-  env->SetBooleanField(
-      obj,
-      field_ids_->load_with_overview_mode,
-      prefs.initialize_at_minimum_page_scale);
-  CheckException(env);
-
-  env->SetBooleanField(
-      obj,
-      field_ids_->media_playback_requires_user_gesture,
-      prefs.user_gesture_required_for_media_playback);
-  CheckException(env);
-
-  str.Reset(
-      ConvertUTF8ToJavaString(env, prefs.default_video_poster_url.spec()));
-  env->SetObjectField(obj, field_ids_->default_video_poster_url, str.obj());
-  CheckException(env);
-}
-
-void ContentSettings::SyncToNativeImpl() {
-  JNIEnv* env = base::android::AttachCurrentThread();
-  CHECK(env);
-  if (!field_ids_.get())
-    field_ids_.reset(new FieldIds(env));
-
-  ScopedJavaLocalRef<jobject> scoped_obj = content_settings_.get(env);
-  jobject obj = scoped_obj.obj();
-  if (!obj)
-    return;
-  RenderViewHost* render_view_host = web_contents()->GetRenderViewHost();
-  WebPreferences prefs = render_view_host->GetDelegate()->GetWebkitPrefs();
-
-  prefs.text_autosizing_enabled =
-      Java_ContentSettings_getTextAutosizingEnabled(env, obj);
-
-  int text_size_percent = env->GetIntField(obj, field_ids_->text_size_percent);
-  if (prefs.text_autosizing_enabled) {
-    prefs.font_scale_factor = text_size_percent / 100.0f;
-    prefs.force_enable_zoom = text_size_percent >= 130;
-  } else {
-    prefs.force_enable_zoom = false;
-  }
-
-  ScopedJavaLocalRef<jstring> str(
-      env, static_cast<jstring>(
-          env->GetObjectField(obj, field_ids_->standard_fond_family)));
-  prefs.standard_font_family_map[WebPreferences::kCommonScript] =
-      ConvertJavaStringToUTF16(str);
-
-  str.Reset(
-      env, static_cast<jstring>(
-          env->GetObjectField(obj, field_ids_->fixed_font_family)));
-  prefs.fixed_font_family_map[WebPreferences::kCommonScript] =
-      ConvertJavaStringToUTF16(str);
-
-  str.Reset(
-      env, static_cast<jstring>(
-          env->GetObjectField(obj, field_ids_->sans_serif_font_family)));
-  prefs.sans_serif_font_family_map[WebPreferences::kCommonScript] =
-      ConvertJavaStringToUTF16(str);
-
-  str.Reset(
-      env, static_cast<jstring>(
-          env->GetObjectField(obj, field_ids_->serif_font_family)));
-  prefs.serif_font_family_map[WebPreferences::kCommonScript] =
-      ConvertJavaStringToUTF16(str);
-
-  str.Reset(
-      env, static_cast<jstring>(
-          env->GetObjectField(obj, field_ids_->cursive_font_family)));
-  prefs.cursive_font_family_map[WebPreferences::kCommonScript] =
-      ConvertJavaStringToUTF16(str);
-
-  str.Reset(
-      env, static_cast<jstring>(
-          env->GetObjectField(obj, field_ids_->fantasy_font_family)));
-  prefs.fantasy_font_family_map[WebPreferences::kCommonScript] =
-      ConvertJavaStringToUTF16(str);
-
-  str.Reset(
-      env, static_cast<jstring>(
-          env->GetObjectField(obj, field_ids_->default_text_encoding)));
-  prefs.default_encoding = ConvertJavaStringToUTF8(str);
-
-  prefs.minimum_font_size =
-      env->GetIntField(obj, field_ids_->minimum_font_size);
-
-  prefs.minimum_logical_font_size =
-      env->GetIntField(obj, field_ids_->minimum_logical_font_size);
-
-  prefs.default_font_size =
-      env->GetIntField(obj, field_ids_->default_font_size);
-
-  prefs.default_fixed_font_size =
-      env->GetIntField(obj, field_ids_->default_fixed_font_size);
-
-  prefs.loads_images_automatically =
-      env->GetBooleanField(obj, field_ids_->load_images_automatically);
-
-  prefs.images_enabled =
-      env->GetBooleanField(obj, field_ids_->images_enabled);
-
-  prefs.javascript_enabled =
-      env->GetBooleanField(obj, field_ids_->java_script_enabled);
-
-  prefs.allow_universal_access_from_file_urls = env->GetBooleanField(
-      obj, field_ids_->allow_universal_access_from_file_urls);
-
-  prefs.allow_file_access_from_file_urls = env->GetBooleanField(
-      obj, field_ids_->allow_file_access_from_file_urls);
-
-  prefs.javascript_can_open_windows_automatically = env->GetBooleanField(
-      obj, field_ids_->java_script_can_open_windows_automatically);
-
-  prefs.supports_multiple_windows = env->GetBooleanField(
-      obj, field_ids_->support_multiple_windows);
-
-  prefs.plugins_enabled = !Java_ContentSettings_getPluginsDisabled(env, obj);
-
-  prefs.application_cache_enabled =
-      Java_ContentSettings_getAppCacheEnabled(env, obj);
-
-  prefs.local_storage_enabled = env->GetBooleanField(
-      obj, field_ids_->dom_storage_enabled);
-
-  prefs.databases_enabled = env->GetBooleanField(
-      obj, field_ids_->database_enabled);
-
-  prefs.viewport_enabled = env->GetBooleanField(
-      obj, field_ids_->use_wide_viewport);
-  prefs.double_tap_to_zoom_enabled = prefs.viewport_enabled;
-
-  prefs.initialize_at_minimum_page_scale = env->GetBooleanField(
-      obj, field_ids_->load_with_overview_mode);
-
-  prefs.user_gesture_required_for_media_playback = env->GetBooleanField(
-      obj, field_ids_->media_playback_requires_user_gesture);
-
-  str.Reset(
-      env, static_cast<jstring>(
-          env->GetObjectField(obj, field_ids_->default_video_poster_url)));
-  prefs.default_video_poster_url = str.obj() ?
-      GURL(ConvertJavaStringToUTF8(str)) : GURL();
-
-  render_view_host->UpdateWebkitPreferences(prefs);
-}
-
-void ContentSettings::SyncFromNative(JNIEnv* env, jobject obj) {
-  SyncFromNativeImpl();
-}
-
-void ContentSettings::SyncToNative(JNIEnv* env, jobject obj) {
-  SyncToNativeImpl();
-}
-
-void ContentSettings::RenderViewCreated(RenderViewHost* render_view_host) {
-  if (is_master_mode_)
-    SyncToNativeImpl();
+  if (!render_view_host)
+    return false;
+  return render_view_host->GetDelegate()->GetWebkitPrefs().javascript_enabled;
 }
 
 void ContentSettings::WebContentsDestroyed(WebContents* web_contents) {
   delete this;
 }
 
-static jint Init(JNIEnv* env, jobject obj, jint nativeContentViewCore,
-                 jboolean is_master_mode) {
+static jint Init(JNIEnv* env, jobject obj, jint nativeContentViewCore) {
   WebContents* web_contents =
       reinterpret_cast<ContentViewCoreImpl*>(nativeContentViewCore)
           ->GetWebContents();
   ContentSettings* content_settings =
-      new ContentSettings(env, obj, web_contents, is_master_mode);
+      new ContentSettings(env, obj, web_contents);
   return reinterpret_cast<jint>(content_settings);
 }
 
-static jstring GetDefaultUserAgent(JNIEnv* env, jclass clazz) {
-  return base::android::ConvertUTF8ToJavaString(
-      env, GetContentClient()->GetUserAgent()).Release();
-}
-
 }  // namespace content
diff --git a/content/browser/android/content_settings.h b/content/browser/android/content_settings.h
index 3a9128e..5c0f9a0 100644
--- a/content/browser/android/content_settings.h
+++ b/content/browser/android/content_settings.h
@@ -8,7 +8,6 @@
 #include <jni.h>
 
 #include "base/android/jni_helper.h"
-#include "base/memory/scoped_ptr.h"
 #include "content/public/browser/web_contents_observer.h"
 
 namespace content {
@@ -16,35 +15,19 @@
 class ContentSettings : public WebContentsObserver {
  public:
   ContentSettings(JNIEnv* env, jobject obj,
-                  WebContents* contents,
-                  bool is_master_mode);
+                  WebContents* contents);
 
   static bool RegisterContentSettings(JNIEnv* env);
 
-  // Synchronizes the Java settings from native settings.
-  void SyncFromNative(JNIEnv* env, jobject obj);
-  // Synchronizes the native settings from Java settings.
-  void SyncToNative(JNIEnv* env, jobject obj);
+  bool GetJavaScriptEnabled(JNIEnv* env, jobject obj);
 
  private:
-  struct FieldIds;
   // Self-deletes when the underlying WebContents is destroyed.
   virtual ~ContentSettings();
 
-  void SyncFromNativeImpl();
-  void SyncToNativeImpl();
-
   // WebContentsObserver overrides:
-  virtual void RenderViewCreated(RenderViewHost* render_view_host) OVERRIDE;
   virtual void WebContentsDestroyed(WebContents* web_contents) OVERRIDE;
 
-  // Determines whether a sync to native should be triggered when a new render
-  // view is created.
-  bool is_master_mode_;
-
-  // Java field references for accessing the values in the Java object.
-  scoped_ptr<FieldIds> field_ids_;
-
   // The Java counterpart to this class.
   JavaObjectWeakGlobalRef content_settings_;
 };
diff --git a/content/browser/android/content_video_view.cc b/content/browser/android/content_video_view.cc
index 158749b..242134b 100644
--- a/content/browser/android/content_video_view.cc
+++ b/content/browser/android/content_video_view.cc
@@ -7,7 +7,7 @@
 #include "base/android/jni_android.h"
 #include "base/command_line.h"
 #include "base/logging.h"
-#include "content/browser/android/media_player_manager_android.h"
+#include "content/browser/android/media_player_manager_impl.h"
 #include "content/common/android/surface_texture_peer.h"
 #include "content/public/common/content_switches.h"
 #include "jni/ContentVideoView_jni.h"
@@ -22,7 +22,7 @@
   return RegisterNativesImpl(env);
 }
 
-ContentVideoView::ContentVideoView(MediaPlayerManagerAndroid* manager)
+ContentVideoView::ContentVideoView(MediaPlayerManagerImpl* manager)
     : manager_(manager) {
 }
 
diff --git a/content/browser/android/content_video_view.h b/content/browser/android/content_video_view.h
index deb5ffc..49b8d05 100644
--- a/content/browser/android/content_video_view.h
+++ b/content/browser/android/content_video_view.h
@@ -15,17 +15,17 @@
 
 namespace content {
 
-class MediaPlayerManagerAndroid;
+class MediaPlayerManagerImpl;
 
 // Native mirror of ContentVideoView.java. This class is responsible for
 // creating the Java video view and pass all the player status change to
 // it. It accepts media control from Java class, and forwards it to
-// MediaPlayerManagerAndroid.
+// MediaPlayerManagerImpl.
 class ContentVideoView {
  public:
   // Construct a ContentVideoView object. The |manager| will handle all the
   // playback controls from the Java class.
-  explicit ContentVideoView(MediaPlayerManagerAndroid* manager);
+  explicit ContentVideoView(MediaPlayerManagerImpl* manager);
   ~ContentVideoView();
 
   static bool RegisterContentVideoView(JNIEnv* env);
@@ -66,7 +66,7 @@
  private:
   // Object that manages the fullscreen media player. It is responsible for
   // handling all the playback controls.
-  MediaPlayerManagerAndroid* manager_;
+  MediaPlayerManagerImpl* manager_;
 
   // Reference to the Java object.
   base::android::ScopedJavaGlobalRef<jobject> j_content_video_view_;
diff --git a/content/browser/android/content_view_core_impl.cc b/content/browser/android/content_view_core_impl.cc
index 68cf0c5..41487dd 100644
--- a/content/browser/android/content_view_core_impl.cc
+++ b/content/browser/android/content_view_core_impl.cc
@@ -16,7 +16,6 @@
 #include "cc/layers/layer.h"
 #include "content/browser/android/interstitial_page_delegate_android.h"
 #include "content/browser/android/load_url_params.h"
-#include "content/browser/android/media_player_manager_android.h"
 #include "content/browser/android/sync_input_event_filter.h"
 #include "content/browser/android/touch_point.h"
 #include "content/browser/renderer_host/compositor_impl_android.h"
@@ -30,6 +29,7 @@
 #include "content/browser/web_contents/navigation_controller_impl.h"
 #include "content/browser/web_contents/navigation_entry_impl.h"
 #include "content/browser/web_contents/web_contents_view_android.h"
+#include "content/common/input_messages.h"
 #include "content/common/view_messages.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/favicon_status.h"
@@ -45,8 +45,9 @@
 #include "third_party/WebKit/Source/WebKit/chromium/public/WebBindings.h"
 #include "third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h"
 #include "third_party/WebKit/Source/WebKit/chromium/public/android/WebInputEventFactory.h"
+#include "ui/android/view_android.h"
+#include "ui/android/window_android.h"
 #include "ui/gfx/android/java_bitmap.h"
-#include "ui/gfx/android/window_android.h"
 #include "ui/gfx/screen.h"
 #include "ui/gfx/size_conversions.h"
 #include "ui/gfx/size_f.h"
@@ -150,15 +151,14 @@
 
 ContentViewCoreImpl::ContentViewCoreImpl(JNIEnv* env, jobject obj,
                                          bool hardware_accelerated,
-                                         bool input_events_delivered_at_vsync,
                                          WebContents* web_contents,
+                                         ui::ViewAndroid* view_android,
                                          ui::WindowAndroid* window_android)
     : java_ref_(env, obj),
       web_contents_(static_cast<WebContentsImpl*>(web_contents)),
       root_layer_(cc::Layer::Create()),
       tab_crashed_(false),
-      input_events_delivered_at_vsync_(input_events_delivered_at_vsync),
-      renderer_frame_pending_(false),
+      view_android_(view_android),
       window_android_(window_android) {
   CHECK(web_contents) <<
       "A ContentViewCoreImpl should be created with a valid WebContents.";
@@ -219,6 +219,9 @@
   notification_registrar_.Add(
       this, NOTIFICATION_WEB_CONTENTS_CONNECTED,
       Source<WebContents>(web_contents_));
+  notification_registrar_.Add(
+      this, NOTIFICATION_WEB_CONTENTS_SWAPPED,
+      Source<WebContents>(web_contents_));
 
   static_cast<WebContentsViewAndroid*>(web_contents_->GetView())->
       SetContentViewCore(this);
@@ -278,6 +281,13 @@
       }
       break;
     }
+    case NOTIFICATION_WEB_CONTENTS_SWAPPED: {
+      JNIEnv* env = AttachCurrentThread();
+      ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
+      if (!obj.is_null()) {
+        Java_ContentViewCore_onWebContentsSwapped(env, obj.obj());
+      }
+    }
   }
 }
 
@@ -300,21 +310,6 @@
   return java_ref_.get(env);
 }
 
-ScopedJavaLocalRef<jobject> ContentViewCoreImpl::GetContainerViewDelegate() {
-  JNIEnv* env = AttachCurrentThread();
-  ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
-  if (obj.is_null())
-    return ScopedJavaLocalRef<jobject>();
-  return Java_ContentViewCore_getContainerViewDelegate(env, obj.obj());
-}
-
-void ContentViewCoreImpl::OnWebPreferencesUpdated() {
-  JNIEnv* env = AttachCurrentThread();
-  ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
-  if (!obj.is_null())
-    Java_ContentViewCore_onWebPreferencesUpdated(env, obj.obj());
-}
-
 jint ContentViewCoreImpl::GetBackgroundColor(JNIEnv* env, jobject obj) {
   RenderWidgetHostViewAndroid* rwhva = GetRenderWidgetHostViewAndroid();
   if (!rwhva)
@@ -348,6 +343,12 @@
 }
 
 void ContentViewCoreImpl::OnTabCrashed() {
+  JNIEnv* env = AttachCurrentThread();
+  ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
+  if (obj.is_null())
+    return;
+  Java_ContentViewCore_resetVSyncNotification(env, obj.obj());
+
   // if tab_crashed_ is already true, just return. e.g. if two tabs share the
   // render process, this will be called for each tab when the render process
   // crashed. If user reload one tab, a new render process is created. It can be
@@ -358,10 +359,6 @@
   if (tab_crashed_)
     return;
   tab_crashed_ = true;
-  JNIEnv* env = AttachCurrentThread();
-  ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
-  if (obj.is_null())
-    return;
   Java_ContentViewCore_onTabCrash(env, obj.obj());
 }
 
@@ -375,7 +372,8 @@
     const gfx::SizeF& content_size,
     const gfx::SizeF& viewport_size,
     const gfx::Vector2dF& controls_offset,
-    const gfx::Vector2dF& content_offset) {
+    const gfx::Vector2dF& content_offset,
+    float overdraw_bottom_height) {
   JNIEnv* env = AttachCurrentThread();
   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
   if (obj.is_null())
@@ -393,7 +391,8 @@
       viewport_size.width(),
       viewport_size.height(),
       controls_offset.y(),
-      content_offset.y());
+      content_offset.y(),
+      overdraw_bottom_height);
 
   for (size_t i = 0; i < update_frame_info_callbacks_.size(); ++i) {
     update_frame_info_callbacks_[i].Run(
@@ -431,7 +430,7 @@
   // given |selected_item| as is.
   ScopedJavaLocalRef<jintArray> selected_array;
   if (multiple) {
-    scoped_array<jint> native_selected_array(new jint[items.size()]);
+    scoped_ptr<jint[]> native_selected_array(new jint[items.size()]);
     size_t selected_count = 0;
     for (size_t i = 0; i < items.size(); ++i) {
       if (items[i].checked)
@@ -600,6 +599,23 @@
       env, obj.obj(), static_cast<jint>(player_id));
 }
 
+void ContentViewCoreImpl::NotifyGeometryChange(int player_id,
+                                               const gfx::RectF& rect) {
+  JNIEnv* env = AttachCurrentThread();
+
+  ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
+  if (obj.is_null())
+    return;
+
+  Java_ContentViewCore_notifyGeometryChange(env,
+                                            obj.obj(),
+                                            static_cast<jint>(player_id),
+                                            static_cast<jfloat>(rect.x()),
+                                            static_cast<jfloat>(rect.y()),
+                                            static_cast<jfloat>(rect.width()),
+                                            static_cast<jfloat>(rect.height()));
+}
+
 gfx::Size ContentViewCoreImpl::GetPhysicalBackingSize() const {
   JNIEnv* env = AttachCurrentThread();
   ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
@@ -615,8 +631,19 @@
   ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
   if (j_obj.is_null())
     return gfx::Size();
-  return gfx::Size(Java_ContentViewCore_getViewportWidthPix(env, j_obj.obj()),
-                   Java_ContentViewCore_getViewportHeightPix(env, j_obj.obj()));
+  return gfx::Size(
+      Java_ContentViewCore_getViewportWidthPix(env, j_obj.obj()),
+      Java_ContentViewCore_getViewportHeightPix(env, j_obj.obj()));
+}
+
+gfx::Size ContentViewCoreImpl::GetViewportSizeOffsetPix() const {
+  JNIEnv* env = AttachCurrentThread();
+  ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
+  if (j_obj.is_null())
+    return gfx::Size();
+  return gfx::Size(
+      Java_ContentViewCore_getViewportSizeOffsetWidthPix(env, j_obj.obj()),
+      Java_ContentViewCore_getViewportSizeOffsetHeightPix(env, j_obj.obj()));
 }
 
 gfx::Size ContentViewCoreImpl::GetViewportSizeDip() const {
@@ -624,6 +651,11 @@
       gfx::ScaleSize(GetViewportSizePix(), 1.0f / GetDpiScale()));
 }
 
+gfx::Size ContentViewCoreImpl::GetViewportSizeOffsetDip() const {
+  return gfx::ToCeiledSize(
+      gfx::ScaleSize(GetViewportSizeOffsetPix(), 1.0f / GetDpiScale()));
+}
+
 float ContentViewCoreImpl::GetOverdrawBottomHeightDip() const {
   JNIEnv* env = AttachCurrentThread();
   ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
@@ -649,17 +681,30 @@
   layer->RemoveFromParent();
 }
 
-void ContentViewCoreImpl::DidProduceRendererFrame() {
-  renderer_frame_pending_ = true;
-}
-
 void ContentViewCoreImpl::LoadUrl(
     NavigationController::LoadURLParams& params) {
   GetWebContents()->GetController().LoadURLWithParams(params);
   tab_crashed_ = false;
 }
 
+void ContentViewCoreImpl::SetVSyncNotificationEnabled(bool enabled) {
+  JNIEnv* env = AttachCurrentThread();
+  ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
+  if (obj.is_null())
+    return;
+  Java_ContentViewCore_setVSyncNotificationEnabled(
+      env, obj.obj(), static_cast<jboolean>(enabled));
+}
+
+ui::ViewAndroid* ContentViewCoreImpl::GetViewAndroid() const {
+  // view_android_ should never be null for Chrome.
+  DCHECK(view_android_);
+  return view_android_;
+}
+
 ui::WindowAndroid* ContentViewCoreImpl::GetWindowAndroid() const {
+  // This should never be NULL for Chrome, but will be NULL for WebView.
+  DCHECK(window_android_);
   return window_android_;
 }
 
@@ -742,22 +787,6 @@
       web_contents_->GetRenderViewHost());
 }
 
-void ContentViewCoreImpl::SetAllUserAgentOverridesInHistory(
-    JNIEnv* env,
-    jobject,
-    jstring user_agent_override) {
-  bool override_used = user_agent_override != NULL;
-  if (override_used) {
-    std::string override =
-        base::android::ConvertJavaStringToUTF8(env, user_agent_override);
-    web_contents_->SetUserAgentOverride(override);
-  }
-
-  const NavigationController& controller = web_contents_->GetController();
-  for (int i = 0; i < controller.GetEntryCount(); ++i)
-    controller.GetEntryAtIndex(i)->SetIsOverridingUserAgent(override_used);
-}
-
 ScopedJavaLocalRef<jstring> ContentViewCoreImpl::GetURL(
     JNIEnv* env, jobject) const {
   return ConvertUTF8ToJavaString(env, GetWebContents()->GetURL().spec());
@@ -809,7 +838,6 @@
     WebKit::WebTouchEvent event;
     TouchPoint::BuildWebTouchEvent(env, type, time_ms, GetDpiScale(), pts,
         event);
-    UpdateVSyncFlagOnInputEvent(&event);
     rwhv->SendTouchEvent(event);
     return true;
   }
@@ -832,6 +860,14 @@
   input_event_filter_->SetInputHandler(input_handler);
 }
 
+void ContentViewCoreImpl::RequestContentClipping(
+    const gfx::Rect& clipping,
+    const gfx::Size& content_size) {
+  RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
+  if (rwhv)
+    rwhv->RequestContentClipping(clipping, content_size);
+}
+
 jboolean ContentViewCoreImpl::SendMouseMoveEvent(JNIEnv* env,
                                                  jobject obj,
                                                  jlong time_ms,
@@ -876,27 +912,19 @@
 }
 
 WebGestureEvent ContentViewCoreImpl::MakeGestureEvent(
-    WebInputEvent::Type type, long time_ms, float x, float y) const {
+    WebInputEvent::Type type, long time_ms, float x, float y,
+    InputEventVSyncStatus vsync_status) const {
   WebGestureEvent event;
   event.type = type;
   event.x = x / GetDpiScale();
   event.y = y / GetDpiScale();
   event.timeStampSeconds = time_ms / 1000.0;
   event.sourceDevice = WebGestureEvent::Touchscreen;
-  UpdateVSyncFlagOnInputEvent(&event);
+  if (vsync_status == LAST_INPUT_EVENT_FOR_VSYNC)
+    event.modifiers |= WebInputEvent::IsLastInputEventForCurrentVSync;
   return event;
 }
 
-void ContentViewCoreImpl::UpdateVSyncFlagOnInputEvent(
-    WebKit::WebInputEvent* event) const {
-  if (!input_events_delivered_at_vsync_)
-    return;
-  if (event->type == WebInputEvent::GestureScrollUpdate ||
-      event->type == WebInputEvent::GesturePinchUpdate ||
-      event->type == WebInputEvent::TouchMove)
-    event->modifiers |= WebInputEvent::IsLastInputEventForCurrentVSync;
-}
-
 void ContentViewCoreImpl::SendGestureEvent(
     const WebKit::WebGestureEvent& event) {
   RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
@@ -907,20 +935,26 @@
 void ContentViewCoreImpl::ScrollBegin(JNIEnv* env, jobject obj, jlong time_ms,
                                       jfloat x, jfloat y) {
   WebGestureEvent event = MakeGestureEvent(
-      WebInputEvent::GestureScrollBegin, time_ms, x, y);
+      WebInputEvent::GestureScrollBegin, time_ms, x, y,
+      NOT_LAST_INPUT_EVENT_FOR_VSYNC);
   SendGestureEvent(event);
 }
 
 void ContentViewCoreImpl::ScrollEnd(JNIEnv* env, jobject obj, jlong time_ms) {
   WebGestureEvent event = MakeGestureEvent(
-      WebInputEvent::GestureScrollEnd, time_ms, 0, 0);
+      WebInputEvent::GestureScrollEnd, time_ms, 0, 0,
+      NOT_LAST_INPUT_EVENT_FOR_VSYNC);
   SendGestureEvent(event);
 }
 
 void ContentViewCoreImpl::ScrollBy(JNIEnv* env, jobject obj, jlong time_ms,
-                                   jfloat x, jfloat y, jfloat dx, jfloat dy) {
+                                   jfloat x, jfloat y, jfloat dx, jfloat dy,
+                                   jboolean last_input_event_for_vsync) {
+  InputEventVSyncStatus vsync_status =
+      last_input_event_for_vsync ? LAST_INPUT_EVENT_FOR_VSYNC
+                                 : NOT_LAST_INPUT_EVENT_FOR_VSYNC;
   WebGestureEvent event = MakeGestureEvent(
-      WebInputEvent::GestureScrollUpdate, time_ms, x, y);
+      WebInputEvent::GestureScrollUpdate, time_ms, x, y, vsync_status);
   event.data.scrollUpdate.deltaX = -dx / GetDpiScale();
   event.data.scrollUpdate.deltaY = -dy / GetDpiScale();
 
@@ -930,7 +964,8 @@
 void ContentViewCoreImpl::FlingStart(JNIEnv* env, jobject obj, jlong time_ms,
                                      jfloat x, jfloat y, jfloat vx, jfloat vy) {
   WebGestureEvent event = MakeGestureEvent(
-      WebInputEvent::GestureFlingStart, time_ms, x, y);
+      WebInputEvent::GestureFlingStart, time_ms, x, y,
+      NOT_LAST_INPUT_EVENT_FOR_VSYNC);
 
   // Velocity should not be scaled by DIP since that interacts poorly with the
   // deceleration constants.  The DIP scaling is done on the renderer.
@@ -942,7 +977,8 @@
 
 void ContentViewCoreImpl::FlingCancel(JNIEnv* env, jobject obj, jlong time_ms) {
   WebGestureEvent event = MakeGestureEvent(
-      WebInputEvent::GestureFlingCancel, time_ms, 0, 0);
+      WebInputEvent::GestureFlingCancel, time_ms, 0, 0,
+      NOT_LAST_INPUT_EVENT_FOR_VSYNC);
   SendGestureEvent(event);
 }
 
@@ -950,7 +986,8 @@
                                     jfloat x, jfloat y,
                                     jboolean disambiguation_popup_tap) {
   WebGestureEvent event = MakeGestureEvent(
-      WebInputEvent::GestureTap, time_ms, x, y);
+      WebInputEvent::GestureTap, time_ms, x, y,
+      NOT_LAST_INPUT_EVENT_FOR_VSYNC);
 
   event.data.tap.tapCount = 1;
   if (!disambiguation_popup_tap) {
@@ -966,7 +1003,8 @@
                                          jlong time_ms,
                                          jfloat x, jfloat y) {
   WebGestureEvent event = MakeGestureEvent(
-      WebInputEvent::GestureTapDown, time_ms, x, y);
+      WebInputEvent::GestureTapDown, time_ms, x, y,
+      NOT_LAST_INPUT_EVENT_FOR_VSYNC);
   SendGestureEvent(event);
 }
 
@@ -976,14 +1014,16 @@
                                           jfloat x,
                                           jfloat y) {
   WebGestureEvent event = MakeGestureEvent(
-      WebInputEvent::GestureTapCancel, time_ms, x, y);
+      WebInputEvent::GestureTapCancel, time_ms, x, y,
+      NOT_LAST_INPUT_EVENT_FOR_VSYNC);
   SendGestureEvent(event);
 }
 
 void ContentViewCoreImpl::DoubleTap(JNIEnv* env, jobject obj, jlong time_ms,
                                     jfloat x, jfloat y) {
   WebGestureEvent event = MakeGestureEvent(
-      WebInputEvent::GestureDoubleTap, time_ms, x, y);
+      WebInputEvent::GestureDoubleTap, time_ms, x, y,
+      NOT_LAST_INPUT_EVENT_FOR_VSYNC);
   SendGestureEvent(event);
 }
 
@@ -991,7 +1031,8 @@
                                     jfloat x, jfloat y,
                                     jboolean disambiguation_popup_tap) {
   WebGestureEvent event = MakeGestureEvent(
-      WebInputEvent::GestureLongPress, time_ms, x, y);
+      WebInputEvent::GestureLongPress, time_ms, x, y,
+      NOT_LAST_INPUT_EVENT_FOR_VSYNC);
 
   if (!disambiguation_popup_tap) {
     const float touch_padding_dip = GetTouchPaddingDip();
@@ -1006,7 +1047,8 @@
                                   jfloat x, jfloat y,
                                   jboolean disambiguation_popup_tap) {
   WebGestureEvent event = MakeGestureEvent(
-      WebInputEvent::GestureLongTap, time_ms, x, y);
+      WebInputEvent::GestureLongTap, time_ms, x, y,
+      NOT_LAST_INPUT_EVENT_FOR_VSYNC);
 
   if (!disambiguation_popup_tap) {
     const float touch_padding_dip = GetTouchPaddingDip();
@@ -1020,21 +1062,28 @@
 void ContentViewCoreImpl::PinchBegin(JNIEnv* env, jobject obj, jlong time_ms,
                                      jfloat x, jfloat y) {
   WebGestureEvent event = MakeGestureEvent(
-      WebInputEvent::GesturePinchBegin, time_ms, x, y);
+      WebInputEvent::GesturePinchBegin, time_ms, x, y,
+      NOT_LAST_INPUT_EVENT_FOR_VSYNC);
   SendGestureEvent(event);
 }
 
 void ContentViewCoreImpl::PinchEnd(JNIEnv* env, jobject obj, jlong time_ms) {
   WebGestureEvent event = MakeGestureEvent(
-      WebInputEvent::GesturePinchEnd, time_ms, 0, 0);
+      WebInputEvent::GesturePinchEnd, time_ms, 0, 0,
+      NOT_LAST_INPUT_EVENT_FOR_VSYNC);
   SendGestureEvent(event);
 }
 
 void ContentViewCoreImpl::PinchBy(JNIEnv* env, jobject obj, jlong time_ms,
                                   jfloat anchor_x, jfloat anchor_y,
-                                  jfloat delta) {
+                                  jfloat delta,
+                                  jboolean last_input_event_for_vsync) {
+  InputEventVSyncStatus vsync_status =
+      last_input_event_for_vsync ? LAST_INPUT_EVENT_FOR_VSYNC
+                                 : NOT_LAST_INPUT_EVENT_FOR_VSYNC;
   WebGestureEvent event = MakeGestureEvent(
-      WebInputEvent::GesturePinchUpdate, time_ms, anchor_x, anchor_y);
+      WebInputEvent::GesturePinchUpdate, time_ms, anchor_x, anchor_y,
+      vsync_status);
   event.data.pinchUpdate.scale = delta;
 
   SendGestureEvent(event);
@@ -1162,6 +1211,15 @@
       base::TimeDelta::FromMicroseconds(interval_micros));
 }
 
+void ContentViewCoreImpl::OnVSync(JNIEnv* env, jobject /* obj */,
+                                  jlong frame_time_micros) {
+  RenderWidgetHostViewAndroid* view = GetRenderWidgetHostViewAndroid();
+  if (!view)
+    return;
+
+  view->SendVSync(base::TimeTicks::FromInternalValue(frame_time_micros));
+}
+
 jboolean ContentViewCoreImpl::PopulateBitmapFromCompositor(JNIEnv* env,
                                                            jobject obj,
                                                            jobject jbitmap) {
@@ -1194,34 +1252,31 @@
   return web_contents_->ShowingInterstitialPage();
 }
 
-jboolean ContentViewCoreImpl::ConsumePendingRendererFrame(JNIEnv* env,
-                                                          jobject obj) {
-  bool had_pending_frame = renderer_frame_pending_;
-  renderer_frame_pending_ = false;
-  return had_pending_frame;
-}
-
 void ContentViewCoreImpl::AttachExternalVideoSurface(JNIEnv* env,
                                                      jobject obj,
                                                      jint player_id,
                                                      jobject jsurface) {
+#if defined(GOOGLE_TV)
   RenderViewHostImpl* rvhi = static_cast<RenderViewHostImpl*>(
       web_contents_->GetRenderViewHost());
   if (rvhi && rvhi->media_player_manager()) {
     rvhi->media_player_manager()->AttachExternalVideoSurface(
         static_cast<int>(player_id), jsurface);
   }
+#endif
 }
 
 void ContentViewCoreImpl::DetachExternalVideoSurface(JNIEnv* env,
                                                      jobject obj,
                                                      jint player_id) {
+#if defined(GOOGLE_TV)
   RenderViewHostImpl* rvhi = static_cast<RenderViewHostImpl*>(
       web_contents_->GetRenderViewHost());
   if (rvhi && rvhi->media_player_manager()) {
     rvhi->media_player_manager()->DetachExternalVideoSurface(
         static_cast<int>(player_id));
   }
+#endif
 }
 
 jboolean ContentViewCoreImpl::IsRenderWidgetHostViewReady(JNIEnv* env,
@@ -1235,10 +1290,16 @@
   host->ExitFullscreen();
 }
 
-void ContentViewCoreImpl::EnableHidingTopControls(JNIEnv* env, jobject obj,
-                                                  bool enable) {
+void ContentViewCoreImpl::UpdateTopControlsState(JNIEnv* env,
+                                                 jobject obj,
+                                                 bool enable_hiding,
+                                                 bool enable_showing,
+                                                 bool animate) {
   RenderViewHost* host = web_contents_->GetRenderViewHost();
-  host->Send(new ViewMsg_EnableHidingTopControls(host->GetRoutingID(), enable));
+  host->Send(new ViewMsg_UpdateTopControlsState(host->GetRoutingID(),
+                                                enable_hiding,
+                                                enable_showing,
+                                                animate));
 }
 
 void ContentViewCoreImpl::ShowImeIfNeeded(JNIEnv* env, jobject obj) {
@@ -1249,8 +1310,8 @@
 void ContentViewCoreImpl::ScrollFocusedEditableNodeIntoView(JNIEnv* env,
                                                             jobject obj) {
   RenderViewHost* host = web_contents_->GetRenderViewHost();
-  host->Send(new ViewMsg_ScrollFocusedEditableNodeIntoRect(host->GetRoutingID(),
-                                                           gfx::Rect()));
+  host->Send(new InputMsg_ScrollFocusedEditableNodeIntoRect(
+      host->GetRoutingID(), gfx::Rect()));
 }
 
 namespace {
@@ -1283,13 +1344,13 @@
 
 int ContentViewCoreImpl::GetNavigationHistory(JNIEnv* env,
                                               jobject obj,
-                                              jobject context) {
+                                              jobject history) {
   // Iterate through navigation entries to populate the list
   const NavigationController& controller = web_contents_->GetController();
   int count = controller.GetEntryCount();
   for (int i = 0; i < count; ++i) {
     AddNavigationEntryToHistory(
-        env, obj, context, controller.GetEntryAtIndex(i), i);
+        env, obj, history, controller.GetEntryAtIndex(i), i);
   }
 
   return controller.GetCurrentEntryIndex();
@@ -1297,7 +1358,7 @@
 
 void ContentViewCoreImpl::GetDirectedNavigationHistory(JNIEnv* env,
                                                        jobject obj,
-                                                       jobject context,
+                                                       jobject history,
                                                        jboolean is_forward,
                                                        jint max_entries) {
   // Iterate through navigation entries to populate the list
@@ -1312,11 +1373,20 @@
       break;
 
     AddNavigationEntryToHistory(
-        env, obj, context, controller.GetEntryAtIndex(i), i);
+        env, obj, history, controller.GetEntryAtIndex(i), i);
     num_added++;
   }
 }
 
+ScopedJavaLocalRef<jstring>
+ContentViewCoreImpl::GetOriginalUrlForActiveNavigationEntry(JNIEnv* env,
+                                                            jobject obj) {
+  NavigationEntry* entry = web_contents_->GetController().GetActiveEntry();
+  if (entry == NULL)
+    return ScopedJavaLocalRef<jstring>(env, NULL);
+  return ConvertUTF8ToJavaString(env, entry->GetOriginalRequestURL().spec());
+}
+
 int ContentViewCoreImpl::GetNativeImeAdapter(JNIEnv* env, jobject obj) {
   RenderWidgetHostViewAndroid* rwhva = GetRenderWidgetHostViewAndroid();
   if (!rwhva)
@@ -1446,14 +1516,15 @@
 
 // This is called for each ContentView.
 jint Init(JNIEnv* env, jobject obj,
-          jboolean input_events_delivered_at_vsync,
           jboolean hardware_accelerated,
           jint native_web_contents,
-          jint native_window) {
+          jint view_android,
+          jint window_android) {
   ContentViewCoreImpl* view = new ContentViewCoreImpl(
-      env, obj, input_events_delivered_at_vsync, hardware_accelerated,
+      env, obj, hardware_accelerated,
       reinterpret_cast<WebContents*>(native_web_contents),
-      reinterpret_cast<ui::WindowAndroid*>(native_window));
+      reinterpret_cast<ui::ViewAndroid*>(view_android),
+      reinterpret_cast<ui::WindowAndroid*>(window_android));
   return reinterpret_cast<jint>(view);
 }
 
diff --git a/content/browser/android/content_view_core_impl.h b/content/browser/android/content_view_core_impl.h
index ba17590..414f5cc 100644
--- a/content/browser/android/content_view_core_impl.h
+++ b/content/browser/android/content_view_core_impl.h
@@ -21,10 +21,12 @@
 #include "googleurl/src/gurl.h"
 #include "third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h"
 #include "ui/gfx/rect.h"
+#include "ui/gfx/rect_f.h"
 
 struct WebMenuItem;
 
 namespace ui {
+class ViewAndroid;
 class WindowAndroid;
 }
 
@@ -40,19 +42,17 @@
   ContentViewCoreImpl(JNIEnv* env,
                       jobject obj,
                       bool hardware_accelerated,
-                      bool input_events_delivered_at_vsync,
                       WebContents* web_contents,
+                      ui::ViewAndroid* view_android,
                       ui::WindowAndroid* window_android);
 
   // ContentViewCore implementation.
   virtual base::android::ScopedJavaLocalRef<jobject> GetJavaObject() OVERRIDE;
-  virtual base::android::ScopedJavaLocalRef<jobject> GetContainerViewDelegate()
-      OVERRIDE;
   virtual WebContents* GetWebContents() const OVERRIDE;
+  virtual ui::ViewAndroid* GetViewAndroid() const OVERRIDE;
   virtual ui::WindowAndroid* GetWindowAndroid() const OVERRIDE;
   virtual scoped_refptr<cc::Layer> GetLayer() const OVERRIDE;
   virtual void LoadUrl(NavigationController::LoadURLParams& params) OVERRIDE;
-  virtual void OnWebPreferencesUpdated() OVERRIDE;
   virtual jint GetCurrentRenderProcessId(JNIEnv* env, jobject obj) OVERRIDE;
   virtual void ShowPastePopup(int x, int y) OVERRIDE;
   virtual unsigned int GetScaledContentTexture(
@@ -61,6 +61,8 @@
   virtual float GetDpiScale() const OVERRIDE;
   virtual void SetInputHandler(
       WebKit::WebCompositorInputHandler* input_handler) OVERRIDE;
+  virtual void RequestContentClipping(const gfx::Rect& clipping,
+                                      const gfx::Size& content_size) OVERRIDE;
   virtual void AddFrameInfoCallback(
       const UpdateFrameInfoCallback& callback) OVERRIDE;
   virtual void RemoveFrameInfoCallback(
@@ -87,10 +89,6 @@
       jstring base_url_for_data_url,
       jstring virtual_url_for_data_url,
       jboolean can_load_local_resources);
-  void SetAllUserAgentOverridesInHistory(
-      JNIEnv* env,
-      jobject obj,
-      jstring user_agent_override);
   base::android::ScopedJavaLocalRef<jstring> GetURL(JNIEnv* env, jobject) const;
   base::android::ScopedJavaLocalRef<jstring> GetTitle(
       JNIEnv* env, jobject obj) const;
@@ -116,7 +114,8 @@
   void ScrollBegin(JNIEnv* env, jobject obj, jlong time_ms, jfloat x, jfloat y);
   void ScrollEnd(JNIEnv* env, jobject obj, jlong time_ms);
   void ScrollBy(JNIEnv* env, jobject obj, jlong time_ms,
-                jfloat x, jfloat y, jfloat dx, jfloat dy);
+                jfloat x, jfloat y, jfloat dx, jfloat dy,
+                jboolean last_input_event_for_vsync);
   void FlingStart(JNIEnv* env, jobject obj, jlong time_ms,
                   jfloat x, jfloat y, jfloat vx, jfloat vy);
   void FlingCancel(JNIEnv* env, jobject obj, jlong time_ms);
@@ -138,8 +137,8 @@
   void PinchBegin(JNIEnv* env, jobject obj, jlong time_ms, jfloat x, jfloat y);
   void PinchEnd(JNIEnv* env, jobject obj, jlong time_ms);
   void PinchBy(JNIEnv* env, jobject obj, jlong time_ms,
-               jfloat x, jfloat y,
-               jfloat delta);
+               jfloat x, jfloat y, jfloat delta,
+               jboolean last_input_event_for_vsync);
   void SelectBetweenCoordinates(JNIEnv* env, jobject obj,
                                 jfloat x1, jfloat y1,
                                 jfloat x2, jfloat y2);
@@ -186,21 +185,28 @@
                               jclass safe_annotation_clazz,
                               jobject retained_object_set);
   void RemoveJavascriptInterface(JNIEnv* env, jobject obj, jstring name);
-  int GetNavigationHistory(JNIEnv* env, jobject obj, jobject context);
+  int GetNavigationHistory(JNIEnv* env, jobject obj, jobject history);
   void GetDirectedNavigationHistory(JNIEnv* env,
                                     jobject obj,
-                                    jobject context,
+                                    jobject history,
                                     jboolean is_forward,
                                     jint max_entries);
+  base::android::ScopedJavaLocalRef<jstring>
+      GetOriginalUrlForActiveNavigationEntry(JNIEnv* env, jobject obj);
   void UpdateVSyncParameters(JNIEnv* env, jobject obj, jlong timebase_micros,
                              jlong interval_micros);
+  void OnVSync(JNIEnv* env, jobject /* obj */, jlong frame_time_micros);
   jboolean PopulateBitmapFromCompositor(JNIEnv* env,
                                         jobject obj,
                                         jobject jbitmap);
   void WasResized(JNIEnv* env, jobject obj);
   jboolean IsRenderWidgetHostViewReady(JNIEnv* env, jobject obj);
   void ExitFullscreen(JNIEnv* env, jobject obj);
-  void EnableHidingTopControls(JNIEnv* env, jobject obj, bool enable);
+  void UpdateTopControlsState(JNIEnv* env,
+                              jobject obj,
+                              bool enable_hiding,
+                              bool enable_showing,
+                              bool animate);
   void ShowImeIfNeeded(JNIEnv* env, jobject obj);
 
   void ShowInterstitialPage(JNIEnv* env,
@@ -209,8 +215,6 @@
                             jint delegate);
   jboolean IsShowingInterstitialPage(JNIEnv* env, jobject obj);
 
-  jboolean ConsumePendingRendererFrame(JNIEnv* env, jobject obj);
-
   void AttachExternalVideoSurface(JNIEnv* env,
                                   jobject obj,
                                   jint player_id,
@@ -238,7 +242,8 @@
                        const gfx::SizeF& content_size,
                        const gfx::SizeF& viewport_size,
                        const gfx::Vector2dF& controls_offset,
-                       const gfx::Vector2dF& content_offset);
+                       const gfx::Vector2dF& content_offset,
+                       float overdraw_bottom_height);
 
   void UpdateImeAdapter(int native_ime_adapter, int text_input_type,
                         const std::string& text,
@@ -265,6 +270,7 @@
       const gfx::Rect& target_rect, const SkBitmap& zoomed_bitmap);
 
   void RequestExternalVideoSurface(int player_id);
+  void NotifyGeometryChange(int player_id, const gfx::RectF& rect);
 
   // --------------------------------------------------------------------------
   // Methods called from native code
@@ -272,15 +278,21 @@
 
   gfx::Size GetPhysicalBackingSize() const;
   gfx::Size GetViewportSizeDip() const;
+  gfx::Size GetViewportSizeOffsetDip() const;
   float GetOverdrawBottomHeightDip() const;
 
   InputEventAckState FilterInputEvent(const WebKit::WebInputEvent& input_event);
 
   void AttachLayer(scoped_refptr<cc::Layer> layer);
   void RemoveLayer(scoped_refptr<cc::Layer> layer);
-  void DidProduceRendererFrame();
+  void SetVSyncNotificationEnabled(bool enabled);
 
  private:
+  enum InputEventVSyncStatus {
+      NOT_LAST_INPUT_EVENT_FOR_VSYNC,
+      LAST_INPUT_EVENT_FOR_VSYNC
+  };
+
   class ContentViewUserData;
 
   friend class ContentViewUserData;
@@ -303,11 +315,10 @@
 
   WebKit::WebGestureEvent MakeGestureEvent(
       WebKit::WebInputEvent::Type type, long time_ms,
-      float xPix, float yPix) const;
+      float x, float y, InputEventVSyncStatus vsync_status) const;
 
   gfx::Size GetViewportSizePix() const;
-
-  void UpdateVSyncFlagOnInputEvent(WebKit::WebInputEvent* event) const;
+  gfx::Size GetViewportSizeOffsetPix() const;
 
   void DeleteScaledSnapshotTexture();
 
@@ -328,16 +339,13 @@
   // Whether the renderer backing this ContentViewCore has crashed.
   bool tab_crashed_;
 
-  // Whether input events will be consistently delivered at vsync time.
-  bool input_events_delivered_at_vsync_;
-
-  // Whether a new frame from the renderer is waiting to be displayed by the
-  // browser compositor.
-  bool renderer_frame_pending_;
-
   // Device scale factor.
   float dpi_scale_;
 
+  // The Android view that can be used to add and remove decoration layers
+  // like AutofillPopup.
+  ui::ViewAndroid* view_android_;
+
   // The owning window that has a hold of main application activity.
   ui::WindowAndroid* window_android_;
 
diff --git a/content/browser/android/content_view_render_view.cc b/content/browser/android/content_view_render_view.cc
index 8e38e08..635ff80 100644
--- a/content/browser/android/content_view_render_view.cc
+++ b/content/browser/android/content_view_render_view.cc
@@ -31,7 +31,7 @@
 
 ContentViewRenderView::ContentViewRenderView()
     : scheduled_composite_(false),
-      weak_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
+      weak_factory_(this) {
 }
 
 ContentViewRenderView::~ContentViewRenderView() {
@@ -77,19 +77,19 @@
     return;
 
   scheduled_composite_ = true;
-  MessageLoop::current()->PostTask(
+  base::MessageLoop::current()->PostTask(
       FROM_HERE,
       base::Bind(&ContentViewRenderView::Composite,
                  weak_factory_.GetWeakPtr()));
 }
 
 void ContentViewRenderView::InitCompositor() {
-  if (!compositor_.get())
+  if (!compositor_)
     compositor_.reset(Compositor::Create(this));
 }
 
 void ContentViewRenderView::Composite() {
-  if (!compositor_.get())
+  if (!compositor_)
     return;
 
   scheduled_composite_ = false;
diff --git a/content/browser/android/content_view_statics.cc b/content/browser/android/content_view_statics.cc
index 0fb0896..66af865 100644
--- a/content/browser/android/content_view_statics.cc
+++ b/content/browser/android/content_view_statics.cc
@@ -3,25 +3,64 @@
 // found in the LICENSE file.
 
 #include <jni.h>
+#include <vector>
 
 #include "base/android/jni_android.h"
 #include "base/android/jni_string.h"
 #include "base/android/scoped_java_ref.h"
 #include "base/basictypes.h"
+#include "base/lazy_instance.h"
 #include "base/logging.h"
 #include "content/browser/android/content_view_statics.h"
 #include "content/common/android/address_parser.h"
 #include "content/common/view_messages.h"
 #include "content/public/browser/render_process_host.h"
-
 #include "jni/ContentViewStatics_jni.h"
 
 using base::android::ConvertJavaStringToUTF16;
 using base::android::ConvertUTF16ToJavaString;
-using base::android::ScopedJavaLocalRef;
 
+namespace {
 
-// Return the first substring consisting of the address of a physical location.
+// TODO(pliard): http://crbug.com/235909. Move WebKit shared timer toggling
+// functionality out of ContentViewStatistics and not be build on top of
+// WebKit::Platform::SuspendSharedTimer.
+// TODO(pliard): http://crbug.com/235912. Add unit tests for WebKit shared timer
+// toggling.
+
+// This tracks the renderer processes that received a suspend request. It's
+// important on resume to only resume the renderer processes that were actually
+// suspended as opposed to all the current renderer processes because the
+// suspend calls are refcounted within WebKitPlatformSupport and it expects a
+// perfectly matched number of resume calls.
+// Note that this vector is only accessed from the UI thread.
+base::LazyInstance<std::vector<int /* process id */> > g_suspended_processes =
+    LAZY_INSTANCE_INITIALIZER;
+
+// Suspends timers in all current render processes.
+void SuspendWebKitSharedTimers(std::vector<int>* suspended_processes) {
+  for (content::RenderProcessHost::iterator i(
+          content::RenderProcessHost::AllHostsIterator());
+       !i.IsAtEnd(); i.Advance()) {
+    content::RenderProcessHost* host = i.GetCurrentValue();
+    suspended_processes->push_back(host->GetID());
+    host->Send(new ViewMsg_SetWebKitSharedTimersSuspended(true));
+  }
+}
+
+// Resumes timers in processes that were previously stopped.
+void ResumeWebkitSharedTimers(const std::vector<int>& suspended_processes) {
+  for (std::vector<int>::const_iterator it = suspended_processes.begin();
+       it != suspended_processes.end(); ++it) {
+    content::RenderProcessHost* host = content::RenderProcessHost::FromID(*it);
+    if (host)  // The process might have been killed since it was suspended.
+      host->Send(new ViewMsg_SetWebKitSharedTimersSuspended(false));
+  }
+}
+
+}  // namespace
+
+// Returns the first substring consisting of the address of a physical location.
 static jstring FindAddress(JNIEnv* env, jclass clazz, jstring addr) {
   string16 content_16 = ConvertJavaStringToUTF16(env, addr);
   string16 result_16;
@@ -33,12 +72,13 @@
 static void SetWebKitSharedTimersSuspended(JNIEnv* env,
                                            jclass obj,
                                            jboolean suspend) {
-  for (content::RenderProcessHost::iterator i =
-           content::RenderProcessHost::AllHostsIterator();
-       !i.IsAtEnd();
-       i.Advance()) {
-    content::RenderProcessHost* host = i.GetCurrentValue();
-    host->Send(new ViewMsg_SetWebKitSharedTimersSuspended(suspend));
+  std::vector<int>* suspended_processes = g_suspended_processes.Pointer();
+  if (suspend) {
+    DCHECK(suspended_processes->empty());
+    SuspendWebKitSharedTimers(suspended_processes);
+  } else {
+    ResumeWebkitSharedTimers(*suspended_processes);
+    suspended_processes->clear();
   }
 }
 
diff --git a/content/browser/android/date_time_chooser_android.cc b/content/browser/android/date_time_chooser_android.cc
index 95bf2f3..0a9a1e2 100644
--- a/content/browser/android/date_time_chooser_android.cc
+++ b/content/browser/android/date_time_chooser_android.cc
@@ -55,7 +55,8 @@
 }
 
 // DateTimeChooserAndroid implementation
-DateTimeChooserAndroid::DateTimeChooserAndroid() {
+DateTimeChooserAndroid::DateTimeChooserAndroid()
+  : sender_(NULL) {
 }
 
 DateTimeChooserAndroid::~DateTimeChooserAndroid() {
@@ -89,7 +90,10 @@
     ContentViewCore* content, RenderViewHost* sender,
     int type, int year, int month, int day,
     int hour, int minute, int second) {
-  sender_.reset(new DateTimeIPCSender(sender));
+  if (sender_)
+    delete sender_;
+  sender_ = new DateTimeIPCSender(sender);
+
   JNIEnv* env = AttachCurrentThread();
   j_date_time_chooser_.Reset(Java_DateTimeChooserAndroid_createDateTimeChooser(
       env, content->GetJavaObject().obj(),
diff --git a/content/browser/android/date_time_chooser_android.h b/content/browser/android/date_time_chooser_android.h
index c33c5c4..6709c38 100644
--- a/content/browser/android/date_time_chooser_android.h
+++ b/content/browser/android/date_time_chooser_android.h
@@ -45,7 +45,10 @@
  private:
   class DateTimeIPCSender;
 
-  scoped_ptr<DateTimeIPCSender> sender_;
+  // The DateTimeIPCSender class is a render view observer, so it will take care
+  // of its own deletion.
+  DateTimeIPCSender* sender_;
+
   base::android::ScopedJavaGlobalRef<jobject> j_date_time_chooser_;
 
   DISALLOW_COPY_AND_ASSIGN(DateTimeChooserAndroid);
diff --git a/content/browser/android/download_controller_android_impl.cc b/content/browser/android/download_controller_android_impl.cc
index 2ade0d0..cc8d640 100644
--- a/content/browser/android/download_controller_android_impl.cc
+++ b/content/browser/android/download_controller_android_impl.cc
@@ -11,14 +11,18 @@
 #include "base/memory/scoped_ptr.h"
 #include "content/browser/android/content_view_core_impl.h"
 #include "content/browser/download/download_item_impl.h"
+#include "content/browser/download/download_manager_impl.h"
 #include "content/browser/loader/resource_dispatcher_host_impl.h"
 #include "content/browser/renderer_host/render_process_host_impl.h"
 #include "content/browser/renderer_host/render_view_host_delegate.h"
 #include "content/browser/renderer_host/render_view_host_impl.h"
 #include "content/browser/web_contents/web_contents_impl.h"
+#include "content/public/browser/browser_context.h"
 #include "content/public/browser/browser_thread.h"
+#include "content/public/browser/download_url_parameters.h"
 #include "content/public/browser/global_request_id.h"
 #include "content/public/browser/web_contents_view.h"
+#include "content/public/common/referrer.h"
 #include "jni/DownloadController_jni.h"
 #include "net/cookies/cookie_options.h"
 #include "net/cookies/cookie_store.h"
@@ -79,10 +83,8 @@
 }
 
 void DownloadControllerAndroidImpl::CreateGETDownload(
-    RenderViewHost* render_view_host,
-    int request_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  int render_process_id = render_view_host->GetProcess()->GetID();
+    int render_process_id, int render_view_id, int request_id) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
   GlobalRequestID global_id(render_process_id, request_id);
 
   // We are yielding the UI thread and render_view_host may go away by
@@ -91,14 +93,12 @@
   GetDownloadInfoCB cb = base::Bind(
         &DownloadControllerAndroidImpl::StartAndroidDownload,
         base::Unretained(this), render_process_id,
-        render_view_host->GetRoutingID());
-  BrowserThread::PostTask(
-      BrowserThread::IO, FROM_HERE,
-      base::Bind(
-          &DownloadControllerAndroidImpl::PrepareDownloadInfo,
-          base::Unretained(this), global_id,
-          base::Bind(&DownloadControllerAndroidImpl::StartDownloadOnUIThread,
-                     base::Unretained(this), cb)));
+        render_view_id);
+
+  PrepareDownloadInfo(
+      global_id,
+      base::Bind(&DownloadControllerAndroidImpl::StartDownloadOnUIThread,
+                 base::Unretained(this), cb));
 }
 
 void DownloadControllerAndroidImpl::PrepareDownloadInfo(
@@ -226,7 +226,7 @@
       jcookie.obj(), jreferer.obj(), info.total_bytes);
 }
 
-void DownloadControllerAndroidImpl::OnPostDownloadStarted(
+void DownloadControllerAndroidImpl::OnDownloadStarted(
     DownloadItem* download_item) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   if (!download_item->GetWebContents())
@@ -243,12 +243,14 @@
   if (view.is_null())
     return;
 
-  Java_DownloadController_onHttpPostDownloadStarted(
+  Java_DownloadController_onDownloadStarted(
       env, GetJavaObject()->Controller(env).obj(), view.obj());
 }
 
 void DownloadControllerAndroidImpl::OnDownloadUpdated(DownloadItem* item) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  if (item->IsDangerous() && !item->IsCancelled())
+    OnDangerousDownload(item);
 
   if (!item->IsComplete())
     return;
@@ -275,12 +277,25 @@
     return;
   }
 
-  Java_DownloadController_onHttpPostDownloadCompleted(env,
+  Java_DownloadController_onDownloadCompleted(env,
       GetJavaObject()->Controller(env).obj(), view_core.obj(), jurl.obj(),
       jcontent_disposition.obj(), jmime_type.obj(), jpath.obj(),
       item->GetReceivedBytes(), true);
 }
 
+void DownloadControllerAndroidImpl::OnDangerousDownload(DownloadItem* item) {
+  JNIEnv* env = base::android::AttachCurrentThread();
+  ScopedJavaLocalRef<jstring> jfilename = ConvertUTF8ToJavaString(
+      env, item->GetTargetFilePath().BaseName().value());
+  ScopedJavaLocalRef<jobject> view_core = GetContentViewCoreFromWebContents(
+      item->GetWebContents());
+  if (!view_core.is_null()) {
+    Java_DownloadController_onDangerousDownload(
+        env, GetJavaObject()->Controller(env).obj(), view_core.obj(),
+        jfilename.obj(), item->GetId());
+  }
+}
+
 ScopedJavaLocalRef<jobject> DownloadControllerAndroidImpl::GetContentView(
     int render_process_id, int render_view_id) {
   RenderViewHost* render_view_host =
@@ -301,10 +316,7 @@
 ScopedJavaLocalRef<jobject>
     DownloadControllerAndroidImpl::GetContentViewCoreFromWebContents(
     WebContents* web_contents) {
-  if (!web_contents)
-    return ScopedJavaLocalRef<jobject>();
-
-  ContentViewCore* view_core = web_contents->GetView()->GetContentNativeView();
+  ContentViewCore* view_core = ContentViewCore::FromWebContents(web_contents);
   return view_core ? view_core->GetJavaObject() :
       ScopedJavaLocalRef<jobject>();
 }
@@ -323,6 +335,40 @@
   return java_object_;
 }
 
+void DownloadControllerAndroidImpl::StartContextMenuDownload(
+    const ContextMenuParams& params, WebContents* web_contents, bool is_link) {
+  const GURL& url = is_link ? params.link_url : params.src_url;
+  const GURL& referrer = params.frame_url.is_empty() ?
+      params.page_url : params.frame_url;
+  DownloadManagerImpl* dlm = static_cast<DownloadManagerImpl*>(
+      BrowserContext::GetDownloadManager(web_contents->GetBrowserContext()));
+  scoped_ptr<DownloadUrlParameters> dl_params(
+      DownloadUrlParameters::FromWebContents(web_contents, url));
+  dl_params->set_referrer(
+      Referrer(referrer, params.referrer_policy));
+  if (is_link)
+    dl_params->set_referrer_encoding(params.frame_charset);
+  else
+    dl_params->set_prefer_cache(true);
+  dl_params->set_prompt(false);
+  dlm->DownloadUrl(dl_params.Pass());
+}
+
+void DownloadControllerAndroidImpl::DangerousDownloadValidated(
+    WebContents* web_contents, int download_id, bool accept) {
+  if (!web_contents)
+    return;
+  DownloadManagerImpl* dlm = static_cast<DownloadManagerImpl*>(
+      BrowserContext::GetDownloadManager(web_contents->GetBrowserContext()));
+  DownloadItem* item = dlm->GetDownload(download_id);
+  if (!item)
+    return;
+  if (accept)
+    item->DangerousDownloadValidated();
+  else
+    item->Delete(content::DownloadItem::DELETE_DUE_TO_USER_DISCARD);
+}
+
 DownloadControllerAndroidImpl::DownloadInfoAndroid::DownloadInfoAndroid(
     net::URLRequest* request) {
   request->GetResponseHeaderByName("content-disposition", &content_disposition);
@@ -332,7 +378,7 @@
 
   request->extra_request_headers().GetHeader(
       net::HttpRequestHeaders::kUserAgent, &user_agent);
-  GURL referer_url(request->GetSanitizedReferrer());
+  GURL referer_url(request->referrer());
   if (referer_url.is_valid())
     referer = referer_url.spec();
   if (!request->url_chain().empty()) {
diff --git a/content/browser/android/download_controller_android_impl.h b/content/browser/android/download_controller_android_impl.h
index 6dc87e2..c8a0ea2 100644
--- a/content/browser/android/download_controller_android_impl.h
+++ b/content/browser/android/download_controller_android_impl.h
@@ -75,9 +75,14 @@
   virtual ~DownloadControllerAndroidImpl();
 
   // DownloadControllerAndroid implementation.
-  virtual void CreateGETDownload(RenderViewHost* source,
+  virtual void CreateGETDownload(int render_process_id, int render_view_id,
                                  int request_id) OVERRIDE;
-  virtual void OnPostDownloadStarted(DownloadItem* download_item) OVERRIDE;
+  virtual void OnDownloadStarted(DownloadItem* download_item) OVERRIDE;
+  virtual void StartContextMenuDownload(
+      const ContextMenuParams& params, WebContents* web_contents,
+      bool is_link) OVERRIDE;
+  virtual void DangerousDownloadValidated(
+      WebContents* web_contents, int download_id, bool accept) OVERRIDE;
 
   // DownloadItem::Observer interface.
   virtual void OnDownloadUpdated(DownloadItem* item) OVERRIDE;
@@ -102,6 +107,9 @@
                             int render_view_id,
                             const DownloadInfoAndroid& info);
 
+  // The download item contains dangerous file types.
+  void OnDangerousDownload(DownloadItem *item);
+
   base::android::ScopedJavaLocalRef<jobject> GetContentViewCoreFromWebContents(
       WebContents* web_contents);
 
diff --git a/content/browser/android/media_player_manager_android.cc b/content/browser/android/media_player_manager_android.cc
deleted file mode 100644
index 7375ff7..0000000
--- a/content/browser/android/media_player_manager_android.cc
+++ /dev/null
@@ -1,331 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/android/media_player_manager_android.h"
-
-#include "base/bind.h"
-#include "content/browser/android/media_resource_getter_impl.h"
-#include "content/browser/web_contents/web_contents_view_android.h"
-#include "content/common/media/media_player_messages.h"
-#include "content/public/browser/browser_context.h"
-#include "content/public/browser/render_process_host.h"
-#include "content/public/browser/render_view_host.h"
-#include "content/public/browser/storage_partition.h"
-
-using media::MediaPlayerBridge;
-
-// Threshold on the number of media players per renderer before we start
-// attempting to release inactive media players.
-static const int kMediaPlayerThreshold = 1;
-
-namespace content {
-
-MediaPlayerManagerAndroid::MediaPlayerManagerAndroid(
-    RenderViewHost* render_view_host)
-    : RenderViewHostObserver(render_view_host),
-      ALLOW_THIS_IN_INITIALIZER_LIST(video_view_(this)),
-      fullscreen_player_id_(-1),
-      web_contents_(WebContents::FromRenderViewHost(render_view_host)) {
-}
-
-MediaPlayerManagerAndroid::~MediaPlayerManagerAndroid() {}
-
-bool MediaPlayerManagerAndroid::OnMessageReceived(const IPC::Message& msg) {
-  bool handled = true;
-  IPC_BEGIN_MESSAGE_MAP(MediaPlayerManagerAndroid, msg)
-    IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_EnterFullscreen, OnEnterFullscreen)
-    IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_ExitFullscreen, OnExitFullscreen)
-    IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_MediaPlayerInitialize, OnInitialize)
-    IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_MediaPlayerStart, OnStart)
-    IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_MediaPlayerSeek, OnSeek)
-    IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_MediaPlayerPause, OnPause)
-    IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_MediaPlayerRelease,
-                        OnReleaseResources)
-    IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_DestroyMediaPlayer, OnDestroyPlayer)
-    IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_DestroyAllMediaPlayers,
-                        DestroyAllMediaPlayers)
-    IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_RequestExternalSurface,
-                        OnRequestExternalSurface)
-    IPC_MESSAGE_UNHANDLED(handled = false)
-  IPC_END_MESSAGE_MAP()
-  return handled;
-}
-
-void MediaPlayerManagerAndroid::FullscreenPlayerPlay() {
-  MediaPlayerBridge* player = GetFullscreenPlayer();
-  if (player) {
-    player->Start();
-    Send(new MediaPlayerMsg_DidMediaPlayerPlay(
-        routing_id(), fullscreen_player_id_));
-  }
-}
-
-void MediaPlayerManagerAndroid::FullscreenPlayerPause() {
-  MediaPlayerBridge* player = GetFullscreenPlayer();
-  if (player) {
-    player->Pause();
-    Send(new MediaPlayerMsg_DidMediaPlayerPause(
-        routing_id(), fullscreen_player_id_));
-  }
-}
-
-void MediaPlayerManagerAndroid::FullscreenPlayerSeek(int msec) {
-  MediaPlayerBridge* player = GetFullscreenPlayer();
-  if (player)
-    player->SeekTo(base::TimeDelta::FromMilliseconds(msec));
-}
-
-void MediaPlayerManagerAndroid::ExitFullscreen(bool release_media_player) {
-  Send(new MediaPlayerMsg_DidExitFullscreen(
-      routing_id(), fullscreen_player_id_));
-  MediaPlayerBridge* player = GetFullscreenPlayer();
-  fullscreen_player_id_ = -1;
-  if (!player)
-    return;
-  if (release_media_player)
-    player->Release();
-  else
-    player->SetVideoSurface(NULL);
-}
-
-void MediaPlayerManagerAndroid::SetVideoSurface(jobject surface) {
-  MediaPlayerBridge* player = GetFullscreenPlayer();
-  if (player) {
-    player->SetVideoSurface(surface);
-    Send(new MediaPlayerMsg_DidEnterFullscreen(
-        routing_id(), player->player_id()));
-  }
-}
-
-void MediaPlayerManagerAndroid::OnInitialize(
-    int player_id, const GURL& url, const GURL& first_party_for_cookies) {
-  for (ScopedVector<MediaPlayerBridge>::iterator it = players_.begin();
-      it != players_.end(); ++it) {
-    if ((*it)->player_id() == player_id) {
-      players_.erase(it);
-      break;
-    }
-  }
-
-  RenderProcessHost* host = render_view_host()->GetProcess();
-  BrowserContext* context = host->GetBrowserContext();
-  StoragePartition* partition = host->GetStoragePartition();
-  fileapi::FileSystemContext* file_system_context =
-      partition ? partition->GetFileSystemContext() : NULL;
-  players_.push_back(new MediaPlayerBridge(
-      player_id, url, first_party_for_cookies,
-      new MediaResourceGetterImpl(context, file_system_context, host->GetID(),
-                                  routing_id()),
-      context->IsOffTheRecord(), this,
-      base::Bind(&MediaPlayerManagerAndroid::OnError, base::Unretained(this)),
-      base::Bind(&MediaPlayerManagerAndroid::OnVideoSizeChanged,
-                 base::Unretained(this)),
-      base::Bind(&MediaPlayerManagerAndroid::OnBufferingUpdate,
-                 base::Unretained(this)),
-      base::Bind(&MediaPlayerManagerAndroid::OnPrepared,
-                 base::Unretained(this)),
-      base::Bind(&MediaPlayerManagerAndroid::OnPlaybackComplete,
-                 base::Unretained(this)),
-      base::Bind(&MediaPlayerManagerAndroid::OnSeekComplete,
-                 base::Unretained(this)),
-      base::Bind(&MediaPlayerManagerAndroid::OnTimeUpdate,
-                 base::Unretained(this)),
-      base::Bind(&MediaPlayerManagerAndroid::OnMediaInterrupted,
-                 base::Unretained(this))));
-
-  // Send a MediaPrepared message to webkit so that Load() can finish.
-  Send(new MediaPlayerMsg_MediaPrepared(
-      routing_id(), player_id, GetPlayer(player_id)->GetDuration()));
-}
-
-void MediaPlayerManagerAndroid::OnStart(int player_id) {
-  MediaPlayerBridge* player = GetPlayer(player_id);
-  if (player)
-    player->Start();
-}
-
-void MediaPlayerManagerAndroid::OnSeek(int player_id, base::TimeDelta time) {
-  MediaPlayerBridge* player = GetPlayer(player_id);
-  if (player)
-    player->SeekTo(time);
-}
-
-void MediaPlayerManagerAndroid::OnPause(int player_id) {
-  MediaPlayerBridge* player = GetPlayer(player_id);
-  if (player)
-    player->Pause();
-}
-
-void MediaPlayerManagerAndroid::OnEnterFullscreen(int player_id) {
-  DCHECK_EQ(fullscreen_player_id_, -1);
-
-  fullscreen_player_id_ = player_id;
-  video_view_.CreateContentVideoView();
-}
-
-void MediaPlayerManagerAndroid::OnExitFullscreen(int player_id) {
-  if (fullscreen_player_id_ == player_id) {
-    MediaPlayerBridge* player = GetPlayer(player_id);
-    if (player)
-      player->SetVideoSurface(NULL);
-    video_view_.DestroyContentVideoView();
-    fullscreen_player_id_ = -1;
-  }
-}
-
-void MediaPlayerManagerAndroid::OnReleaseResources(int player_id) {
-  MediaPlayerBridge* player = GetPlayer(player_id);
-  // Don't release the fullscreen player when tab visibility changes,
-  // it will be released when user hit the back/home button or when
-  // OnDestroyPlayer is called.
-  if (player && player_id != fullscreen_player_id_)
-    player->Release();
-}
-
-void MediaPlayerManagerAndroid::OnDestroyPlayer(int player_id) {
-  for (ScopedVector<MediaPlayerBridge>::iterator it = players_.begin();
-      it != players_.end(); ++it) {
-    if ((*it)->player_id() == player_id) {
-      players_.erase(it);
-      break;
-    }
-  }
-  if (fullscreen_player_id_ == player_id)
-    fullscreen_player_id_ = -1;
-}
-
-void MediaPlayerManagerAndroid::DestroyAllMediaPlayers() {
-  players_.clear();
-  if (fullscreen_player_id_ != -1) {
-    video_view_.DestroyContentVideoView();
-    fullscreen_player_id_ = -1;
-  }
-}
-
-void MediaPlayerManagerAndroid::AttachExternalVideoSurface(int player_id,
-                                                           jobject surface) {
-  MediaPlayerBridge* player = GetPlayer(player_id);
-  if (player)
-    player->SetVideoSurface(surface);
-}
-
-void MediaPlayerManagerAndroid::DetachExternalVideoSurface(int player_id) {
-  MediaPlayerBridge* player = GetPlayer(player_id);
-  if (player)
-    player->SetVideoSurface(NULL);
-}
-
-void MediaPlayerManagerAndroid::OnRequestExternalSurface(int player_id) {
-  if (web_contents_) {
-    WebContentsViewAndroid* view =
-        static_cast<WebContentsViewAndroid*>(web_contents_->GetView());
-    if (view)
-      view->RequestExternalVideoSurface(player_id);
-  }
-}
-
-MediaPlayerBridge* MediaPlayerManagerAndroid::GetPlayer(int player_id) {
-  for (ScopedVector<MediaPlayerBridge>::iterator it = players_.begin();
-      it != players_.end(); ++it) {
-    if ((*it)->player_id() == player_id)
-      return *it;
-  }
-  return NULL;
-}
-
-MediaPlayerBridge* MediaPlayerManagerAndroid::GetFullscreenPlayer() {
-  return GetPlayer(fullscreen_player_id_);
-}
-
-void MediaPlayerManagerAndroid::OnPrepared(int player_id,
-                                           base::TimeDelta duration) {
-  Send(new MediaPlayerMsg_MediaPrepared(routing_id(), player_id, duration));
-  if (fullscreen_player_id_ != -1)
-    video_view_.UpdateMediaMetadata();
-}
-
-void MediaPlayerManagerAndroid::OnPlaybackComplete(int player_id) {
-  Send(new MediaPlayerMsg_MediaPlaybackCompleted(routing_id(), player_id));
-  if (fullscreen_player_id_ != -1)
-    video_view_.OnPlaybackComplete();
-}
-
-void MediaPlayerManagerAndroid::OnMediaInterrupted(int player_id) {
-  // Tell WebKit that the audio should be paused, then release all resources
-  Send(new MediaPlayerMsg_DidMediaPlayerPause(routing_id(), player_id));
-  OnReleaseResources(player_id);
-}
-
-void MediaPlayerManagerAndroid::OnBufferingUpdate(
-    int player_id, int percentage) {
-  Send(new MediaPlayerMsg_MediaBufferingUpdate(
-      routing_id(), player_id, percentage));
-  if (fullscreen_player_id_ != -1)
-    video_view_.OnBufferingUpdate(percentage);
-}
-
-void MediaPlayerManagerAndroid::OnSeekComplete(int player_id,
-                                               base::TimeDelta current_time) {
-  Send(new MediaPlayerMsg_MediaSeekCompleted(
-      routing_id(), player_id, current_time));
-}
-
-void MediaPlayerManagerAndroid::OnError(int player_id, int error) {
-  Send(new MediaPlayerMsg_MediaError(routing_id(), player_id, error));
-  if (fullscreen_player_id_ != -1)
-    video_view_.OnMediaPlayerError(error);
-}
-
-void MediaPlayerManagerAndroid::OnVideoSizeChanged(
-    int player_id, int width, int height) {
-  Send(new MediaPlayerMsg_MediaVideoSizeChanged(routing_id(), player_id,
-      width, height));
-  if (fullscreen_player_id_ != -1)
-    video_view_.OnVideoSizeChanged(width, height);
-}
-
-void MediaPlayerManagerAndroid::OnTimeUpdate(int player_id,
-                                             base::TimeDelta current_time) {
-  Send(new MediaPlayerMsg_MediaTimeUpdate(
-      routing_id(), player_id, current_time));
-}
-
-void MediaPlayerManagerAndroid::RequestMediaResources(
-    MediaPlayerBridge* player) {
-  if (player == NULL)
-    return;
-
-  int num_active_player = 0;
-  ScopedVector<MediaPlayerBridge>::iterator it;
-  for (it = players_.begin(); it != players_.end(); ++it) {
-    if (!(*it)->prepared())
-      continue;
-
-    // The player is already active, ignore it.
-    if ((*it) == player)
-      return;
-    else
-      num_active_player++;
-  }
-
-  // Number of active players are less than the threshold, do nothing.
-  if (num_active_player < kMediaPlayerThreshold)
-    return;
-
-  for (it = players_.begin(); it != players_.end(); ++it) {
-    if ((*it)->prepared() && !(*it)->IsPlaying() &&
-        fullscreen_player_id_ != (*it)->player_id()) {
-      (*it)->Release();
-      Send(new MediaPlayerMsg_MediaPlayerReleased(
-          routing_id(), (*it)->player_id()));
-    }
-  }
-}
-
-void MediaPlayerManagerAndroid::ReleaseMediaResources(
-    MediaPlayerBridge* player) {
-  // Nothing needs to be done.
-}
-
-}  // namespace content
diff --git a/content/browser/android/media_player_manager_impl.cc b/content/browser/android/media_player_manager_impl.cc
new file mode 100644
index 0000000..ba799a6
--- /dev/null
+++ b/content/browser/android/media_player_manager_impl.cc
@@ -0,0 +1,388 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/android/media_player_manager_impl.h"
+
+#include "base/bind.h"
+#include "content/browser/android/media_resource_getter_impl.h"
+#include "content/browser/web_contents/web_contents_view_android.h"
+#include "content/common/media/media_player_messages.h"
+#include "content/public/browser/browser_context.h"
+#include "content/public/browser/render_process_host.h"
+#include "content/public/browser/render_view_host.h"
+#include "content/public/browser/storage_partition.h"
+
+using media::MediaPlayerBridge;
+
+// Threshold on the number of media players per renderer before we start
+// attempting to release inactive media players.
+static const int kMediaPlayerThreshold = 1;
+
+namespace content {
+
+MediaPlayerManagerImpl::MediaPlayerManagerImpl(
+    RenderViewHost* render_view_host)
+    : RenderViewHostObserver(render_view_host),
+      video_view_(this),
+      fullscreen_player_id_(-1),
+      web_contents_(WebContents::FromRenderViewHost(render_view_host)) {
+}
+
+MediaPlayerManagerImpl::~MediaPlayerManagerImpl() {}
+
+bool MediaPlayerManagerImpl::OnMessageReceived(const IPC::Message& msg) {
+  bool handled = true;
+  IPC_BEGIN_MESSAGE_MAP(MediaPlayerManagerImpl, msg)
+    IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_EnterFullscreen, OnEnterFullscreen)
+    IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_ExitFullscreen, OnExitFullscreen)
+    IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_MediaPlayerInitialize, OnInitialize)
+    IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_MediaPlayerStart, OnStart)
+    IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_MediaPlayerSeek, OnSeek)
+    IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_MediaPlayerPause, OnPause)
+    IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_MediaPlayerRelease,
+                        OnReleaseResources)
+    IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_DestroyMediaPlayer, OnDestroyPlayer)
+    IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_DestroyAllMediaPlayers,
+                        DestroyAllMediaPlayers)
+#if defined(GOOGLE_TV)
+    IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_RequestExternalSurface,
+                        OnRequestExternalSurface)
+    IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_NotifyGeometryChange,
+                        OnNotifyGeometryChange)
+    IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_DemuxerReady,
+                        OnDemuxerReady)
+    IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_ReadFromDemuxerAck,
+                        OnReadFromDemuxerAck)
+#endif
+    IPC_MESSAGE_UNHANDLED(handled = false)
+  IPC_END_MESSAGE_MAP()
+  return handled;
+}
+
+void MediaPlayerManagerImpl::FullscreenPlayerPlay() {
+  MediaPlayerBridge* player = GetFullscreenPlayer();
+  if (player) {
+    player->Start();
+    Send(new MediaPlayerMsg_DidMediaPlayerPlay(
+        routing_id(), fullscreen_player_id_));
+  }
+}
+
+void MediaPlayerManagerImpl::FullscreenPlayerPause() {
+  MediaPlayerBridge* player = GetFullscreenPlayer();
+  if (player) {
+    player->Pause();
+    Send(new MediaPlayerMsg_DidMediaPlayerPause(
+        routing_id(), fullscreen_player_id_));
+  }
+}
+
+void MediaPlayerManagerImpl::FullscreenPlayerSeek(int msec) {
+  MediaPlayerBridge* player = GetFullscreenPlayer();
+  if (player)
+    player->SeekTo(base::TimeDelta::FromMilliseconds(msec));
+}
+
+void MediaPlayerManagerImpl::ExitFullscreen(bool release_media_player) {
+  Send(new MediaPlayerMsg_DidExitFullscreen(
+      routing_id(), fullscreen_player_id_));
+  MediaPlayerBridge* player = GetFullscreenPlayer();
+  fullscreen_player_id_ = -1;
+  if (!player)
+    return;
+  if (release_media_player)
+    player->Release();
+  else
+    player->SetVideoSurface(NULL);
+}
+
+void MediaPlayerManagerImpl::SetVideoSurface(jobject surface) {
+  MediaPlayerBridge* player = GetFullscreenPlayer();
+  if (player) {
+    player->SetVideoSurface(surface);
+    Send(new MediaPlayerMsg_DidEnterFullscreen(
+        routing_id(), player->player_id()));
+  }
+}
+
+void MediaPlayerManagerImpl::OnInitialize(
+    int player_id, const GURL& url,
+    bool is_media_source,
+    const GURL& first_party_for_cookies) {
+  for (ScopedVector<MediaPlayerBridge>::iterator it = players_.begin();
+      it != players_.end(); ++it) {
+    if ((*it)->player_id() == player_id) {
+      players_.erase(it);
+      break;
+    }
+  }
+
+  RenderProcessHost* host = render_view_host()->GetProcess();
+  players_.push_back(media::MediaPlayerBridge::Create(
+      player_id, url, is_media_source, first_party_for_cookies,
+      host->GetBrowserContext()->IsOffTheRecord(), this,
+#if defined(GOOGLE_TV)
+      base::Bind(&MediaPlayerManagerImpl::OnReadFromDemuxer,
+                 base::Unretained(this)),
+#endif
+      base::Bind(&MediaPlayerManagerImpl::OnError, base::Unretained(this)),
+      base::Bind(&MediaPlayerManagerImpl::OnVideoSizeChanged,
+                 base::Unretained(this)),
+      base::Bind(&MediaPlayerManagerImpl::OnBufferingUpdate,
+                 base::Unretained(this)),
+      base::Bind(&MediaPlayerManagerImpl::OnMediaMetadataChanged,
+                 base::Unretained(this)),
+      base::Bind(&MediaPlayerManagerImpl::OnPlaybackComplete,
+                 base::Unretained(this)),
+      base::Bind(&MediaPlayerManagerImpl::OnSeekComplete,
+                 base::Unretained(this)),
+      base::Bind(&MediaPlayerManagerImpl::OnTimeUpdate,
+                 base::Unretained(this)),
+      base::Bind(&MediaPlayerManagerImpl::OnMediaInterrupted,
+                 base::Unretained(this))));
+}
+
+media::MediaResourceGetter* MediaPlayerManagerImpl::GetMediaResourceGetter() {
+  if (!media_resource_getter_.get()) {
+    RenderProcessHost* host = render_view_host()->GetProcess();
+    BrowserContext* context = host->GetBrowserContext();
+    StoragePartition* partition = host->GetStoragePartition();
+    fileapi::FileSystemContext* file_system_context =
+        partition ? partition->GetFileSystemContext() : NULL;
+    media_resource_getter_.reset(new MediaResourceGetterImpl(
+        context, file_system_context, host->GetID(), routing_id()));
+  }
+  return media_resource_getter_.get();
+}
+
+void MediaPlayerManagerImpl::OnStart(int player_id) {
+  MediaPlayerBridge* player = GetPlayer(player_id);
+  if (player)
+    player->Start();
+}
+
+void MediaPlayerManagerImpl::OnSeek(int player_id, base::TimeDelta time) {
+  MediaPlayerBridge* player = GetPlayer(player_id);
+  if (player)
+    player->SeekTo(time);
+}
+
+void MediaPlayerManagerImpl::OnPause(int player_id) {
+  MediaPlayerBridge* player = GetPlayer(player_id);
+  if (player)
+    player->Pause();
+}
+
+void MediaPlayerManagerImpl::OnEnterFullscreen(int player_id) {
+  DCHECK_EQ(fullscreen_player_id_, -1);
+
+  fullscreen_player_id_ = player_id;
+  video_view_.CreateContentVideoView();
+}
+
+void MediaPlayerManagerImpl::OnExitFullscreen(int player_id) {
+  if (fullscreen_player_id_ == player_id) {
+    MediaPlayerBridge* player = GetPlayer(player_id);
+    if (player)
+      player->SetVideoSurface(NULL);
+    video_view_.DestroyContentVideoView();
+    fullscreen_player_id_ = -1;
+  }
+}
+
+void MediaPlayerManagerImpl::OnReleaseResources(int player_id) {
+  MediaPlayerBridge* player = GetPlayer(player_id);
+  // Don't release the fullscreen player when tab visibility changes,
+  // it will be released when user hit the back/home button or when
+  // OnDestroyPlayer is called.
+  if (player && player_id != fullscreen_player_id_)
+    player->Release();
+}
+
+void MediaPlayerManagerImpl::OnDestroyPlayer(int player_id) {
+  for (ScopedVector<MediaPlayerBridge>::iterator it = players_.begin();
+      it != players_.end(); ++it) {
+    if ((*it)->player_id() == player_id) {
+      players_.erase(it);
+      break;
+    }
+  }
+  if (fullscreen_player_id_ == player_id)
+    fullscreen_player_id_ = -1;
+}
+
+void MediaPlayerManagerImpl::DestroyAllMediaPlayers() {
+  players_.clear();
+  if (fullscreen_player_id_ != -1) {
+    video_view_.DestroyContentVideoView();
+    fullscreen_player_id_ = -1;
+  }
+}
+
+#if defined(GOOGLE_TV)
+void MediaPlayerManagerImpl::AttachExternalVideoSurface(int player_id,
+                                                           jobject surface) {
+  MediaPlayerBridge* player = GetPlayer(player_id);
+  if (player)
+    player->SetVideoSurface(surface);
+}
+
+void MediaPlayerManagerImpl::DetachExternalVideoSurface(int player_id) {
+  MediaPlayerBridge* player = GetPlayer(player_id);
+  if (player)
+    player->SetVideoSurface(NULL);
+}
+
+void MediaPlayerManagerImpl::OnRequestExternalSurface(int player_id) {
+  if (!web_contents_)
+    return;
+
+  WebContentsViewAndroid* view =
+      static_cast<WebContentsViewAndroid*>(web_contents_->GetView());
+  if (view)
+    view->RequestExternalVideoSurface(player_id);
+}
+
+void MediaPlayerManagerImpl::OnNotifyGeometryChange(int player_id,
+                                                       const gfx::RectF& rect) {
+  if (!web_contents_)
+    return;
+
+  WebContentsViewAndroid* view =
+      static_cast<WebContentsViewAndroid*>(web_contents_->GetView());
+  if (view)
+    view->NotifyGeometryChange(player_id, rect);
+}
+
+void MediaPlayerManagerImpl::OnDemuxerReady(
+    int player_id,
+    const media::MediaPlayerHostMsg_DemuxerReady_Params& params) {
+  MediaPlayerBridge* player = GetPlayer(player_id);
+  if (player)
+    player->DemuxerReady(params);
+}
+
+void MediaPlayerManagerImpl::OnReadFromDemuxerAck(
+    int player_id,
+    const media::MediaPlayerHostMsg_ReadFromDemuxerAck_Params& params) {
+  MediaPlayerBridge* player = GetPlayer(player_id);
+  if (player)
+    player->ReadFromDemuxerAck(params);
+}
+#endif
+
+MediaPlayerBridge* MediaPlayerManagerImpl::GetPlayer(int player_id) {
+  for (ScopedVector<MediaPlayerBridge>::iterator it = players_.begin();
+      it != players_.end(); ++it) {
+    if ((*it)->player_id() == player_id)
+      return *it;
+  }
+  return NULL;
+}
+
+MediaPlayerBridge* MediaPlayerManagerImpl::GetFullscreenPlayer() {
+  return GetPlayer(fullscreen_player_id_);
+}
+
+void MediaPlayerManagerImpl::OnMediaMetadataChanged(
+    int player_id, base::TimeDelta duration, int width, int height,
+    bool success) {
+  Send(new MediaPlayerMsg_MediaMetadataChanged(
+      routing_id(), player_id, duration, width, height, success));
+  if (fullscreen_player_id_ != -1)
+    video_view_.UpdateMediaMetadata();
+}
+
+void MediaPlayerManagerImpl::OnPlaybackComplete(int player_id) {
+  Send(new MediaPlayerMsg_MediaPlaybackCompleted(routing_id(), player_id));
+  if (fullscreen_player_id_ != -1)
+    video_view_.OnPlaybackComplete();
+}
+
+void MediaPlayerManagerImpl::OnMediaInterrupted(int player_id) {
+  // Tell WebKit that the audio should be paused, then release all resources
+  Send(new MediaPlayerMsg_DidMediaPlayerPause(routing_id(), player_id));
+  OnReleaseResources(player_id);
+}
+
+void MediaPlayerManagerImpl::OnBufferingUpdate(
+    int player_id, int percentage) {
+  Send(new MediaPlayerMsg_MediaBufferingUpdate(
+      routing_id(), player_id, percentage));
+  if (fullscreen_player_id_ != -1)
+    video_view_.OnBufferingUpdate(percentage);
+}
+
+void MediaPlayerManagerImpl::OnSeekComplete(int player_id,
+                                               base::TimeDelta current_time) {
+  Send(new MediaPlayerMsg_MediaSeekCompleted(
+      routing_id(), player_id, current_time));
+}
+
+void MediaPlayerManagerImpl::OnError(int player_id, int error) {
+  Send(new MediaPlayerMsg_MediaError(routing_id(), player_id, error));
+  if (fullscreen_player_id_ != -1)
+    video_view_.OnMediaPlayerError(error);
+}
+
+void MediaPlayerManagerImpl::OnVideoSizeChanged(
+    int player_id, int width, int height) {
+  Send(new MediaPlayerMsg_MediaVideoSizeChanged(routing_id(), player_id,
+      width, height));
+  if (fullscreen_player_id_ != -1)
+    video_view_.OnVideoSizeChanged(width, height);
+}
+
+void MediaPlayerManagerImpl::OnTimeUpdate(int player_id,
+                                             base::TimeDelta current_time) {
+  Send(new MediaPlayerMsg_MediaTimeUpdate(
+      routing_id(), player_id, current_time));
+}
+
+#if defined(GOOGLE_TV)
+void MediaPlayerManagerImpl::OnReadFromDemuxer(
+    int player_id, media::DemuxerStream::Type type, bool seek_done) {
+  Send(new MediaPlayerMsg_ReadFromDemuxer(
+      routing_id(), player_id, type, seek_done));
+}
+#endif
+
+void MediaPlayerManagerImpl::RequestMediaResources(
+    MediaPlayerBridge* player) {
+  if (player == NULL)
+    return;
+
+  int num_active_player = 0;
+  ScopedVector<MediaPlayerBridge>::iterator it;
+  for (it = players_.begin(); it != players_.end(); ++it) {
+    if (!(*it)->prepared())
+      continue;
+
+    // The player is already active, ignore it.
+    if ((*it) == player)
+      return;
+    else
+      num_active_player++;
+  }
+
+  // Number of active players are less than the threshold, do nothing.
+  if (num_active_player < kMediaPlayerThreshold)
+    return;
+
+  for (it = players_.begin(); it != players_.end(); ++it) {
+    if ((*it)->prepared() && !(*it)->IsPlaying() &&
+        fullscreen_player_id_ != (*it)->player_id()) {
+      (*it)->Release();
+      Send(new MediaPlayerMsg_MediaPlayerReleased(
+          routing_id(), (*it)->player_id()));
+    }
+  }
+}
+
+void MediaPlayerManagerImpl::ReleaseMediaResources(
+    MediaPlayerBridge* player) {
+  // Nothing needs to be done.
+}
+
+}  // namespace content
diff --git a/content/browser/android/media_player_manager_android.h b/content/browser/android/media_player_manager_impl.h
similarity index 65%
rename from content/browser/android/media_player_manager_android.h
rename to content/browser/android/media_player_manager_impl.h
index 2500086..34905df 100644
--- a/content/browser/android/media_player_manager_android.h
+++ b/content/browser/android/media_player_manager_impl.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CONTENT_BROWSER_ANDROID_MEDIA_PLAYER_MANAGER_ANDROID_H_
-#define CONTENT_BROWSER_ANDROID_MEDIA_PLAYER_MANAGER_ANDROID_H_
+#ifndef CONTENT_BROWSER_ANDROID_MEDIA_PLAYER_MANAGER_IMPL_H_
+#define CONTENT_BROWSER_ANDROID_MEDIA_PLAYER_MANAGER_IMPL_H_
 
 #include <map>
 
@@ -14,8 +14,12 @@
 #include "content/browser/android/content_video_view.h"
 #include "content/public/browser/render_view_host_observer.h"
 #include "googleurl/src/gurl.h"
+#if defined(GOOGLE_TV)
+#include "media/base/android/demuxer_stream_player_params.h"
+#endif
 #include "media/base/android/media_player_bridge.h"
-#include "media/base/android/media_player_bridge_manager.h"
+#include "media/base/android/media_player_manager.h"
+#include "ui/gfx/rect_f.h"
 
 namespace content {
 
@@ -26,13 +30,13 @@
 // them to corresponding MediaPlayerBridge object. Callbacks from
 // MediaPlayerBridge objects are converted to IPCs and then sent to the
 // render process.
-class MediaPlayerManagerAndroid
+class MediaPlayerManagerImpl
     : public RenderViewHostObserver,
-      public media::MediaPlayerBridgeManager {
+      public media::MediaPlayerManager {
  public:
-  // Create a MediaPlayerManagerAndroid object for the |render_view_host|.
-  explicit MediaPlayerManagerAndroid(RenderViewHost* render_view_host);
-  virtual ~MediaPlayerManagerAndroid();
+  // Create a MediaPlayerManagerImpl object for the |render_view_host|.
+  explicit MediaPlayerManagerImpl(RenderViewHost* render_view_host);
+  virtual ~MediaPlayerManagerImpl();
 
   // RenderViewHostObserver overrides.
   virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
@@ -49,7 +53,8 @@
   void OnTimeUpdate(int player_id, base::TimeDelta current_time);
 
   // Callbacks needed by media::MediaPlayerBridge.
-  void OnPrepared(int player_id, base::TimeDelta duration);
+  void OnMediaMetadataChanged(int player_id, base::TimeDelta duration,
+                              int width, int height, bool success);
   void OnPlaybackComplete(int player_id);
   void OnMediaInterrupted(int player_id);
   void OnBufferingUpdate(int player_id, int percentage);
@@ -57,15 +62,24 @@
   void OnError(int player_id, int error);
   void OnVideoSizeChanged(int player_id, int width, int height);
 
+#if defined(GOOGLE_TV)
+  // Callbacks needed by media::DemuxerStreamPlayer.
+  void OnReadFromDemuxer(
+      int player_id, media::DemuxerStream::Type type, bool seek_done);
+#endif
+
   // media::MediaPlayerBridgeManager overrides.
   virtual void RequestMediaResources(media::MediaPlayerBridge* player) OVERRIDE;
   virtual void ReleaseMediaResources(media::MediaPlayerBridge* player) OVERRIDE;
+  virtual media::MediaResourceGetter* GetMediaResourceGetter() OVERRIDE;
 
   // Release all the players managed by this object.
   void DestroyAllMediaPlayers();
 
+#if defined(GOOGLE_TV)
   void AttachExternalVideoSurface(int player_id, jobject surface);
   void DetachExternalVideoSurface(int player_id);
+#endif
 
   media::MediaPlayerBridge* GetFullscreenPlayer();
   media::MediaPlayerBridge* GetPlayer(int player_id);
@@ -75,13 +89,23 @@
   void OnEnterFullscreen(int player_id);
   void OnExitFullscreen(int player_id);
   void OnInitialize(int player_id, const GURL& url,
+                    bool is_media_source,
                     const GURL& first_party_for_cookies);
   void OnStart(int player_id);
   void OnSeek(int player_id, base::TimeDelta time);
   void OnPause(int player_id);
   void OnReleaseResources(int player_id);
   void OnDestroyPlayer(int player_id);
+#if defined(GOOGLE_TV)
   void OnRequestExternalSurface(int player_id);
+  void OnNotifyGeometryChange(int player_id, const gfx::RectF& rect);
+  void OnDemuxerReady(
+      int player_id,
+      const media::MediaPlayerHostMsg_DemuxerReady_Params& params);
+  void OnReadFromDemuxerAck(
+      int player_id,
+      const media::MediaPlayerHostMsg_ReadFromDemuxerAck_Params& params);
+#endif
 
   // An array of managed players.
   ScopedVector<media::MediaPlayerBridge> players_;
@@ -94,9 +118,12 @@
 
   WebContents* web_contents_;
 
-  DISALLOW_COPY_AND_ASSIGN(MediaPlayerManagerAndroid);
+  // Object for retrieving resources media players.
+  scoped_ptr<media::MediaResourceGetter> media_resource_getter_;
+
+  DISALLOW_COPY_AND_ASSIGN(MediaPlayerManagerImpl);
 };
 
 }  // namespace content
 
-#endif  // CONTENT_BROWSER_ANDROID_MEDIA_PLAYER_MANAGER_ANDROID_H_
+#endif  // CONTENT_BROWSER_ANDROID_MEDIA_PLAYER_MANAGER_IMPL_H_
diff --git a/content/browser/android/media_resource_getter_impl.cc b/content/browser/android/media_resource_getter_impl.cc
index 2f5d4ee..00f92d6 100644
--- a/content/browser/android/media_resource_getter_impl.cc
+++ b/content/browser/android/media_resource_getter_impl.cc
@@ -4,8 +4,11 @@
 
 #include "content/browser/android/media_resource_getter_impl.h"
 
+#include "base/android/jni_android.h"
+#include "base/android/jni_string.h"
 #include "base/bind.h"
 #include "base/path_service.h"
+#include "base/threading/sequenced_worker_pool.h"
 #include "content/browser/child_process_security_policy_impl.h"
 #include "content/browser/fileapi/browser_file_system_helper.h"
 #include "content/public/browser/browser_context.h"
@@ -13,6 +16,7 @@
 #include "content/public/browser/content_browser_client.h"
 #include "content/public/common/content_client.h"
 #include "googleurl/src/gurl.h"
+#include "jni/MediaResourceGetter_jni.h"
 #include "net/cookies/cookie_monster.h"
 #include "net/cookies/cookie_store.h"
 #include "net/url_request/url_request_context.h"
@@ -27,6 +31,31 @@
       BrowserThread::UI, FROM_HERE, base::Bind(callback, result));
 }
 
+// Get the metadata from a media URL. When finished, a task is posted to the UI
+// thread to run the callback function.
+static void GetMediaMetadata(
+    const std::string& url, const std::string& cookies,
+    const media::MediaResourceGetter::ExtractMediaMetadataCB& callback) {
+  JNIEnv* env = base::android::AttachCurrentThread();
+
+  base::android::ScopedJavaLocalRef<jstring> j_url_string =
+      base::android::ConvertUTF8ToJavaString(env, url);
+  base::android::ScopedJavaLocalRef<jstring> j_cookies =
+      base::android::ConvertUTF8ToJavaString(env, cookies);
+  jobject j_context = base::android::GetApplicationContext();
+  base::android::ScopedJavaLocalRef<jobject> j_metadata =
+      Java_MediaResourceGetter_extractMediaMetadata(
+          env, j_context, j_url_string.obj(), j_cookies.obj());
+  BrowserThread::PostTask(
+      BrowserThread::UI, FROM_HERE,
+      base::Bind(callback, base::TimeDelta::FromMilliseconds(
+                     Java_MediaMetadata_getDurationInMilliseconds(
+                         env, j_metadata.obj())),
+                 Java_MediaMetadata_getWidth(env, j_metadata.obj()),
+                 Java_MediaMetadata_getHeight(env, j_metadata.obj()),
+                 Java_MediaMetadata_isSuccess(env, j_metadata.obj())));
+}
+
 // The task object that retrieves cookie on the IO thread.
 // TODO(qinmin): refactor this class to make the code reusable by others as
 // there are lots of duplicated functionalities elsewhere.
@@ -177,16 +206,16 @@
     int renderer_id, int routing_id)
     : browser_context_(browser_context),
       file_system_context_(file_system_context),
-      ALLOW_THIS_IN_INITIALIZER_LIST(weak_this_(this)),
+      weak_this_(this),
       renderer_id_(renderer_id),
       routing_id_(routing_id) {
 }
 
 MediaResourceGetterImpl::~MediaResourceGetterImpl() {}
 
-void MediaResourceGetterImpl::GetCookies(const GURL& url,
-                                  const GURL& first_party_for_cookies,
-                                  const GetCookieCB& callback) {
+void MediaResourceGetterImpl::GetCookies(
+    const GURL& url, const GURL& first_party_for_cookies,
+    const GetCookieCB& callback) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   scoped_refptr<CookieGetterTask> task = new CookieGetterTask(
       browser_context_, renderer_id_, routing_id_);
@@ -230,4 +259,18 @@
   callback.Run(platform_path);
 }
 
+void MediaResourceGetterImpl::ExtractMediaMetadata(
+    const std::string& url, const std::string& cookies,
+    const ExtractMediaMetadataCB& callback) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  base::SequencedWorkerPool* pool = content::BrowserThread::GetBlockingPool();
+  pool->PostWorkerTask(
+      FROM_HERE, base::Bind(&GetMediaMetadata, url, cookies, callback));
+}
+
+// static
+bool MediaResourceGetterImpl::RegisterMediaResourceGetter(JNIEnv* env) {
+  return RegisterNativesImpl(env);
+}
+
 }  // namespace content
diff --git a/content/browser/android/media_resource_getter_impl.h b/content/browser/android/media_resource_getter_impl.h
index 20ba44f..1d15244 100644
--- a/content/browser/android/media_resource_getter_impl.h
+++ b/content/browser/android/media_resource_getter_impl.h
@@ -5,6 +5,7 @@
 #ifndef CONTENT_BROWSER_ANDROID_MEDIA_RESOURCE_GETTER_IMPL_H_
 #define CONTENT_BROWSER_ANDROID_MEDIA_RESOURCE_GETTER_IMPL_H_
 
+#include <jni.h>
 #include <string>
 
 #include "base/memory/ref_counted.h"
@@ -46,6 +47,11 @@
   virtual void GetPlatformPathFromFileSystemURL(
       const GURL& url,
       const GetPlatformPathCB& callback) OVERRIDE;
+  virtual void ExtractMediaMetadata(
+      const std::string& url, const std::string& cookies,
+      const ExtractMediaMetadataCB& callback) OVERRIDE;
+
+  static bool RegisterMediaResourceGetter(JNIEnv* env);
 
  private:
   // Called when GetCookies() finishes.
diff --git a/content/browser/android/surface_texture_peer_browser_impl.cc b/content/browser/android/surface_texture_peer_browser_impl.cc
index afd999b..1cba847 100644
--- a/content/browser/android/surface_texture_peer_browser_impl.cc
+++ b/content/browser/android/surface_texture_peer_browser_impl.cc
@@ -4,12 +4,12 @@
 
 #include "content/browser/android/surface_texture_peer_browser_impl.h"
 
-#include "content/browser/android/media_player_manager_android.h"
+#include "content/browser/android/media_player_manager_impl.h"
 #include "content/browser/renderer_host/render_view_host_impl.h"
-#include "content/common/android/scoped_java_surface.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/render_process_host.h"
 #include "media/base/android/media_player_bridge.h"
+#include "ui/gl/android/scoped_java_surface.h"
 
 namespace content {
 
@@ -18,7 +18,7 @@
 // Pass a java surface object to the MediaPlayerBridge object
 // identified by render process handle, render view ID and player ID.
 static void SetSurfacePeer(
-    scoped_refptr<SurfaceTextureBridge> surface_texture_bridge,
+    scoped_refptr<gfx::SurfaceTextureBridge> surface_texture_bridge,
     base::ProcessHandle render_process_handle,
     int render_view_id,
     int player_id) {
@@ -40,7 +40,7 @@
           host->media_player_manager()->GetPlayer(player_id);
       if (player &&
           player != host->media_player_manager()->GetFullscreenPlayer()) {
-        ScopedJavaSurface surface(surface_texture_bridge.get());
+        gfx::ScopedJavaSurface surface(surface_texture_bridge.get());
         player->SetVideoSurface(surface.j_surface().obj());
       }
     }
@@ -57,7 +57,7 @@
 
 void SurfaceTexturePeerBrowserImpl::EstablishSurfaceTexturePeer(
     base::ProcessHandle render_process_handle,
-    scoped_refptr<SurfaceTextureBridge> surface_texture_bridge,
+    scoped_refptr<gfx::SurfaceTextureBridge> surface_texture_bridge,
     int render_view_id,
     int player_id) {
   if (!surface_texture_bridge)
diff --git a/content/browser/android/surface_texture_peer_browser_impl.h b/content/browser/android/surface_texture_peer_browser_impl.h
index 5ebe141..644bf2c 100644
--- a/content/browser/android/surface_texture_peer_browser_impl.h
+++ b/content/browser/android/surface_texture_peer_browser_impl.h
@@ -24,7 +24,7 @@
   // SurfaceTexturePeer implementation.
   virtual void EstablishSurfaceTexturePeer(
       base::ProcessHandle render_process_handle,
-      scoped_refptr<SurfaceTextureBridge> surface_texture_bridge,
+      scoped_refptr<gfx::SurfaceTextureBridge> surface_texture_bridge,
       int render_view_id,
       int player_id) OVERRIDE;
 
diff --git a/content/browser/appcache/appcache_dispatcher_host.cc b/content/browser/appcache/appcache_dispatcher_host.cc
index ac4564c..90a5dc7 100644
--- a/content/browser/appcache/appcache_dispatcher_host.cc
+++ b/content/browser/appcache/appcache_dispatcher_host.cc
@@ -16,13 +16,13 @@
     ChromeAppCacheService* appcache_service,
     int process_id)
     : appcache_service_(appcache_service),
-      ALLOW_THIS_IN_INITIALIZER_LIST(frontend_proxy_(this)),
+      frontend_proxy_(this),
       process_id_(process_id) {
 }
 
 void AppCacheDispatcherHost::OnChannelConnected(int32 peer_pid) {
   BrowserMessageFilter::OnChannelConnected(peer_pid);
-  if (appcache_service_.get()) {
+  if (appcache_service_) {
     backend_impl_.Initialize(
         appcache_service_.get(), &frontend_proxy_, process_id_);
     get_status_callback_ =
@@ -69,7 +69,7 @@
 }
 
 void AppCacheDispatcherHost::OnRegisterHost(int host_id) {
-  if (appcache_service_.get()) {
+  if (appcache_service_) {
     if (!backend_impl_.RegisterHost(host_id)) {
       BadMessageReceived();
     }
@@ -77,7 +77,7 @@
 }
 
 void AppCacheDispatcherHost::OnUnregisterHost(int host_id) {
-  if (appcache_service_.get()) {
+  if (appcache_service_) {
     if (!backend_impl_.UnregisterHost(host_id)) {
       BadMessageReceived();
     }
@@ -86,7 +86,7 @@
 
 void AppCacheDispatcherHost::OnSetSpawningHostId(
     int host_id, int spawning_host_id) {
-  if (appcache_service_.get()) {
+  if (appcache_service_) {
     if (!backend_impl_.SetSpawningHostId(host_id, spawning_host_id))
       BadMessageReceived();
   }
@@ -96,7 +96,7 @@
     int host_id, const GURL& document_url,
     int64 cache_document_was_loaded_from,
     const GURL& opt_manifest_url) {
-  if (appcache_service_.get()) {
+  if (appcache_service_) {
     if (!backend_impl_.SelectCache(host_id, document_url,
                                    cache_document_was_loaded_from,
                                    opt_manifest_url)) {
@@ -109,7 +109,7 @@
 
 void AppCacheDispatcherHost::OnSelectCacheForWorker(
     int host_id, int parent_process_id, int parent_host_id) {
-  if (appcache_service_.get()) {
+  if (appcache_service_) {
     if (!backend_impl_.SelectCacheForWorker(
             host_id, parent_process_id, parent_host_id)) {
       BadMessageReceived();
@@ -121,7 +121,7 @@
 
 void AppCacheDispatcherHost::OnSelectCacheForSharedWorker(
     int host_id, int64 appcache_id) {
-  if (appcache_service_.get()) {
+  if (appcache_service_) {
     if (!backend_impl_.SelectCacheForSharedWorker(host_id, appcache_id))
       BadMessageReceived();
   } else {
@@ -132,7 +132,7 @@
 void AppCacheDispatcherHost::OnMarkAsForeignEntry(
     int host_id, const GURL& document_url,
     int64 cache_document_was_loaded_from) {
-  if (appcache_service_.get()) {
+  if (appcache_service_) {
     if (!backend_impl_.MarkAsForeignEntry(host_id, document_url,
                                           cache_document_was_loaded_from)) {
       BadMessageReceived();
@@ -142,19 +142,19 @@
 
 void AppCacheDispatcherHost::OnGetResourceList(
     int host_id, std::vector<appcache::AppCacheResourceInfo>* params) {
-  if (appcache_service_.get())
+  if (appcache_service_)
     backend_impl_.GetResourceList(host_id, params);
 }
 
 void AppCacheDispatcherHost::OnGetStatus(int host_id, IPC::Message* reply_msg) {
-  if (pending_reply_msg_.get()) {
+  if (pending_reply_msg_) {
     BadMessageReceived();
     delete reply_msg;
     return;
   }
 
   pending_reply_msg_.reset(reply_msg);
-  if (appcache_service_.get()) {
+  if (appcache_service_) {
     if (!backend_impl_.GetStatusWithCallback(host_id, get_status_callback_,
                                              reply_msg)) {
       BadMessageReceived();
@@ -167,14 +167,14 @@
 
 void AppCacheDispatcherHost::OnStartUpdate(int host_id,
                                            IPC::Message* reply_msg) {
-  if (pending_reply_msg_.get()) {
+  if (pending_reply_msg_) {
     BadMessageReceived();
     delete reply_msg;
     return;
   }
 
   pending_reply_msg_.reset(reply_msg);
-  if (appcache_service_.get()) {
+  if (appcache_service_) {
     if (!backend_impl_.StartUpdateWithCallback(host_id, start_update_callback_,
                                                reply_msg)) {
       BadMessageReceived();
@@ -186,14 +186,14 @@
 }
 
 void AppCacheDispatcherHost::OnSwapCache(int host_id, IPC::Message* reply_msg) {
-  if (pending_reply_msg_.get()) {
+  if (pending_reply_msg_) {
     BadMessageReceived();
     delete reply_msg;
     return;
   }
 
   pending_reply_msg_.reset(reply_msg);
-  if (appcache_service_.get()) {
+  if (appcache_service_) {
     if (!backend_impl_.SwapCacheWithCallback(host_id, swap_cache_callback_,
                                              reply_msg)) {
       BadMessageReceived();
diff --git a/content/browser/appcache/chrome_appcache_service_unittest.cc b/content/browser/appcache/chrome_appcache_service_unittest.cc
index 0c8a7f4..d925104 100644
--- a/content/browser/appcache/chrome_appcache_service_unittest.cc
+++ b/content/browser/appcache/chrome_appcache_service_unittest.cc
@@ -63,16 +63,15 @@
 class ChromeAppCacheServiceTest : public testing::Test {
  public:
   ChromeAppCacheServiceTest()
-      : message_loop_(MessageLoop::TYPE_IO),
+      : message_loop_(base::MessageLoop::TYPE_IO),
         kProtectedManifestURL(kProtectedManifest),
         kNormalManifestURL(kNormalManifest),
         kSessionOnlyManifestURL(kSessionOnlyManifest),
         file_thread_(BrowserThread::FILE, &message_loop_),
-        file_user_blocking_thread_(
-            BrowserThread::FILE_USER_BLOCKING, &message_loop_),
+        file_user_blocking_thread_(BrowserThread::FILE_USER_BLOCKING,
+                                   &message_loop_),
         cache_thread_(BrowserThread::CACHE, &message_loop_),
-        io_thread_(BrowserThread::IO, &message_loop_) {
-  }
+        io_thread_(BrowserThread::IO, &message_loop_) {}
 
  protected:
   scoped_refptr<ChromeAppCacheService> CreateAppCacheService(
@@ -80,7 +79,7 @@
       bool init_storage);
   void InsertDataIntoAppCache(ChromeAppCacheService* appcache_service);
 
-  MessageLoop message_loop_;
+  base::MessageLoop message_loop_;
   base::ScopedTempDir temp_dir_;
   const GURL kProtectedManifestURL;
   const GURL kNormalManifestURL;
diff --git a/content/browser/browser_child_process_host_impl.cc b/content/browser/browser_child_process_host_impl.cc
index 7979c36..6a2218f 100644
--- a/content/browser/browser_child_process_host_impl.cc
+++ b/content/browser/browser_child_process_host_impl.cc
@@ -221,7 +221,7 @@
 base::TerminationStatus BrowserChildProcessHostImpl::GetTerminationStatus(
     int* exit_code) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-  if (!child_process_.get())  // If the delegate doesn't use Launch() helper.
+  if (!child_process_)  // If the delegate doesn't use Launch() helper.
     return base::GetTerminationStatus(data_.handle, exit_code);
   return child_process_->GetChildTerminationStatus(false /* known_dead */,
                                                    exit_code);
@@ -300,7 +300,8 @@
 }
 
 void BrowserChildProcessHostImpl::OnProcessLaunched() {
-  if (!child_process_->GetHandle()) {
+  base::ProcessHandle handle = child_process_->GetHandle();
+  if (!handle) {
     delete delegate_;  // Will delete us
     return;
   }
@@ -312,12 +313,12 @@
   // IPC channel thereafter.
   DCHECK(!early_exit_watcher_.GetWatchedEvent());
   early_exit_watcher_.StartWatching(
-      new base::WaitableEvent(child_process_->GetHandle()),
+      new base::WaitableEvent(handle),
       base::Bind(&BrowserChildProcessHostImpl::OnProcessExitedEarly,
                  base::Unretained(this)));
 #endif
 
-  data_.handle = child_process_->GetHandle();
+  data_.handle = handle;
   delegate_->OnProcessLaunched();
 }
 
diff --git a/content/browser/browser_context.cc b/content/browser/browser_context.cc
index cac0e2c..b32b58a 100644
--- a/content/browser/browser_context.cc
+++ b/content/browser/browser_context.cc
@@ -9,7 +9,7 @@
 #include "content/browser/appcache/chrome_appcache_service.h"
 #include "content/browser/dom_storage/dom_storage_context_impl.h"
 #include "content/browser/download/download_manager_impl.h"
-#include "content/browser/in_process_webkit/indexed_db_context_impl.h"
+#include "content/browser/indexed_db/indexed_db_context_impl.h"
 #include "content/browser/loader/resource_dispatcher_host_impl.h"
 #include "content/browser/storage_partition_impl.h"
 #include "content/browser/storage_partition_impl_map.h"
@@ -106,25 +106,16 @@
       ExamineClipboard(clipboard, ui::Clipboard::BUFFER_SELECTION);
   }
 
-  ui::Clipboard::SourceTag GetAsSourceTag() {
-    return ui::Clipboard::SourceTag(this);
+  ui::SourceTag GetAsSourceTag() {
+    return ui::SourceTag(this);
   }
 
  private:
   void ExamineClipboard(ui::Clipboard* clipboard,
                         ui::Clipboard::Buffer buffer) {
-    ui::Clipboard::SourceTag source_tag = clipboard->ReadSourceTag(buffer);
-    if (source_tag == ui::Clipboard::SourceTag(this)) {
-      if (buffer == ui::Clipboard::BUFFER_STANDARD) {
-        // We want to leave invalid SourceTag in the clipboard in order to
-        // collect statistics later.
-        clipboard->WriteObjects(buffer,
-                                ui::Clipboard::ObjectMap(),
-                                ui::Clipboard::kInvalidSourceTag);
-      } else {
-        clipboard->Clear(buffer);
-      }
-    }
+    ui::SourceTag source_tag = clipboard->ReadSourceTag(buffer);
+    if (source_tag == ui::SourceTag(this))
+      clipboard->Clear(buffer);
   }
 };
 
@@ -167,13 +158,12 @@
     DCHECK(rdh);
     scoped_refptr<DownloadManager> download_manager =
         new DownloadManagerImpl(
-            GetContentClient()->browser()->GetNetLog());
+            GetContentClient()->browser()->GetNetLog(), context);
 
     context->SetUserData(
         kDownloadManagerKeyName,
         new UserDataAdapter<DownloadManager>(download_manager));
     download_manager->SetDelegate(context->GetDownloadManagerDelegate());
-    download_manager->Init(context);
   }
 
   return UserDataAdapter<DownloadManager>::Get(
@@ -321,7 +311,7 @@
                           base::Bind(&PurgeDOMStorageContextInPartition));
 }
 
-ui::Clipboard::SourceTag BrowserContext::GetMarkerForOffTheRecordContext(
+ui::SourceTag BrowserContext::GetMarkerForOffTheRecordContext(
     BrowserContext* context) {
   if (context && context->IsOffTheRecord()) {
     OffTheRecordClipboardDestroyer* clipboard_destroyer =
@@ -329,7 +319,7 @@
 
     return clipboard_destroyer->GetAsSourceTag();
   }
-  return ui::Clipboard::SourceTag();
+  return ui::SourceTag();
 }
 #endif  // !OS_IOS
 
diff --git a/content/browser/browser_main_loop.cc b/content/browser/browser_main_loop.cc
index 4b7feb6..31f9f17 100644
--- a/content/browser/browser_main_loop.cc
+++ b/content/browser/browser_main_loop.cc
@@ -13,6 +13,8 @@
 #include "base/metrics/field_trial.h"
 #include "base/metrics/histogram.h"
 #include "base/pending_task.h"
+#include "base/power_monitor/power_monitor.h"
+#include "base/system_monitor/system_monitor.h"
 #include "base/run_loop.h"
 #include "base/string_number_conversions.h"
 #include "base/threading/thread_restrictions.h"
@@ -46,7 +48,6 @@
 #include "media/audio/audio_manager.h"
 #include "net/base/network_change_notifier.h"
 #include "net/socket/client_socket_factory.h"
-#include "net/socket/tcp_client_socket.h"
 #include "net/ssl/ssl_config_service.h"
 #include "ui/base/clipboard/clipboard.h"
 
@@ -232,7 +233,7 @@
 }
 
 // For measuring memory usage after each task. Behind a command line flag.
-class BrowserMainLoop::MemoryObserver : public MessageLoop::TaskObserver {
+class BrowserMainLoop::MemoryObserver : public base::MessageLoop::TaskObserver {
  public:
   MemoryObserver() {}
   virtual ~MemoryObserver() {}
@@ -292,6 +293,7 @@
 }
 
 void BrowserMainLoop::Init() {
+  TRACE_EVENT0("startup", "BrowserMainLoop::Init")
   parts_.reset(
       GetContentClient()->browser()->CreateBrowserMainParts(parameters_));
 }
@@ -299,6 +301,7 @@
 // BrowserMainLoop stages ==================================================
 
 void BrowserMainLoop::EarlyInitialization() {
+  TRACE_EVENT0("startup", "BrowserMainLoop::EarlyInitialization")
 #if defined(USE_X11)
   if (parsed_command_line_.HasSwitch(switches::kSingleProcess) ||
       parsed_command_line_.HasSwitch(switches::kInProcessGPU)) {
@@ -308,7 +311,7 @@
   }
 #endif
 
-  if (parts_.get())
+  if (parts_)
     parts_->PreEarlyInitialization();
 
 #if defined(OS_WIN)
@@ -327,11 +330,6 @@
   if (parsed_command_line_.HasSwitch(switches::kEnableSSLCachedInfo))
     net::SSLConfigService::EnableCachedInfo();
 
-  // TODO(abarth): Should this move to InitializeNetworkOptions?  This doesn't
-  // seem dependent on SSL initialization().
-  if (parsed_command_line_.HasSwitch(switches::kEnableTcpFastOpen))
-    net::SetTCPFastOpenEnabled(true);
-
 #if !defined(OS_IOS)
   if (parsed_command_line_.HasSwitch(switches::kRendererProcessLimit)) {
     std::string limit_string = parsed_command_line_.GetSwitchValueASCII(
@@ -343,13 +341,17 @@
   }
 #endif  // !defined(OS_IOS)
 
-  if (parts_.get())
+  if (parts_)
     parts_->PostEarlyInitialization();
 }
 
 void BrowserMainLoop::MainMessageLoopStart() {
-  if (parts_.get())
+  TRACE_EVENT0("startup", "BrowserMainLoop::MainMessageLoopStart")
+  if (parts_) {
+    TRACE_EVENT0("startup",
+        "BrowserMainLoop::MainMessageLoopStart:PreMainMessageLoopStart");
     parts_->PreMainMessageLoopStart();
+  }
 
 #if defined(OS_WIN)
   // If we're running tests (ui_task is non-null), then the ResourceBundle
@@ -361,12 +363,13 @@
 #endif
 
   // Create a MessageLoop if one does not already exist for the current thread.
-  if (!MessageLoop::current())
-    main_message_loop_.reset(new MessageLoop(MessageLoop::TYPE_UI));
+  if (!base::MessageLoop::current())
+    main_message_loop_.reset(new base::MessageLoop(base::MessageLoop::TYPE_UI));
 
   InitializeMainThread();
 
   system_monitor_.reset(new base::SystemMonitor);
+  power_monitor_.reset(new base::PowerMonitor);
   hi_res_timer_manager_.reset(new HighResolutionTimerManager);
   network_change_notifier_.reset(net::NetworkChangeNotifier::Create());
   audio_manager_.reset(media::AudioManager::Create());
@@ -398,7 +401,7 @@
   system_message_window_.reset(new SystemMessageWindowWin);
 #endif
 
-  if (parts_.get())
+  if (parts_)
     parts_->PostMainMessageLoopStart();
 
 #if defined(OS_ANDROID)
@@ -408,13 +411,18 @@
 
   if (parsed_command_line_.HasSwitch(switches::kMemoryMetrics)) {
     memory_observer_.reset(new MemoryObserver());
-    MessageLoop::current()->AddTaskObserver(memory_observer_.get());
+    base::MessageLoop::current()->AddTaskObserver(memory_observer_.get());
   }
 }
 
 void BrowserMainLoop::CreateThreads() {
-  if (parts_.get())
+  TRACE_EVENT0("startup", "BrowserMainLoop::CreateThreads")
+
+  if (parts_) {
+    TRACE_EVENT0("startup",
+        "BrowserMainLoop::MainMessageLoopStart:PreCreateThreads");
     result_code_ = parts_->PreCreateThreads();
+  }
 
 #if !defined(OS_IOS) && (!defined(GOOGLE_CHROME_BUILD) || defined(OS_ANDROID))
   // Single-process is an unsupported and not fully tested mode, so
@@ -428,9 +436,9 @@
 
   base::Thread::Options default_options;
   base::Thread::Options io_message_loop_options;
-  io_message_loop_options.message_loop_type = MessageLoop::TYPE_IO;
+  io_message_loop_options.message_loop_type = base::MessageLoop::TYPE_IO;
   base::Thread::Options ui_message_loop_options;
-  ui_message_loop_options.message_loop_type = MessageLoop::TYPE_UI;
+  ui_message_loop_options.message_loop_type = base::MessageLoop::TYPE_UI;
 
   // Start threads in the order they occur in the BrowserThread::ID
   // enumeration, except for BrowserThread::UI which is the main
@@ -445,16 +453,28 @@
 
     switch (thread_id) {
       case BrowserThread::DB:
+        TRACE_EVENT_BEGIN1("startup",
+            "BrowserMainLoop::CreateThreads:start",
+            "Thread", "BrowserThread::DB");
         thread_to_start = &db_thread_;
         break;
       case BrowserThread::WEBKIT_DEPRECATED:
         // Special case as WebKitThread is a separate
         // type.  |thread_to_start| is not used in this case.
+        TRACE_EVENT_BEGIN1("startup",
+            "BrowserMainLoop::CreateThreads:start",
+            "Thread", "BrowserThread::WEBKIT_DEPRECATED");
         break;
       case BrowserThread::FILE_USER_BLOCKING:
+        TRACE_EVENT_BEGIN1("startup",
+            "BrowserMainLoop::CreateThreads:start",
+            "Thread", "BrowserThread::FILE_USER_BLOCKING");
         thread_to_start = &file_user_blocking_thread_;
         break;
       case BrowserThread::FILE:
+        TRACE_EVENT_BEGIN1("startup",
+            "BrowserMainLoop::CreateThreads:start",
+            "Thread", "BrowserThread::FILE");
         thread_to_start = &file_thread_;
 #if defined(OS_WIN)
         // On Windows, the FILE thread needs to be have a UI message loop
@@ -466,13 +486,22 @@
 #endif
         break;
       case BrowserThread::PROCESS_LAUNCHER:
+        TRACE_EVENT_BEGIN1("startup",
+            "BrowserMainLoop::CreateThreads:start",
+            "Thread", "BrowserThread::PROCESS_LAUNCHER");
         thread_to_start = &process_launcher_thread_;
         break;
       case BrowserThread::CACHE:
+        TRACE_EVENT_BEGIN1("startup",
+            "BrowserMainLoop::CreateThreads:start",
+            "Thread", "BrowserThread::CACHE");
         thread_to_start = &cache_thread_;
         options = &io_message_loop_options;
         break;
       case BrowserThread::IO:
+        TRACE_EVENT_BEGIN1("startup",
+            "BrowserMainLoop::CreateThreads:start",
+            "Thread", "BrowserThread::IO");
         thread_to_start = &io_thread_;
         options = &io_message_loop_options;
         break;
@@ -496,12 +525,18 @@
     } else {
       NOTREACHED();
     }
+
+    TRACE_EVENT_END0("startup", "BrowserMainLoop::CreateThreads:start");
+
   }
 
   BrowserThreadsStarted();
 
-  if (parts_.get())
+  if (parts_) {
+    TRACE_EVENT0("startup",
+        "BrowserMainLoop::CreateThreads:PreMainMessageLoopRun");
     parts_->PreMainMessageLoopRun();
+  }
 
   // If the UI thread blocks, the whole UI is unresponsive.
   // Do not allow disk IO from the UI thread.
@@ -513,7 +548,7 @@
   TRACE_EVENT_BEGIN_ETW("BrowserMain:MESSAGE_LOOP", 0, "");
 
   bool ran_main_loop = false;
-  if (parts_.get())
+  if (parts_)
     ran_main_loop = parts_->MainMessageLoopRun(&result_code_);
 
   if (!ran_main_loop)
@@ -531,7 +566,7 @@
       base::Bind(base::IgnoreResult(&base::ThreadRestrictions::SetIOAllowed),
                  true));
 
-  if (parts_.get())
+  if (parts_)
     parts_->PostMainMessageLoopRun();
 
 #if !defined(OS_IOS)
@@ -542,7 +577,7 @@
   GpuProcessHostUIShim::DestroyAll();
 
   // Cancel pending requests and prevent new requests.
-  if (resource_dispatcher_host_.get())
+  if (resource_dispatcher_host_)
     resource_dispatcher_host_.get()->Shutdown();
 
 #if defined(USE_AURA)
@@ -610,7 +645,7 @@
 #if !defined(OS_IOS)
         // Clean up state that lives on or uses the file_thread_ before
         // it goes away.
-        if (resource_dispatcher_host_.get())
+        if (resource_dispatcher_host_)
           resource_dispatcher_host_.get()->save_file_manager()->Shutdown();
 #endif  // !defined(OS_IOS)
         break;
@@ -663,19 +698,19 @@
   URLDataManager::DeleteDataSources();
 #endif  // !defined(OS_IOS)
 
-  if (parts_.get())
+  if (parts_)
     parts_->PostDestroyThreads();
 }
 
 void BrowserMainLoop::InitializeMainThread() {
   const char* kThreadName = "CrBrowserMain";
   base::PlatformThread::SetName(kThreadName);
-  if (main_message_loop_.get())
+  if (main_message_loop_)
     main_message_loop_->set_thread_name(kThreadName);
 
   // Register the main thread by instantiating it, but don't call any methods.
-  main_thread_.reset(new BrowserThreadImpl(BrowserThread::UI,
-                                           MessageLoop::current()));
+  main_thread_.reset(
+      new BrowserThreadImpl(BrowserThread::UI, base::MessageLoop::current()));
 }
 
 #if defined(OS_ANDROID)
@@ -689,6 +724,7 @@
 #endif
 
 void BrowserMainLoop::BrowserThreadsStarted() {
+  TRACE_EVENT0("startup", "BrowserMainLoop::BrowserThreadsStarted")
 #if defined(OS_ANDROID)
 // TODO(epenner): Move thread priorities to base. (crbug.com/170549)
   BrowserThread::PostTask(BrowserThread::UI,
@@ -713,11 +749,19 @@
   device_monitor_mac_.reset(new DeviceMonitorMac());
 #endif
 
-  // RDH needs the IO thread to be created.
-  resource_dispatcher_host_.reset(new ResourceDispatcherHostImpl());
+  // RDH needs the IO thread to be created
+  {
+    TRACE_EVENT0("startup",
+      "BrowserMainLoop::BrowserThreadsStarted:InitResourceDispatcherHost");
+    resource_dispatcher_host_.reset(new ResourceDispatcherHostImpl());
+  }
 
   // MediaStreamManager needs the IO thread to be created.
-  media_stream_manager_.reset(new MediaStreamManager(audio_manager_.get()));
+  {
+    TRACE_EVENT0("startup",
+      "BrowserMainLoop::BrowserThreadsStarted:InitMediaStreamManager");
+    media_stream_manager_.reset(new MediaStreamManager(audio_manager_.get()));
+  }
 
   // Initialize the GpuDataManager before we set up the MessageLoops because
   // otherwise we'll trigger the assertion about doing IO on the UI thread.
@@ -725,7 +769,11 @@
 #endif  // !OS_IOS
 
 #if defined(ENABLE_INPUT_SPEECH)
-  speech_recognition_manager_.reset(new SpeechRecognitionManagerImpl());
+  {
+    TRACE_EVENT0("startup",
+      "BrowserMainLoop::BrowserThreadsStarted:InitSpeechRecognition");
+    speech_recognition_manager_.reset(new SpeechRecognitionManagerImpl());
+  }
 #endif
 
 #if !defined(OS_IOS)
@@ -744,12 +792,13 @@
   // When running the GPU thread in-process, avoid optimistically starting it
   // since creating the GPU thread races against creation of the one-and-only
   // ChildProcess instance which is created by the renderer thread.
-  if (GpuDataManagerImpl::GetInstance()->GpuAccessAllowed() &&
+  if (GpuDataManagerImpl::GetInstance()->GpuAccessAllowed(NULL) &&
       IsForceCompositingModeEnabled() &&
       !parsed_command_line_.HasSwitch(switches::kDisableGpuProcessPrelaunch) &&
       !parsed_command_line_.HasSwitch(switches::kSingleProcess) &&
       !parsed_command_line_.HasSwitch(switches::kInProcessGPU)) {
-    TRACE_EVENT_INSTANT0("gpu", "Post task to launch GPU process");
+    TRACE_EVENT_INSTANT0("gpu", "Post task to launch GPU process",
+                         TRACE_EVENT_SCOPE_THREAD);
     BrowserThread::PostTask(
         BrowserThread::IO, FROM_HERE, base::Bind(
             base::IgnoreResult(&GpuProcessHost::Get),
@@ -760,6 +809,7 @@
 }
 
 void BrowserMainLoop::InitializeToolkit() {
+  TRACE_EVENT0("startup", "BrowserMainLoop::InitializeToolkit")
   // TODO(evan): this function is rather subtle, due to the variety
   // of intersecting ifdefs we have.  To keep it easy to follow, there
   // are no #else branches on any #ifs.
@@ -800,7 +850,7 @@
     LOG_GETLASTERROR(FATAL);
 #endif
 
-  if (parts_.get())
+  if (parts_)
     parts_->ToolkitInitialized();
 }
 
@@ -809,9 +859,10 @@
   // Android's main message loop is the Java message loop.
   NOTREACHED();
 #else
-  DCHECK_EQ(MessageLoop::TYPE_UI, MessageLoop::current()->type());
+  DCHECK_EQ(base::MessageLoop::TYPE_UI, base::MessageLoop::current()->type());
   if (parameters_.ui_task)
-    MessageLoopForUI::current()->PostTask(FROM_HERE, *parameters_.ui_task);
+    base::MessageLoopForUI::current()->PostTask(FROM_HERE,
+                                                *parameters_.ui_task);
 
   base::RunLoop run_loop;
   run_loop.Run();
diff --git a/content/browser/browser_main_loop.h b/content/browser/browser_main_loop.h
index 25e15a0..30442a6 100644
--- a/content/browser/browser_main_loop.h
+++ b/content/browser/browser_main_loop.h
@@ -11,9 +11,10 @@
 
 class CommandLine;
 class HighResolutionTimerManager;
-class MessageLoop;
 
 namespace base {
+class MessageLoop;
+class PowerMonitor;
 class SystemMonitor;
 }
 
@@ -93,8 +94,9 @@
   int result_code_;
 
   // Members initialized in |MainMessageLoopStart()| ---------------------------
-  scoped_ptr<MessageLoop> main_message_loop_;
+  scoped_ptr<base::MessageLoop> main_message_loop_;
   scoped_ptr<base::SystemMonitor> system_monitor_;
+  scoped_ptr<base::PowerMonitor> power_monitor_;
   scoped_ptr<HighResolutionTimerManager> hi_res_timer_manager_;
   scoped_ptr<net::NetworkChangeNotifier> network_change_notifier_;
   scoped_ptr<media::AudioManager> audio_manager_;
diff --git a/content/browser/browser_main_runner.cc b/content/browser/browser_main_runner.cc
index c283db9..175b62f 100644
--- a/content/browser/browser_main_runner.cc
+++ b/content/browser/browser_main_runner.cc
@@ -43,6 +43,7 @@
 
   virtual int Initialize(const MainFunctionParams& parameters)
       OVERRIDE {
+    TRACE_EVENT0("startup", "BrowserMainRunnerImpl::Initialize")
     is_initialized_ = true;
 
 #if !defined(OS_IOS)
diff --git a/content/browser/browser_plugin/browser_plugin_embedder.cc b/content/browser/browser_plugin/browser_plugin_embedder.cc
index 10df740..12de8ef 100644
--- a/content/browser/browser_plugin/browser_plugin_embedder.cc
+++ b/content/browser/browser_plugin/browser_plugin_embedder.cc
@@ -10,6 +10,7 @@
 #include "content/browser/web_contents/web_contents_impl.h"
 #include "content/common/browser_plugin/browser_plugin_constants.h"
 #include "content/common/browser_plugin/browser_plugin_messages.h"
+#include "content/common/drag_messages.h"
 #include "content/common/gpu/gpu_messages.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/user_metrics.h"
@@ -40,6 +41,28 @@
   return new BrowserPluginEmbedder(web_contents);
 }
 
+void BrowserPluginEmbedder::DragEnteredGuest(BrowserPluginGuest* guest) {
+  guest_dragging_over_ = guest->AsWeakPtr();
+}
+
+void BrowserPluginEmbedder::DragLeftGuest(BrowserPluginGuest* guest) {
+  // Avoid race conditions in switching between guests being hovered over by
+  // only un-setting if the caller is marked as the guest being dragged over.
+  if (guest_dragging_over_ == guest) {
+    guest_dragging_over_.reset();
+  }
+}
+
+void BrowserPluginEmbedder::StartDrag(BrowserPluginGuest* guest) {
+  guest_started_drag_ = guest->AsWeakPtr();
+}
+
+void BrowserPluginEmbedder::StopDrag(BrowserPluginGuest* guest) {
+  if (guest_started_drag_ == guest) {
+    guest_started_drag_.reset();
+  }
+}
+
 void BrowserPluginEmbedder::GetRenderViewHostAtPosition(
     int x, int y, const WebContents::GetRenderViewHostCallback& callback) {
   // Store the callback so we can call it later when we have the response.
@@ -62,14 +85,46 @@
     IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_AllocateInstanceID,
                         OnAllocateInstanceID)
     IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_Attach, OnAttach)
-    IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_CreateGuest, OnCreateGuest)
     IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_PluginAtPositionResponse,
                         OnPluginAtPositionResponse)
+    IPC_MESSAGE_HANDLER_GENERIC(DragHostMsg_UpdateDragCursor,
+                                OnUpdateDragCursor(&handled));
     IPC_MESSAGE_UNHANDLED(handled = false)
   IPC_END_MESSAGE_MAP()
   return handled;
 }
 
+void BrowserPluginEmbedder::DragSourceEndedAt(int client_x, int client_y,
+    int screen_x, int screen_y, WebKit::WebDragOperation operation) {
+  if (guest_started_drag_) {
+    gfx::Point guest_offset =
+        guest_started_drag_->GetScreenCoordinates(gfx::Point());
+    guest_started_drag_->DragSourceEndedAt(client_x - guest_offset.x(),
+        client_y - guest_offset.y(), screen_x, screen_y, operation);
+  }
+}
+
+void BrowserPluginEmbedder::DragSourceMovedTo(int client_x, int client_y,
+                                              int screen_x, int screen_y) {
+  if (guest_started_drag_) {
+    gfx::Point guest_offset =
+        guest_started_drag_->GetScreenCoordinates(gfx::Point());
+    guest_started_drag_->DragSourceMovedTo(client_x - guest_offset.x(),
+        client_y - guest_offset.y(), screen_x, screen_y);
+  }
+}
+
+void BrowserPluginEmbedder::SystemDragEnded() {
+  if (guest_started_drag_ && (guest_started_drag_ != guest_dragging_over_))
+    guest_started_drag_->EndSystemDrag();
+  guest_started_drag_.reset();
+  guest_dragging_over_.reset();
+}
+
+void BrowserPluginEmbedder::OnUpdateDragCursor(bool* handled) {
+  *handled = (guest_dragging_over_ != NULL);
+}
+
 void BrowserPluginEmbedder::CleanUp() {
   // CleanUp gets called when BrowserPluginEmbedder's WebContents goes away
   // or the associated RenderViewHost is destroyed or swapped out. Therefore we
@@ -97,18 +152,21 @@
 
 void BrowserPluginEmbedder::OnAttach(
     int instance_id,
-    const BrowserPluginHostMsg_CreateGuest_Params& params) {
+    const BrowserPluginHostMsg_Attach_Params& params) {
+  if (!GetBrowserPluginGuestManager()->CanEmbedderAccessInstanceIDMaybeKill(
+          web_contents()->GetRenderProcessHost()->GetID(), instance_id))
+    return;
+
   BrowserPluginGuest* guest =
       GetBrowserPluginGuestManager()->GetGuestByInstanceID(
           instance_id, web_contents()->GetRenderProcessHost()->GetID());
-  if (guest)
-    guest->Attach(static_cast<WebContentsImpl*>(web_contents()), params);
-}
 
-void BrowserPluginEmbedder::OnCreateGuest(
-    int instance_id,
-    const BrowserPluginHostMsg_CreateGuest_Params& params) {
-  BrowserPluginGuest* guest = GetBrowserPluginGuestManager()->CreateGuest(
+  if (guest) {
+    guest->Attach(static_cast<WebContentsImpl*>(web_contents()), params);
+    return;
+  }
+
+  guest = GetBrowserPluginGuestManager()->CreateGuest(
       web_contents()->GetSiteInstance(), instance_id, params);
   if (guest)
     guest->Initialize(static_cast<WebContentsImpl*>(web_contents()), params);
@@ -122,9 +180,12 @@
     return;
 
   RenderViewHost* render_view_host;
-  BrowserPluginGuest* guest =
-      GetBrowserPluginGuestManager()->GetGuestByInstanceID(
-          instance_id, web_contents()->GetRenderProcessHost()->GetID());
+  BrowserPluginGuest* guest = NULL;
+  if (instance_id != browser_plugin::kInstanceIDNone) {
+    guest = GetBrowserPluginGuestManager()->GetGuestByInstanceID(
+                instance_id, web_contents()->GetRenderProcessHost()->GetID());
+  }
+
   if (guest)
     render_view_host = guest->GetWebContents()->GetRenderViewHost();
   else  // No plugin, use embedder's RenderViewHost.
diff --git a/content/browser/browser_plugin/browser_plugin_embedder.h b/content/browser/browser_plugin/browser_plugin_embedder.h
index ddcf6f1..1b6c8b2 100644
--- a/content/browser/browser_plugin/browser_plugin_embedder.h
+++ b/content/browser/browser_plugin/browser_plugin_embedder.h
@@ -16,10 +16,12 @@
 
 #include <map>
 
+#include "base/memory/weak_ptr.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_contents_observer.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebDragOperation.h"
 
-struct BrowserPluginHostMsg_CreateGuest_Params;
+struct BrowserPluginHostMsg_Attach_Params;
 struct BrowserPluginHostMsg_ResizeGuest_Params;
 
 namespace gfx {
@@ -28,6 +30,7 @@
 
 namespace content {
 
+class BrowserPluginGuest;
 class BrowserPluginGuestManager;
 class BrowserPluginHostFactory;
 class WebContentsImpl;
@@ -56,6 +59,24 @@
   virtual void RenderViewGone(base::TerminationStatus status) OVERRIDE;
   virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
 
+  void DragSourceEndedAt(int client_x, int client_y, int screen_x,
+      int screen_y, WebKit::WebDragOperation operation);
+
+  void DragSourceMovedTo(int client_x, int client_y,
+                         int screen_x, int screen_y);
+
+  void OnUpdateDragCursor(bool* handled);
+
+  void DragEnteredGuest(BrowserPluginGuest* guest);
+
+  void DragLeftGuest(BrowserPluginGuest* guest);
+
+  void StartDrag(BrowserPluginGuest* guest);
+
+  void StopDrag(BrowserPluginGuest* guest);
+
+  void SystemDragEnded();
+
  private:
   friend class TestBrowserPluginEmbedder;
 
@@ -69,9 +90,7 @@
 
   void OnAllocateInstanceID(int request_id);
   void OnAttach(int instance_id,
-                const BrowserPluginHostMsg_CreateGuest_Params& params);
-  void OnCreateGuest(int instance_id,
-                     const BrowserPluginHostMsg_CreateGuest_Params& params);
+                const BrowserPluginHostMsg_Attach_Params& params);
   void OnPluginAtPositionResponse(int instance_id,
                                   int request_id,
                                   const gfx::Point& position);
@@ -88,6 +107,17 @@
   // Next request id for BrowserPluginMsg_PluginAtPositionRequest query.
   int next_get_render_view_request_id_;
 
+  // Used to correctly update the cursor when dragging over a guest, and to
+  // handle a race condition when dropping onto the guest that started the drag
+  // (the race is that the dragend message arrives before the drop message so
+  // the drop never takes place).
+  // crbug.com/233571
+  base::WeakPtr<BrowserPluginGuest> guest_dragging_over_;
+
+  // Pointer to the guest that started the drag, used to forward necessary drag
+  // status messages to the correct guest.
+  base::WeakPtr<BrowserPluginGuest> guest_started_drag_;
+
   DISALLOW_COPY_AND_ASSIGN(BrowserPluginEmbedder);
 };
 
diff --git a/content/browser/browser_plugin/browser_plugin_geolocation_permission_context.cc b/content/browser/browser_plugin/browser_plugin_geolocation_permission_context.cc
index 59a23b5..8a803c4 100644
--- a/content/browser/browser_plugin/browser_plugin_geolocation_permission_context.cc
+++ b/content/browser/browser_plugin/browser_plugin_geolocation_permission_context.cc
@@ -49,7 +49,6 @@
   // have geolocation access.
   RenderViewHost* rvh = RenderViewHost::FromID(render_process_id,
                                                render_view_id);
-  DCHECK(rvh);
   if (rvh) {
     DCHECK(rvh->GetProcess()->IsGuest());
     WebContentsImpl* guest_web_contents =
diff --git a/content/browser/browser_plugin/browser_plugin_guest.cc b/content/browser/browser_plugin/browser_plugin_guest.cc
index 973408f..cffa56c 100644
--- a/content/browser/browser_plugin/browser_plugin_guest.cc
+++ b/content/browser/browser_plugin/browser_plugin_guest.cc
@@ -6,6 +6,7 @@
 
 #include <algorithm>
 
+#include "base/command_line.h"
 #include "base/message_loop.h"
 #include "base/string_util.h"
 #include "base/utf_string_conversions.h"
@@ -13,6 +14,8 @@
 #include "content/browser/browser_plugin/browser_plugin_guest_helper.h"
 #include "content/browser/browser_plugin/browser_plugin_guest_manager.h"
 #include "content/browser/browser_plugin/browser_plugin_host_factory.h"
+#include "content/browser/browser_thread_impl.h"
+#include "content/browser/loader/resource_dispatcher_host_impl.h"
 #include "content/browser/renderer_host/render_view_host_impl.h"
 #include "content/browser/renderer_host/render_widget_host_impl.h"
 #include "content/browser/web_contents/web_contents_impl.h"
@@ -22,6 +25,7 @@
 #include "content/common/content_constants_internal.h"
 #include "content/common/drag_messages.h"
 #include "content/common/gpu/gpu_messages.h"
+#include "content/common/input_messages.h"
 #include "content/common/view_messages.h"
 #include "content/port/browser/render_view_host_delegate_view.h"
 #include "content/public/browser/browser_context.h"
@@ -34,10 +38,13 @@
 #include "content/public/browser/resource_request_details.h"
 #include "content/public/browser/user_metrics.h"
 #include "content/public/browser/web_contents_view.h"
+#include "content/public/common/content_switches.h"
 #include "content/public/common/media_stream_request.h"
 #include "content/public/common/result_codes.h"
 #include "net/base/net_errors.h"
+#include "net/url_request/url_request.h"
 #include "third_party/WebKit/Source/WebKit/chromium/public/WebCursorInfo.h"
+#include "ui/base/keycodes/keyboard_codes.h"
 #include "ui/surface/transport_dib.h"
 #include "webkit/glue/resource_type.h"
 #include "webkit/glue/webdropdata.h"
@@ -51,6 +58,133 @@
 // static
 BrowserPluginHostFactory* BrowserPluginGuest::factory_ = NULL;
 
+// Parent class for the various types of permission requests, each of which
+// should be able to handle the response to their permission request.
+class BrowserPluginGuest::PermissionRequest {
+ public:
+  virtual void Respond(bool should_allow) = 0;
+  virtual ~PermissionRequest() {}
+ protected:
+  PermissionRequest() {}
+};
+
+class BrowserPluginGuest::DownloadRequest : public PermissionRequest {
+ public:
+  explicit DownloadRequest(base::Callback<void(bool)> callback)
+      : callback_(callback) {}
+  virtual void Respond(bool should_allow) OVERRIDE {
+    callback_.Run(should_allow);
+  }
+  virtual ~DownloadRequest() {}
+ private:
+  base::Callback<void(bool)> callback_;
+};
+
+class BrowserPluginGuest::GeolocationRequest : public PermissionRequest {
+ public:
+  GeolocationRequest(GeolocationCallback callback,
+                     int bridge_id,
+                     BrowserPluginGuest* guest,
+                     base::WeakPtrFactory<BrowserPluginGuest>* weak_ptr_factory)
+                     : callback_(callback),
+                       bridge_id_(bridge_id),
+                       guest_(guest),
+                       weak_ptr_factory_(weak_ptr_factory) {}
+
+  virtual void Respond(bool should_allow) OVERRIDE {
+    WebContents* web_contents = guest_->embedder_web_contents();
+    if (should_allow && web_contents) {
+      // If renderer side embedder decides to allow gelocation, we need to check
+      // if the app/embedder itself has geolocation access.
+      BrowserContext* browser_context = web_contents->GetBrowserContext();
+      if (browser_context) {
+        GeolocationPermissionContext* geolocation_context =
+            browser_context->GetGeolocationPermissionContext();
+        if (geolocation_context) {
+          base::Callback<void(bool)> geolocation_callback = base::Bind(
+              &BrowserPluginGuest::SetGeolocationPermission,
+              weak_ptr_factory_->GetWeakPtr(),
+              callback_,
+              bridge_id_);
+          geolocation_context->RequestGeolocationPermission(
+              web_contents->GetRenderProcessHost()->GetID(),
+              web_contents->GetRoutingID(),
+              // The geolocation permission request here is not initiated
+              // through WebGeolocationPermissionRequest. We are only interested
+              // in the fact whether the embedder/app has geolocation
+              // permission. Therefore we use an invalid |bridge_id|.
+              -1 /* bridge_id */,
+              web_contents->GetURL(),
+              geolocation_callback);
+          return;
+        }
+      }
+    }
+    guest_->SetGeolocationPermission(callback_, bridge_id_, false);
+  }
+  virtual ~GeolocationRequest() {}
+ private:
+  base::Callback<void(bool)> callback_;
+  int bridge_id_;
+  BrowserPluginGuest* guest_;
+  base::WeakPtrFactory<BrowserPluginGuest>* weak_ptr_factory_;
+};
+
+class BrowserPluginGuest::MediaRequest : public PermissionRequest {
+ public:
+  MediaRequest(const MediaStreamRequest& request,
+               const MediaResponseCallback& callback,
+               BrowserPluginGuest* guest)
+               : request_(request),
+                 callback_(callback),
+                 guest_(guest) {}
+
+  virtual void Respond(bool should_allow) OVERRIDE {
+    WebContentsImpl* web_contents = guest_->embedder_web_contents();
+    if (should_allow && web_contents) {
+      // Re-route the request to the embedder's WebContents; the guest gets the
+      // permission this way.
+      web_contents->RequestMediaAccessPermission(request_, callback_);
+    } else {
+      // Deny the request.
+      callback_.Run(MediaStreamDevices(), scoped_ptr<MediaStreamUI>());
+    }
+
+  }
+  virtual ~MediaRequest() {}
+ private:
+  MediaStreamRequest request_;
+  MediaResponseCallback callback_;
+  BrowserPluginGuest* guest_;
+};
+
+class BrowserPluginGuest::NewWindowRequest : public PermissionRequest {
+ public:
+  NewWindowRequest(int instance_id, BrowserPluginGuest* guest)
+      : instance_id_(instance_id),
+        guest_(guest) {}
+
+  virtual void Respond(bool should_allow) OVERRIDE {
+    int embedder_render_process_id =
+        guest_->embedder_web_contents()->GetRenderProcessHost()->GetID();
+    BrowserPluginGuest* guest =
+        guest_->GetWebContents()->GetBrowserPluginGuestManager()->
+            GetGuestByInstanceID(instance_id_, embedder_render_process_id);
+    if (!guest) {
+      LOG(INFO) << "Guest not found. Instance ID: " << instance_id_;
+      return;
+    }
+
+    // If we do not destroy the guest then we allow the new window.
+    if (!should_allow)
+      guest->Destroy();
+  }
+  virtual ~NewWindowRequest() {}
+ private:
+  int instance_id_;
+  BrowserPluginGuest* guest_;
+};
+
 namespace {
 const size_t kNumMaxOutstandingPermissionRequests = 1024;
 
@@ -77,8 +211,23 @@
   }
 }
 
+// Called on IO thread.
+static std::string RetrieveDownloadURLFromRequestId(
+    RenderViewHost* render_view_host,
+    int url_request_id) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+  int render_process_id = render_view_host->GetProcess()->GetID();
+  GlobalRequestID global_id(render_process_id, url_request_id);
+  net::URLRequest* url_request =
+      ResourceDispatcherHostImpl::Get()->GetURLRequest(global_id);
+  if (url_request)
+    return url_request->url().possibly_invalid_spec();
+  return std::string();
 }
 
+}  // namespace
+
 class BrowserPluginGuest::EmbedderRenderViewHostObserver
     : public RenderViewHostObserver {
  public:
@@ -94,6 +243,7 @@
   // RenderViewHostObserver:
   virtual void RenderViewHostDestroyed(
       RenderViewHost* render_view_host) OVERRIDE {
+    browser_plugin_guest_->embedder_web_contents_ = NULL;
     browser_plugin_guest_->Destroy();
   }
 
@@ -105,28 +255,53 @@
 
 BrowserPluginGuest::BrowserPluginGuest(
     int instance_id,
-    WebContentsImpl* web_contents)
+    WebContentsImpl* web_contents,
+    BrowserPluginGuest* opener,
+    bool has_render_view)
     : WebContentsObserver(web_contents),
-      ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)),
+      weak_ptr_factory_(this),
       embedder_web_contents_(NULL),
       instance_id_(instance_id),
       damage_buffer_sequence_id_(0),
       damage_buffer_size_(0),
       damage_buffer_scale_factor_(1.0f),
+      guest_device_scale_factor_(1.0f),
       guest_hang_timeout_(
           base::TimeDelta::FromMilliseconds(kHungRendererDelayMs)),
       focused_(false),
       mouse_locked_(false),
       pending_lock_request_(false),
       embedder_visible_(true),
-      opener_(NULL),
-      next_permission_request_id_(0) {
+      next_permission_request_id_(0),
+      has_render_view_(has_render_view) {
   DCHECK(web_contents);
   web_contents->SetDelegate(this);
+  if (opener)
+    opener_ = opener->AsWeakPtr();
   GetWebContents()->GetBrowserPluginGuestManager()->AddGuest(instance_id_,
                                                              GetWebContents());
 }
 
+bool BrowserPluginGuest::AddMessageToConsole(WebContents* source,
+                                             int32 level,
+                                             const string16& message,
+                                             int32 line_no,
+                                             const string16& source_id) {
+  base::DictionaryValue message_info;
+  // Log levels are from base/logging.h: LogSeverity.
+  message_info.Set(browser_plugin::kLevel,
+                   base::Value::CreateIntegerValue(level));
+  message_info.Set(browser_plugin::kMessage,
+                   base::Value::CreateStringValue(message));
+  message_info.Set(browser_plugin::kLine,
+                   base::Value::CreateIntegerValue(line_no));
+  message_info.Set(browser_plugin::kSourceId,
+                   base::Value::CreateStringValue(source_id));
+  SendMessageToEmbedder(
+      new BrowserPluginMsg_AddMessageToConsole(instance_id_, message_info));
+  return false;
+}
+
 void BrowserPluginGuest::DestroyUnattachedWindows() {
   // Destroy() reaches in and removes the BrowserPluginGuest from its opener's
   // pending_new_windows_ set. To avoid mutating the set while iterating, we
@@ -156,8 +331,12 @@
   IPC_BEGIN_MESSAGE_MAP(BrowserPluginGuest, message)
     IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_BuffersSwappedACK,
                         OnSwapBuffersACK)
+    IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_CompositorFrameACK,
+                        OnCompositorFrameACK)
     IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_DragStatusUpdate,
                         OnDragStatusUpdate)
+    IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ExecuteEditCommand,
+                        OnExecuteEditCommand)
     IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_Go, OnGo)
     IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_HandleInputEvent,
                         OnHandleInputEvent)
@@ -183,7 +362,7 @@
 
 void BrowserPluginGuest::Initialize(
     WebContentsImpl* embedder_web_contents,
-    const BrowserPluginHostMsg_CreateGuest_Params& params) {
+    const BrowserPluginHostMsg_Attach_Params& params) {
   focused_ = params.focused;
   guest_visible_ = params.visible;
   if (!params.name.empty())
@@ -244,6 +423,8 @@
   if (!params.src.empty())
     OnNavigateGuest(instance_id_, params.src);
 
+  has_render_view_ = true;
+
   GetContentClient()->browser()->GuestWebContentsCreated(
       GetWebContents(), embedder_web_contents_);
 }
@@ -258,7 +439,19 @@
   RecordAction(UserMetricsAction("BrowserPlugin.Guest.Create"));
   if (factory_)
     return factory_->CreateBrowserPluginGuest(instance_id, web_contents);
-  return new BrowserPluginGuest(instance_id, web_contents);
+  return new BrowserPluginGuest(instance_id, web_contents, NULL, false);
+}
+
+// static
+BrowserPluginGuest* BrowserPluginGuest::CreateWithOpener(
+    int instance_id,
+    WebContentsImpl* web_contents,
+    BrowserPluginGuest* opener,
+    bool has_render_view) {
+  return new BrowserPluginGuest(instance_id,
+                                web_contents,
+                                opener,
+                                has_render_view);
 }
 
 RenderWidgetHostView* BrowserPluginGuest::GetEmbedderRenderWidgetHostView() {
@@ -302,19 +495,39 @@
                                         const gfx::Rect& initial_pos,
                                         bool user_gesture,
                                         bool* was_blocked) {
-  *was_blocked = false;
+  if (was_blocked)
+    *was_blocked = false;
   RequestNewWindowPermission(static_cast<WebContentsImpl*>(new_contents),
                              disposition, initial_pos, user_gesture);
 }
 
-bool BrowserPluginGuest::CanDownload(RenderViewHost* render_view_host,
-                                    int request_id,
-                                    const std::string& request_method) {
-  // TODO(fsamuel): We disable downloads in guests for now, but we will later
-  // expose API to allow embedders to handle them.
-  // Note: it seems content_shell ignores this. This should be fixed
-  // for debugging and test purposes.
-  return false;
+void BrowserPluginGuest::CanDownload(
+    RenderViewHost* render_view_host,
+    int request_id,
+    const std::string& request_method,
+    const base::Callback<void(bool)>& callback) {
+  if (permission_request_map_.size() >= kNumMaxOutstandingPermissionRequests) {
+    // Deny the download request.
+    callback.Run(false);
+    return;
+  }
+
+  int permission_request_id = next_permission_request_id_++;
+  permission_request_map_[permission_request_id] =
+      new DownloadRequest(callback);
+
+  BrowserThread::PostTaskAndReplyWithResult(
+      BrowserThread::IO, FROM_HERE,
+      base::Bind(&RetrieveDownloadURLFromRequestId,
+                 render_view_host, request_id),
+      base::Bind(&BrowserPluginGuest::DidRetrieveDownloadURLFromRequestId,
+                 weak_ptr_factory_.GetWeakPtr(),
+                 request_method,
+                 permission_request_id));
+}
+
+void BrowserPluginGuest::CloseContents(WebContents* source) {
+  SendMessageToEmbedder(new BrowserPluginMsg_Close(instance_id_));
 }
 
 bool BrowserPluginGuest::HandleContextMenu(
@@ -325,6 +538,45 @@
   return true;
 }
 
+void BrowserPluginGuest::HandleKeyboardEvent(
+    WebContents* source,
+    const NativeWebKeyboardEvent& event) {
+  if (!attached())
+    return;
+
+  // Send the unhandled keyboard events back to the embedder to reprocess them.
+  // TODO(fsamuel): This introduces the possibility of out-of-order keyboard
+  // events because the guest may be arbitrarily delayed when responding to
+  // keyboard events. In that time, the embedder may have received and processed
+  // additional key events. This needs to be fixed as soon as possible.
+  // See http://crbug.com/229882.
+  embedder_web_contents_->GetDelegate()->HandleKeyboardEvent(
+      web_contents(), event);
+}
+
+WebContents* BrowserPluginGuest::OpenURLFromTab(WebContents* source,
+                                                const OpenURLParams& params) {
+  // If the guest wishes to navigate away prior to attachment then we save the
+  // navigation to perform upon attachment. Navigation initializes a lot of
+  // state that assumes an embedder exists, such as RenderWidgetHostViewGuest.
+  // Navigation also resumes resource loading which we don't want to allow
+  // until attachment.
+  if (!attached()) {
+    PendingWindowMap::iterator it = opener()->pending_new_windows_.find(this);
+    if (it == opener()->pending_new_windows_.end())
+      return NULL;
+    const TargetURL& old_target_url = it->second;
+    TargetURL new_target_url(params.url);
+    new_target_url.changed = new_target_url.url != old_target_url.url;
+    it->second = new_target_url;
+    return NULL;
+  }
+  // This can happen for cross-site redirects.
+  source->GetController().LoadURL(
+        params.url, params.referrer, params.transition, std::string());
+  return source;
+}
+
 void BrowserPluginGuest::WebContentsCreated(WebContents* source_contents,
                                             int64 source_frame_id,
                                             const string16& frame_name,
@@ -333,12 +585,12 @@
   WebContentsImpl* new_contents_impl =
       static_cast<WebContentsImpl*>(new_contents);
   BrowserPluginGuest* guest = new_contents_impl->GetBrowserPluginGuest();
-  guest->opener_ = this;
+  guest->opener_ = AsWeakPtr();
   guest->name_ = UTF16ToUTF8(frame_name);
   // Take ownership of the new guest until it is attached to the embedder's DOM
   // tree to avoid leaking a guest if this guest is destroyed before attaching
   // the new guest.
-  pending_new_windows_.insert(make_pair(guest, target_url.spec()));
+  pending_new_windows_.insert(std::make_pair(guest, TargetURL(target_url)));
 }
 
 void BrowserPluginGuest::RendererUnresponsive(WebContents* source) {
@@ -423,21 +675,22 @@
   PendingWindowMap::iterator it = pending_new_windows_.find(guest);
   if (it == pending_new_windows_.end())
     return;
-  const std::string& target_url = it->second;
+  const TargetURL& target_url = it->second;
   base::DictionaryValue request_info;
   request_info.Set(browser_plugin::kInitialHeight,
                    base::Value::CreateIntegerValue(initial_bounds.height()));
   request_info.Set(browser_plugin::kInitialWidth,
                    base::Value::CreateIntegerValue(initial_bounds.width()));
   request_info.Set(browser_plugin::kTargetURL,
-                   base::Value::CreateStringValue(target_url));
+                   base::Value::CreateStringValue(target_url.url.spec()));
   request_info.Set(browser_plugin::kWindowID,
                    base::Value::CreateIntegerValue(guest->instance_id()));
   request_info.Set(browser_plugin::kWindowOpenDisposition,
                    base::Value::CreateStringValue(
                        WindowOpenDispositionToString(disposition)));
   int request_id = next_permission_request_id_++;
-  new_window_request_map_[request_id] = guest->instance_id();
+  permission_request_map_[request_id] =
+      new NewWindowRequest(guest->instance_id(), this);
   SendMessageToEmbedder(new BrowserPluginMsg_RequestPermission(
       instance_id(), BrowserPluginPermissionTypeNewWindow,
       request_id, request_info));
@@ -485,6 +738,29 @@
   embedder_web_contents_->Send(msg);
 }
 
+void BrowserPluginGuest::DragSourceEndedAt(int client_x, int client_y,
+    int screen_x, int screen_y, WebKit::WebDragOperation operation) {
+  web_contents()->GetRenderViewHost()->DragSourceEndedAt(client_x, client_y,
+      screen_x, screen_y, operation);
+}
+
+void BrowserPluginGuest::DragSourceMovedTo(int client_x, int client_y,
+                                           int screen_x, int screen_y) {
+  web_contents()->GetRenderViewHost()->DragSourceMovedTo(client_x, client_y,
+                                                         screen_x, screen_y);
+}
+
+void BrowserPluginGuest::EndSystemDrag() {
+  RenderViewHostImpl* guest_rvh = static_cast<RenderViewHostImpl*>(
+      GetWebContents()->GetRenderViewHost());
+  guest_rvh->DragSourceSystemDragEnded();
+  // Issue a MouseUp event to get out of a selection state.
+  WebKit::WebMouseEvent mouse_event;
+  mouse_event.type = WebKit::WebInputEvent::MouseUp;
+  mouse_event.button = WebKit::WebMouseEvent::ButtonLeft;
+  guest_rvh->ForwardMouseEvent(mouse_event);
+}
+
 void BrowserPluginGuest::LoadRedirect(
     const GURL& old_url,
     const GURL& new_url,
@@ -500,14 +776,17 @@
     int bridge_id,
     const GURL& requesting_frame,
     const GeolocationCallback& callback) {
-  if (geolocation_request_callback_map_.size() >=
-          kNumMaxOutstandingPermissionRequests) {
+  if (permission_request_map_.size() >= kNumMaxOutstandingPermissionRequests) {
     // Deny the geolocation request.
     callback.Run(false);
     return;
   }
   int request_id = next_permission_request_id_++;
-  geolocation_request_callback_map_[request_id] = callback;
+  permission_request_map_[request_id] = new GeolocationRequest(
+      callback, bridge_id, this, &weak_ptr_factory_);
+  DCHECK(bridge_id_to_request_id_map_.find(bridge_id) ==
+         bridge_id_to_request_id_map_.end());
+  bridge_id_to_request_id_map_[bridge_id] = request_id;
 
   base::DictionaryValue request_info;
   request_info.Set(browser_plugin::kURL,
@@ -519,20 +798,25 @@
 }
 
 void BrowserPluginGuest::CancelGeolocationRequest(int bridge_id) {
-  GeolocationRequestsMap::iterator callback_iter =
-      geolocation_request_callback_map_.find(bridge_id);
-  if (callback_iter != geolocation_request_callback_map_.end())
-    geolocation_request_callback_map_.erase(callback_iter);
+  std::map<int, int>::iterator bridge_itr =
+      bridge_id_to_request_id_map_.find(bridge_id);
+  if (bridge_itr == bridge_id_to_request_id_map_.end())
+    return;
+
+  int request_id = bridge_itr->second;
+  bridge_id_to_request_id_map_.erase(bridge_itr);
+  RequestMap::iterator request_itr = permission_request_map_.find(request_id);
+  if (request_itr == permission_request_map_.end())
+    return;
+  delete request_itr->second;
+  permission_request_map_.erase(request_itr);
 }
 
-void BrowserPluginGuest::SetGeolocationPermission(int request_id,
+void BrowserPluginGuest::SetGeolocationPermission(GeolocationCallback callback,
+                                                  int bridge_id,
                                                   bool allowed) {
-  GeolocationRequestsMap::iterator callback_iter =
-      geolocation_request_callback_map_.find(request_id);
-  if (callback_iter != geolocation_request_callback_map_.end()) {
-    callback_iter->second.Run(allowed);
-    geolocation_request_callback_map_.erase(callback_iter);
-  }
+  callback.Run(allowed);
+  CancelGeolocationRequest(bridge_id);
 }
 
 void BrowserPluginGuest::DidCommitProvisionalLoadForFrame(
@@ -557,20 +841,29 @@
 }
 
 void BrowserPluginGuest::DidStopLoading(RenderViewHost* render_view_host) {
-  // Initiating a drag from inside a guest is currently not supported. So inject
-  // some JS to disable it. http://crbug.com/161112
-  const char script[] = "window.addEventListener('dragstart', function() { "
-                        "  window.event.preventDefault(); "
-                        "});";
-  render_view_host->ExecuteJavascriptInWebFrame(string16(),
-                                                ASCIIToUTF16(script));
+  bool disable_dragdrop = true;
+#if defined(OS_LINUX) || defined(OS_MACOSX)
+  if (CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kEnableBrowserPluginDragDrop))
+    disable_dragdrop = false;
+#endif  // defined(OS_LINUX) || defined(OS_MACOSX)
+  if (disable_dragdrop) {
+    // Initiating a drag from inside a guest is currently not supported without
+    // the kEnableBrowserPluginDragDrop flag on a linux platform. So inject some
+    // JS to disable it. http://crbug.com/161112
+    const char script[] = "window.addEventListener('dragstart', function() { "
+                          "  window.event.preventDefault(); "
+                          "});";
+    render_view_host->ExecuteJavascriptInWebFrame(string16(),
+                                                  ASCIIToUTF16(script));
+  }
   SendMessageToEmbedder(new BrowserPluginMsg_LoadStop(instance_id()));
 }
 
 void BrowserPluginGuest::RenderViewReady() {
   // TODO(fsamuel): Investigate whether it's possible to update state earlier
   // here (see http://crbug.com/158151).
-  Send(new ViewMsg_SetFocus(routing_id(), focused_));
+  Send(new InputMsg_SetFocus(routing_id(), focused_));
   UpdateVisibility();
   RenderViewHost* rvh = GetWebContents()->GetRenderViewHost();
   if (auto_size_enabled_)
@@ -622,7 +915,9 @@
     const IPC::Message& message) {
   switch (message.type()) {
     case BrowserPluginHostMsg_BuffersSwappedACK::ID:
+    case BrowserPluginHostMsg_CompositorFrameACK::ID:
     case BrowserPluginHostMsg_DragStatusUpdate::ID:
+    case BrowserPluginHostMsg_ExecuteEditCommand::ID:
     case BrowserPluginHostMsg_Go::ID:
     case BrowserPluginHostMsg_HandleInputEvent::ID:
     case BrowserPluginHostMsg_LockMouse_ACK::ID:
@@ -659,11 +954,9 @@
     // renderer process paints inside.
     IPC_MESSAGE_HANDLER(ViewHostMsg_ShowPopup, OnShowPopup)
  #endif
-    IPC_MESSAGE_HANDLER(ViewHostMsg_ShowView, OnShowView)
     IPC_MESSAGE_HANDLER(ViewHostMsg_ShowWidget, OnShowWidget)
     IPC_MESSAGE_HANDLER(ViewHostMsg_TakeFocus, OnTakeFocus)
     IPC_MESSAGE_HANDLER(ViewHostMsg_UnlockMouse, OnUnlockMouse)
-    IPC_MESSAGE_HANDLER(DragHostMsg_UpdateDragCursor, OnUpdateDragCursor)
     IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateFrameName, OnUpdateFrameName)
     IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateRect, OnUpdateRect)
     IPC_MESSAGE_UNHANDLED(handled = false)
@@ -673,26 +966,39 @@
 
 void BrowserPluginGuest::Attach(
     WebContentsImpl* embedder_web_contents,
-    BrowserPluginHostMsg_CreateGuest_Params params) {
-  const std::string target_url = opener()->pending_new_windows_[this];
-  if (!GetWebContents()->opener()) {
-    // For guests that have a suppressed opener, we navigate now.
-    // Navigation triggers the creation of a RenderWidgetHostViewGuest so
-    // we don't need to create one manually.
-    params.src = target_url;
-  } else {
-    // Ensure that the newly attached guest gets a RenderWidgetHostViewGuest.
+    BrowserPluginHostMsg_Attach_Params params) {
+  if (attached())
+    return;
+
+  // Clear parameters that get inherited from the opener.
+  params.storage_partition_id.clear();
+  params.persist_storage = false;
+  params.src.clear();
+
+  // If a RenderView has already been created for this new window, then we need
+  // to initialize the browser-side state now so that the RenderViewHostManager
+  // does not create a new RenderView on navigation.
+  if (has_render_view_) {
+    static_cast<RenderViewHostImpl*>(
+        GetWebContents()->GetRenderViewHost())->Init();
     WebContentsViewGuest* new_view =
         static_cast<WebContentsViewGuest*>(GetWebContents()->GetView());
     new_view->CreateViewForWidget(web_contents()->GetRenderViewHost());
-
-    // Reply to ViewHostMsg_ShowView to inform the renderer that the browser has
-    // processed the move.  The browser may have ignored the move, but it
-    // finished processing.  This is used because the renderer keeps a temporary
-    // cache of the widget position while these asynchronous operations are in
-    // progress.
-    Send(new ViewMsg_Move_ACK(web_contents()->GetRoutingID()));
   }
+
+  // We need to do a navigation here if the target URL has changed between
+  // the time the WebContents was created and the time it was attached.
+  // We also need to do an initial navigation if a RenderView was never
+  // created for the new window in cases where there is no referrer.
+  PendingWindowMap::iterator it = opener()->pending_new_windows_.find(this);
+  if (it != opener()->pending_new_windows_.end()) {
+    const TargetURL& target_url = it->second;
+    if (target_url.changed || !has_render_view_)
+      params.src = it->second.url.spec();
+  } else {
+    NOTREACHED();
+  }
+
   // Once a new guest is attached to the DOM of the embedder page, then the
   // lifetime of the new guest is no longer managed by the opener guest.
   opener()->pending_new_windows_.erase(this);
@@ -705,19 +1011,27 @@
 
   Initialize(embedder_web_contents, params);
 
-  // We initialize the RenderViewHost after a BrowserPlugin has been attached
-  // to it and is ready to receive pixels. Until a RenderViewHost is
-  // initialized, it will not allow any resize requests.
-  if (!GetWebContents()->GetRenderViewHost()->IsRenderViewLive()) {
-    static_cast<RenderViewHostImpl*>(
-        GetWebContents()->GetRenderViewHost())->Init();
-  }
+  // Inform the embedder of the guest's information.
+  // We pull the partition information from the site's URL, which is of the form
+  // guest://site/{persist}?{partition_name}.
+  const GURL& site_url = GetWebContents()->GetSiteInstance()->GetSiteURL();
+  BrowserPluginMsg_Attach_ACK_Params ack_params;
+  ack_params.storage_partition_id = site_url.query();
+  ack_params.persist_storage =
+      site_url.path().find("persist") != std::string::npos;
+  ack_params.name = name_;
+  SendMessageToEmbedder(
+      new BrowserPluginMsg_Attach_ACK(instance_id_, ack_params));
+}
 
-  // Inform the embedder BrowserPlugin of the attached guest.
-  if (!name_.empty()) {
-    SendMessageToEmbedder(
-        new BrowserPluginMsg_UpdatedName(instance_id_, name_));
-  }
+void BrowserPluginGuest::OnCompositorFrameACK(
+    int instance_id,
+    int route_id,
+    int renderer_host_id,
+    const cc::CompositorFrameAck& ack) {
+  RenderWidgetHostImpl::SendSwapCompositorFrameAck(route_id,
+                                                   renderer_host_id,
+                                                   ack);
 }
 
 void BrowserPluginGuest::OnDragStatusUpdate(int instance_id,
@@ -728,22 +1042,31 @@
   RenderViewHost* host = GetWebContents()->GetRenderViewHost();
   switch (drag_status) {
     case WebKit::WebDragStatusEnter:
+      embedder_web_contents_->GetBrowserPluginEmbedder()->DragEnteredGuest(
+          this);
       host->DragTargetDragEnter(drop_data, location, location, mask, 0);
       break;
     case WebKit::WebDragStatusOver:
       host->DragTargetDragOver(location, location, mask, 0);
       break;
     case WebKit::WebDragStatusLeave:
+      embedder_web_contents_->GetBrowserPluginEmbedder()->DragLeftGuest(this);
       host->DragTargetDragLeave();
       break;
     case WebKit::WebDragStatusDrop:
       host->DragTargetDrop(location, location, 0);
+      EndSystemDrag();
       break;
     case WebKit::WebDragStatusUnknown:
       NOTREACHED();
   }
 }
 
+void BrowserPluginGuest::OnExecuteEditCommand(int instance_id,
+                                              const std::string& name) {
+  Send(new InputMsg_ExecuteEditCommand(routing_id(), name, std::string()));
+}
+
 void BrowserPluginGuest::OnGo(int instance_id, int relative_index) {
   GetWebContents()->GetController().GoToOffset(relative_index);
 }
@@ -753,10 +1076,16 @@
     const gfx::Rect& guest_window_rect,
     const WebKit::WebInputEvent* event) {
   guest_window_rect_ = guest_window_rect;
-  guest_screen_rect_ = guest_window_rect;
-  guest_screen_rect_.Offset(
-      embedder_web_contents_->GetRenderViewHost()->GetView()->
-          GetViewBounds().OffsetFromOrigin());
+  // If the embedder's RWHV is destroyed then that means that the embedder's
+  // window has been closed but the embedder's WebContents has not yet been
+  // destroyed. Computing screen coordinates of a BrowserPlugin only makes sense
+  // if there is a visible embedder.
+  if (embedder_web_contents_->GetRenderWidgetHostView()) {
+    guest_screen_rect_ = guest_window_rect;
+    guest_screen_rect_.Offset(
+        embedder_web_contents_->GetRenderWidgetHostView()->
+            GetViewBounds().OffsetFromOrigin());
+  }
   RenderViewHostImpl* guest_rvh = static_cast<RenderViewHostImpl*>(
       GetWebContents()->GetRenderViewHost());
 
@@ -773,12 +1102,12 @@
   }
 
   if (WebKit::WebInputEvent::isKeyboardEventType(event->type)) {
-    NativeWebKeyboardEvent keyboard_event;
-    const WebKit::WebKeyboardEvent* original_event =
-        static_cast<const WebKit::WebKeyboardEvent*>(event);
-    memcpy(&keyboard_event, original_event, sizeof(WebKit::WebKeyboardEvent));
-    if (keyboard_event.type == WebKit::WebInputEvent::KeyDown)
-      keyboard_event.type = WebKit::WebInputEvent::RawKeyDown;
+    RenderViewHostImpl* embedder_rvh = static_cast<RenderViewHostImpl*>(
+        embedder_web_contents_->GetRenderViewHost());
+    if (!embedder_rvh->GetLastKeyboardEvent())
+      return;
+    NativeWebKeyboardEvent keyboard_event(
+        *embedder_rvh->GetLastKeyboardEvent());
     guest_rvh->ForwardKeyboardEvent(keyboard_event);
     return;
   }
@@ -870,11 +1199,19 @@
     RenderWidgetHostImpl* render_widget_host =
         RenderWidgetHostImpl::From(GetWebContents()->GetRenderViewHost());
     render_widget_host->ResetSizeAndRepaintPendingFlags();
+
+    if (guest_device_scale_factor_ != params.scale_factor) {
+      guest_device_scale_factor_ = params.scale_factor;
+      render_widget_host->NotifyScreenInfoChanged();
+    }
   }
+  // Invalid damage buffer means we are in HW compositing mode,
+  // so just resize the WebContents and repaint if needed.
   if (!base::SharedMemory::IsHandleValid(params.damage_buffer_handle)) {
-    // Invalid damage buffer, so just resize the WebContents.
     if (!params.view_size.IsEmpty())
       GetWebContents()->GetView()->SizeContents(params.view_size);
+    if (params.repaint)
+      Send(new ViewMsg_Repaint(routing_id(), params.view_size));
     return;
   }
   SetDamageBuffer(params);
@@ -887,7 +1224,9 @@
   if (focused_ == focused)
       return;
   focused_ = focused;
-  Send(new ViewMsg_SetFocus(routing_id(), focused));
+  Send(new InputMsg_SetFocus(routing_id(), focused));
+  if (!focused && mouse_locked_)
+    OnUnlockMouse();
 }
 
 void BrowserPluginGuest::OnSetName(int instance_id, const std::string& name) {
@@ -944,19 +1283,18 @@
     BrowserPluginPermissionType permission_type,
     int request_id,
     bool should_allow) {
-  switch (permission_type) {
-    case BrowserPluginPermissionTypeGeolocation:
-      OnRespondPermissionGeolocation(request_id, should_allow);
-      break;
-    case BrowserPluginPermissionTypeMedia:
-      OnRespondPermissionMedia(request_id, should_allow);
-      break;
-    case BrowserPluginPermissionTypeNewWindow:
-      OnRespondPermissionNewWindow(request_id, should_allow);
-      break;
-    default:
-      NOTREACHED();
-      break;
+  RequestMap::iterator request_itr = permission_request_map_.find(request_id);
+  if (request_itr == permission_request_map_.end()) {
+    LOG(INFO) << "Not a valid request ID.";
+    return;
+  }
+  request_itr->second->Respond(should_allow);
+
+  // Geolocation requests have to hang around for a while, so we don't delete
+  // them here.
+  if (permission_type != BrowserPluginPermissionTypeGeolocation) {
+    delete request_itr->second;
+    permission_request_map_.erase(request_itr);
   }
 }
 
@@ -1032,18 +1370,6 @@
 }
 #endif
 
-void BrowserPluginGuest::OnShowView(int route_id,
-                                    WindowOpenDisposition disposition,
-                                    const  gfx::Rect& initial_bounds,
-                                    bool user_gesture) {
-  RenderViewHostImpl* rvh = RenderViewHostImpl::FromID(
-      web_contents()->GetRenderProcessHost()->GetID(), route_id);
-  WebContentsImpl* web_contents = static_cast<WebContentsImpl*>(
-      WebContents::FromRenderViewHost(rvh));
-  RequestNewWindowPermission(
-      web_contents, disposition, initial_bounds, user_gesture);
-}
-
 void BrowserPluginGuest::OnShowWidget(int route_id,
                                       const gfx::Rect& initial_pos) {
   gfx::Rect screen_pos(initial_pos);
@@ -1056,18 +1382,6 @@
       new BrowserPluginMsg_AdvanceFocus(instance_id(), reverse));
 }
 
-void BrowserPluginGuest::OnUpdateDragCursor(
-    WebKit::WebDragOperation operation) {
-  RenderViewHostImpl* embedder_render_view_host =
-      static_cast<RenderViewHostImpl*>(
-          embedder_web_contents_->GetRenderViewHost());
-  CHECK(embedder_render_view_host);
-  RenderViewHostDelegateView* view =
-      embedder_render_view_host->GetDelegate()->GetDelegateView();
-  if (view)
-    view->UpdateDragCursor(operation);
-}
-
 void BrowserPluginGuest::OnUpdateFrameName(int frame_id,
                                            bool is_top_level,
                                            const std::string& name) {
@@ -1082,15 +1396,14 @@
     WebContents* web_contents,
     const MediaStreamRequest& request,
     const MediaResponseCallback& callback) {
-  if (media_requests_map_.size() >= kNumMaxOutstandingPermissionRequests) {
+  if (permission_request_map_.size() >= kNumMaxOutstandingPermissionRequests) {
     // Deny the media request.
-    callback.Run(MediaStreamDevices());
+    callback.Run(MediaStreamDevices(), scoped_ptr<MediaStreamUI>());
     return;
   }
   int request_id = next_permission_request_id_++;
-  media_requests_map_.insert(
-      std::make_pair(request_id,
-                     std::make_pair(request, callback)));
+  permission_request_map_[request_id] =
+      new MediaRequest(request, callback, this);
 
   base::DictionaryValue request_info;
   request_info.Set(
@@ -1157,83 +1470,25 @@
       new BrowserPluginMsg_UpdateRect(instance_id(), relay_params));
 }
 
-void BrowserPluginGuest::OnRespondPermissionGeolocation(
-    int request_id, bool should_allow) {
-  if (should_allow && embedder_web_contents_) {
-    // If renderer side embedder decides to allow gelocation, we need to check
-    // if the app/embedder itself has geolocation access.
-    BrowserContext* browser_context =
-        embedder_web_contents_->GetBrowserContext();
-    if (browser_context) {
-      GeolocationPermissionContext* geolocation_context =
-          browser_context->GetGeolocationPermissionContext();
-      if (geolocation_context) {
-        base::Callback<void(bool)> geolocation_callback = base::Bind(
-            &BrowserPluginGuest::SetGeolocationPermission,
-            weak_ptr_factory_.GetWeakPtr(),
-            request_id);
-        geolocation_context->RequestGeolocationPermission(
-            embedder_web_contents_->GetRenderProcessHost()->GetID(),
-            embedder_web_contents_->GetRoutingID(),
-            // The geolocation permission request here is not initiated through
-            // WebGeolocationPermissionRequest. We are only interested in the
-            // fact whether the embedder/app has geolocation permission.
-            // Therefore we use an invalid |bridge_id|.
-            -1 /* bridge_id */,
-            embedder_web_contents_->GetURL(),
-            geolocation_callback);
-        return;
-      }
-    }
-  }
-  SetGeolocationPermission(request_id, false);
-}
-
-void BrowserPluginGuest::OnRespondPermissionMedia(
-    int request_id, bool should_allow) {
-  MediaStreamRequestsMap::iterator media_request_iter =
-      media_requests_map_.find(request_id);
-  if (media_request_iter == media_requests_map_.end()) {
-    LOG(INFO) << "Not a valid request ID.";
+void BrowserPluginGuest::DidRetrieveDownloadURLFromRequestId(
+    const std::string& request_method,
+    int permission_request_id,
+    const std::string& url) {
+  if (url.empty()) {
+    OnRespondPermission(instance_id(), BrowserPluginPermissionTypeDownload,
+                        permission_request_id, false);
     return;
   }
-  const MediaStreamRequest& request = media_request_iter->second.first;
-  const MediaResponseCallback& callback =
-      media_request_iter->second.second;
 
-  if (should_allow && embedder_web_contents_) {
-    // Re-route the request to the embedder's WebContents; the guest gets the
-    // permission this way.
-    embedder_web_contents_->RequestMediaAccessPermission(request, callback);
-  } else {
-    // Deny the request.
-    callback.Run(MediaStreamDevices());
-  }
-  media_requests_map_.erase(media_request_iter);
-}
+  base::DictionaryValue request_info;
+  request_info.Set(browser_plugin::kRequestMethod,
+                   base::Value::CreateStringValue(request_method));
+  request_info.Set(browser_plugin::kURL, base::Value::CreateStringValue(url));
 
-void BrowserPluginGuest::OnRespondPermissionNewWindow(
-    int request_id, bool should_allow) {
-  NewWindowRequestMap::iterator new_window_request_iter =
-      new_window_request_map_.find(request_id);
-  if (new_window_request_iter == new_window_request_map_.end()) {
-    LOG(INFO) << "Not a valid request ID.";
-    return;
-  }
-  int instance_id = new_window_request_iter->second;
-  int embedder_render_process_id =
-      embedder_web_contents_->GetRenderProcessHost()->GetID();
-  BrowserPluginGuest* guest =
-      GetWebContents()->GetBrowserPluginGuestManager()->
-          GetGuestByInstanceID(instance_id, embedder_render_process_id);
-  if (!guest) {
-    LOG(INFO) << "Guest not found. Instance ID: " << instance_id;
-    return;
-  }
-  if (!should_allow)
-    guest->Destroy();
-  // If we do not destroy the guest then we allow the new window.
-  new_window_request_map_.erase(new_window_request_iter);
+  SendMessageToEmbedder(
+      new BrowserPluginMsg_RequestPermission(instance_id(),
+          BrowserPluginPermissionTypeDownload, permission_request_id,
+          request_info));
 }
 
 }  // namespace content
diff --git a/content/browser/browser_plugin/browser_plugin_guest.h b/content/browser/browser_plugin/browser_plugin_guest.h
index 1b480e6..8b406da 100644
--- a/content/browser/browser_plugin/browser_plugin_guest.h
+++ b/content/browser/browser_plugin/browser_plugin_guest.h
@@ -42,7 +42,7 @@
 #include "ui/surface/transport_dib.h"
 
 struct BrowserPluginHostMsg_AutoSize_Params;
-struct BrowserPluginHostMsg_CreateGuest_Params;
+struct BrowserPluginHostMsg_Attach_Params;
 struct BrowserPluginHostMsg_ResizeGuest_Params;
 struct ViewHostMsg_CreateWindow_Params;
 #if defined(OS_MACOSX)
@@ -52,6 +52,10 @@
 class WebCursor;
 struct WebDropData;
 
+namespace cc {
+class CompositorFrameAck;
+}
+
 namespace WebKit {
 class WebInputEvent;
 }
@@ -75,9 +79,11 @@
 // A BrowserPluginGuest can also create a new unattached guest via
 // CreateNewWindow. The newly created guest will live in the same partition,
 // which means it can share storage and can script this guest.
-class CONTENT_EXPORT BrowserPluginGuest : public NotificationObserver,
-                                          public WebContentsDelegate,
-                                          public WebContentsObserver {
+class CONTENT_EXPORT BrowserPluginGuest
+    : public NotificationObserver,
+      public WebContentsDelegate,
+      public WebContentsObserver,
+      public base::SupportsWeakPtr<BrowserPluginGuest> {
  public:
   typedef base::Callback<void(bool)> GeolocationCallback;
   virtual ~BrowserPluginGuest();
@@ -86,6 +92,12 @@
       int instance_id,
       WebContentsImpl* web_contents);
 
+  static BrowserPluginGuest* CreateWithOpener(
+      int instance_id,
+      WebContentsImpl* web_contents,
+      BrowserPluginGuest* opener,
+      bool has_render_view);
+
   // Destroys the guest WebContents and all its associated state, including
   // this BrowserPluginGuest, and its new unattached windows.
   void Destroy();
@@ -103,7 +115,7 @@
   bool OnMessageReceivedFromEmbedder(const IPC::Message& message);
 
   void Initialize(WebContentsImpl* embedder_web_contents,
-                  const BrowserPluginHostMsg_CreateGuest_Params& params);
+                  const BrowserPluginHostMsg_Attach_Params& params);
 
   void set_guest_hang_timeout_for_testing(const base::TimeDelta& timeout) {
     guest_hang_timeout_ = timeout;
@@ -159,6 +171,11 @@
 
   // WebContentsDelegate implementation.
 
+  virtual bool AddMessageToConsole(WebContents* source,
+                                   int32 level,
+                                   const string16& message,
+                                   int32 line_no,
+                                   const string16& source_id) OVERRIDE;
   // If a new window is created with target="_blank" and rel="noreferrer", then
   // this method is called, indicating that the new WebContents is ready to be
   // attached.
@@ -168,10 +185,17 @@
                               const gfx::Rect& initial_pos,
                               bool user_gesture,
                               bool* was_blocked) OVERRIDE;
-  virtual bool CanDownload(RenderViewHost* render_view_host,
+  virtual void CanDownload(RenderViewHost* render_view_host,
                            int request_id,
-                           const std::string& request_method) OVERRIDE;
+                           const std::string& request_method,
+                           const base::Callback<void(bool)>& callback) OVERRIDE;
+  virtual void CloseContents(WebContents* source) OVERRIDE;
   virtual bool HandleContextMenu(const ContextMenuParams& params) OVERRIDE;
+  virtual void HandleKeyboardEvent(
+      WebContents* source,
+      const NativeWebKeyboardEvent& event) OVERRIDE;
+  virtual WebContents* OpenURLFromTab(WebContents* source,
+                                      const OpenURLParams& params) OVERRIDE;
   virtual void WebContentsCreated(WebContents* source_contents,
                                   int64 source_frame_id,
                                   const string16& frame_name,
@@ -190,9 +214,6 @@
   // Exposes the protected web_contents() from WebContentsObserver.
   WebContentsImpl* GetWebContents();
 
-  // Kill the guest process.
-  void Terminate();
-
   // Overridden in tests.
   virtual void SetDamageBuffer(
       const BrowserPluginHostMsg_ResizeGuest_Params& params);
@@ -213,16 +234,14 @@
   // to an embedder implies that this guest's lifetime is no longer managed
   // by its opener, and it can begin loading resources.
   void Attach(WebContentsImpl* embedder_web_contents,
-              BrowserPluginHostMsg_CreateGuest_Params params);
+              BrowserPluginHostMsg_Attach_Params params);
 
-  // Requests geolocation permission through embedder js api.
+  // Requests geolocation permission through Embedder JavaScript API.
   void AskEmbedderForGeolocationPermission(int bridge_id,
                                            const GURL& requesting_frame,
                                            const GeolocationCallback& callback);
   // Cancels pending geolocation request.
   void CancelGeolocationRequest(int bridge_id);
-  // Embedder sets permission to allow or deny geolocation request.
-  void SetGeolocationPermission(int request_id, bool allowed);
 
   // Allow the embedder to call this for unhandled messages when
   // BrowserPluginGuest is already destroyed.
@@ -235,17 +254,30 @@
   // |message|.
   static bool ShouldForwardToBrowserPluginGuest(const IPC::Message& message);
 
- private:
-  typedef std::pair<MediaStreamRequest, MediaResponseCallback>
-      MediaStreamRequestAndCallbackPair;
-  typedef std::map<int, MediaStreamRequestAndCallbackPair>
-      MediaStreamRequestsMap;
+  void DragSourceEndedAt(int client_x, int client_y, int screen_x,
+      int screen_y, WebKit::WebDragOperation operation);
 
+  void DragSourceMovedTo(int client_x, int client_y,
+                         int screen_x, int screen_y);
+
+  // Called when the drag started by this guest ends at an OS-level.
+  void EndSystemDrag();
+
+ private:
   class EmbedderRenderViewHostObserver;
   friend class TestBrowserPluginGuest;
 
+  class DownloadRequest;
+  class GeolocationRequest;
+  // MediaRequest because of naming conflicts with MediaStreamRequest.
+  class MediaRequest;
+  class NewWindowRequest;
+  class PermissionRequest;
+
   BrowserPluginGuest(int instance_id,
-                     WebContentsImpl* web_contents);
+                     WebContentsImpl* web_contents,
+                     BrowserPluginGuest* opener,
+                     bool has_render_view);
 
   // Destroy unattached new windows that have been opened by this
   // BrowserPluginGuest.
@@ -274,6 +306,11 @@
 
   // Message handlers for messages from embedder.
 
+  void OnCompositorFrameACK(int instance_id,
+                            int route_id,
+                            int renderer_host_id,
+                            const cc::CompositorFrameAck& ack);
+
   // Allows or denies a permission request access, after the embedder has had a
   // chance to decide.
   void OnRespondPermission(int instance_id,
@@ -290,6 +327,9 @@
                           const WebDropData& drop_data,
                           WebKit::WebDragOperationsMask drag_mask,
                           const gfx::Point& location);
+  // Instructs the guest to execute an edit command decoded in the embedder.
+  void OnExecuteEditCommand(int instance_id,
+                            const std::string& command);
   // If possible, navigate the guest to |relative_index| entries away from the
   // current navigation entry.
   virtual void OnGo(int instance_id, int relative_index);
@@ -355,6 +395,7 @@
 
   // Message handlers for messages from guest.
 
+  void OnDragStopped();
   void OnHandleInputEventAck(
       WebKit::WebInputEvent::Type event_type,
       InputEventAckState ack_result);
@@ -365,23 +406,23 @@
 #if defined(OS_MACOSX)
   void OnShowPopup(const ViewHostMsg_ShowPopup_Params& params);
 #endif
-  void OnShowView(int route_id,
-                  WindowOpenDisposition disposition,
-                  const gfx::Rect& initial_bounds,
-                  bool user_gesture);
   void OnShowWidget(int route_id, const gfx::Rect& initial_pos);
   // Overriden in tests.
   virtual void OnTakeFocus(bool reverse);
-  void OnUpdateDragCursor(WebKit::WebDragOperation operation);
   void OnUpdateFrameName(int frame_id,
                          bool is_top_level,
                          const std::string& name);
   void OnUpdateRect(const ViewHostMsg_UpdateRect_Params& params);
 
-  // Helpers for |OnRespondPermission|.
-  void OnRespondPermissionGeolocation(int request_id, bool should_allow);
-  void OnRespondPermissionMedia(int request_id, bool should_allow);
-  void OnRespondPermissionNewWindow(int request_id, bool should_allow);
+  // Requests download permission through embedder JavaScript API after
+  // retrieving url information from IO thread.
+  void DidRetrieveDownloadURLFromRequestId(const std::string& request_method,
+                                           int permission_request_id,
+                                           const std::string& url);
+
+  // Embedder sets permission to allow or deny geolocation request.
+  void SetGeolocationPermission(
+      GeolocationCallback callback, int bridge_id, bool allowed);
 
   // Weak pointer used to ask GeolocationPermissionContext about geolocation
   // permission.
@@ -393,8 +434,9 @@
   NotificationRegistrar notification_registrar_;
   scoped_ptr<EmbedderRenderViewHostObserver> embedder_rvh_observer_;
   WebContentsImpl* embedder_web_contents_;
-  typedef std::map<int, GeolocationCallback> GeolocationRequestsMap;
-  GeolocationRequestsMap geolocation_request_callback_map_;
+
+  std::map<int, int> bridge_id_to_request_id_map_;
+
   // An identifier that uniquely identifies a browser plugin guest within an
   // embedder.
   int instance_id_;
@@ -404,6 +446,7 @@
   size_t damage_buffer_size_;
   gfx::Size damage_view_size_;
   float damage_buffer_scale_factor_;
+  float guest_device_scale_factor_;
   gfx::Rect guest_window_rect_;
   gfx::Rect guest_screen_rect_;
   base::TimeDelta guest_hang_timeout_;
@@ -417,20 +460,32 @@
   gfx::Size max_auto_size_;
   gfx::Size min_auto_size_;
 
-  typedef std::map<BrowserPluginGuest*, std::string> PendingWindowMap;
+  // Tracks the target URL of the new window and whether or not it has changed
+  // since the WebContents has been created and before the new window has been
+  // attached to a BrowserPlugin. Once the first navigation commits, we no
+  // longer track this URL.
+  struct TargetURL {
+    bool changed;
+    GURL url;
+    explicit TargetURL(const GURL& url) :
+        changed(false),
+        url(url) {}
+  };
+  typedef std::map<BrowserPluginGuest*, TargetURL> PendingWindowMap;
   PendingWindowMap pending_new_windows_;
-  BrowserPluginGuest* opener_;
+  base::WeakPtr<BrowserPluginGuest> opener_;
   // A counter to generate a unique request id for a permission request.
   // We only need the ids to be unique for a given BrowserPluginGuest.
   int next_permission_request_id_;
-  // A map to store WebContents's media request object and callback.
-  // We need to store these because we need a roundtrip to the embedder to know
-  // if we allow or disallow the request. The key of the map is unique only for
-  // a given BrowserPluginGuest.
-  MediaStreamRequestsMap media_requests_map_;
-  // A map from request ID to instance ID for use by the New Window API.
-  typedef std::map<int, int> NewWindowRequestMap;
-  NewWindowRequestMap new_window_request_map_;
+
+  // A map to store relevant info for a request keyed by the request's id.
+  typedef std::map<int, PermissionRequest*> RequestMap;
+  RequestMap permission_request_map_;
+
+  // Indicates that this BrowserPluginGuest has associated renderer-side state.
+  // This is used to determine whether or not to create a new RenderView when
+  // this guest is attached.
+  bool has_render_view_;
 
   DISALLOW_COPY_AND_ASSIGN(BrowserPluginGuest);
 };
diff --git a/content/browser/browser_plugin/browser_plugin_guest_helper.cc b/content/browser/browser_plugin/browser_plugin_guest_helper.cc
index e255dc8..ee18b6e 100644
--- a/content/browser/browser_plugin/browser_plugin_guest_helper.cc
+++ b/content/browser/browser_plugin/browser_plugin_guest_helper.cc
@@ -32,7 +32,8 @@
 bool BrowserPluginGuestHelper::ShouldForwardToBrowserPluginGuest(
     const IPC::Message& message) {
   switch (message.type()) {
-    case DragHostMsg_UpdateDragCursor::ID:
+    case DragHostMsg_StartDragging::ID:
+    case DragHostMsg_TargetDrop_ACK::ID:
     case ViewHostMsg_HasTouchEventHandlers::ID:
     case ViewHostMsg_SetCursor::ID:
  #if defined(OS_MACOSX)
diff --git a/content/browser/browser_plugin/browser_plugin_guest_manager.cc b/content/browser/browser_plugin/browser_plugin_guest_manager.cc
index 6a41b50..081f332 100644
--- a/content/browser/browser_plugin/browser_plugin_guest_manager.cc
+++ b/content/browser/browser_plugin/browser_plugin_guest_manager.cc
@@ -40,14 +40,8 @@
 BrowserPluginGuest* BrowserPluginGuestManager::CreateGuest(
     SiteInstance* embedder_site_instance,
     int instance_id,
-    const BrowserPluginHostMsg_CreateGuest_Params& params) {
+    const BrowserPluginHostMsg_Attach_Params& params) {
   SiteInstance* guest_site_instance = NULL;
-  int embedder_render_process_id =
-      embedder_site_instance->GetProcess()->GetID();
-  BrowserPluginGuest* guest =
-      GetGuestByInstanceID(instance_id, embedder_render_process_id);
-  CHECK(!guest);
-
   // Validate that the partition id coming from the renderer is valid UTF-8,
   // since we depend on this in other parts of the code, such as FilePath
   // creation. If the validation fails, treat it as a bad message and kill the
@@ -110,22 +104,15 @@
 BrowserPluginGuest* BrowserPluginGuestManager::GetGuestByInstanceID(
     int instance_id,
     int embedder_render_process_id) const {
+  if (!CanEmbedderAccessInstanceIDMaybeKill(embedder_render_process_id,
+                                            instance_id)) {
+    return NULL;
+  }
   GuestInstanceMap::const_iterator it =
       guest_web_contents_by_instance_id_.find(instance_id);
   if (it == guest_web_contents_by_instance_id_.end())
     return NULL;
-
-  BrowserPluginGuest* guest =
-      static_cast<WebContentsImpl*>(it->second)->GetBrowserPluginGuest();
-  if (!CanEmbedderAccessGuest(embedder_render_process_id, guest)) {
-    // The embedder process is trying to access a guest it does not own.
-    content::RecordAction(UserMetricsAction("BadMessageTerminate_BPGM"));
-    base::KillProcess(
-        RenderProcessHost::FromID(embedder_render_process_id)->GetHandle(),
-        content::RESULT_CODE_KILLED_BAD_MESSAGE, false);
-    return NULL;
-  }
-  return guest;
+  return static_cast<WebContentsImpl*>(it->second)->GetBrowserPluginGuest();
 }
 
 void BrowserPluginGuestManager::AddGuest(int instance_id,
@@ -141,6 +128,20 @@
   guest_web_contents_by_instance_id_.erase(instance_id);
 }
 
+bool BrowserPluginGuestManager::CanEmbedderAccessInstanceIDMaybeKill(
+    int embedder_render_process_id,
+    int instance_id) const {
+  if (!CanEmbedderAccessInstanceID(embedder_render_process_id, instance_id)) {
+    // The embedder process is trying to access a guest it does not own.
+    content::RecordAction(UserMetricsAction("BadMessageTerminate_BPGM"));
+    base::KillProcess(
+        RenderProcessHost::FromID(embedder_render_process_id)->GetHandle(),
+        content::RESULT_CODE_KILLED_BAD_MESSAGE, false);
+    return false;
+  }
+  return true;
+}
+
 void BrowserPluginGuestManager::OnMessageReceived(const IPC::Message& message,
                                                   int render_process_id) {
   if (BrowserPluginGuest::ShouldForwardToBrowserPluginGuest(message)) {
@@ -160,11 +161,11 @@
   IPC_END_MESSAGE_MAP()
 }
 
-//static
+// static
 bool BrowserPluginGuestManager::CanEmbedderAccessGuest(
     int embedder_render_process_id,
     BrowserPluginGuest* guest) {
-  // An embedder can access |guest| if the guest has not been attached and its
+  // The embedder can access the guest if it has not been attached and its
   // opener's embedder lives in the same process as the given embedder.
   if (!guest->attached()) {
     if (!guest->opener())
@@ -179,6 +180,31 @@
       guest->embedder_web_contents()->GetRenderProcessHost()->GetID();
 }
 
+bool BrowserPluginGuestManager::CanEmbedderAccessInstanceID(
+    int embedder_render_process_id,
+    int instance_id) const {
+  // The embedder is trying to access a guest with a negative or zero
+  // instance ID.
+  if (instance_id <= browser_plugin::kInstanceIDNone)
+    return false;
+
+  // The embedder is trying to access an instance ID that has not yet been
+  // allocated by BrowserPluginGuestManager. This could cause instance ID
+  // collisions in the future, and potentially give one embedder access to a
+  // guest it does not own.
+  if (instance_id > next_instance_id_)
+    return false;
+
+  GuestInstanceMap::const_iterator it =
+      guest_web_contents_by_instance_id_.find(instance_id);
+  if (it == guest_web_contents_by_instance_id_.end())
+    return true;
+  BrowserPluginGuest* guest =
+      static_cast<WebContentsImpl*>(it->second)->GetBrowserPluginGuest();
+
+  return CanEmbedderAccessGuest(embedder_render_process_id, guest);
+}
+
 SiteInstance* BrowserPluginGuestManager::GetGuestSiteInstance(
     const GURL& guest_site) {
   for (GuestInstanceMap::const_iterator it =
diff --git a/content/browser/browser_plugin/browser_plugin_guest_manager.h b/content/browser/browser_plugin/browser_plugin_guest_manager.h
index 4f5bb9b..4e1ba28 100644
--- a/content/browser/browser_plugin/browser_plugin_guest_manager.h
+++ b/content/browser/browser_plugin/browser_plugin_guest_manager.h
@@ -14,7 +14,7 @@
 #include "content/common/content_export.h"
 #include "ipc/ipc_message.h"
 
-struct BrowserPluginHostMsg_CreateGuest_Params;
+struct BrowserPluginHostMsg_Attach_Params;
 struct BrowserPluginHostMsg_ResizeGuest_Params;
 class GURL;
 
@@ -58,19 +58,27 @@
   BrowserPluginGuest* CreateGuest(
       SiteInstance* embedder_site_instance,
       int instance_id,
-      const BrowserPluginHostMsg_CreateGuest_Params& params);
+      const BrowserPluginHostMsg_Attach_Params& params);
 
-  // Returns a BrowserPluginGuest given an instance ID. Returns NULL if the
-  // guest wasn't found.  If the guest doesn't belong to the given embedder,
-  // then NULL is returned and the embedder is killed.
+  // Returns a BrowserPluginGuest given an |instance_id|. Returns NULL if the
+  // guest wasn't found.  If the embedder is not permitted to access the given
+  // |instance_id|, the embedder is killed, and NULL is returned.
   BrowserPluginGuest* GetGuestByInstanceID(
       int instance_id,
       int embedder_render_process_id) const;
 
   // Adds a new |guest_web_contents| to the embedder (overridable in test).
   virtual void AddGuest(int instance_id, WebContentsImpl* guest_web_contents);
+
+  // Removes the guest with the given |instance_id| from this
+  // BrowserPluginGuestManager.
   void RemoveGuest(int instance_id);
 
+  // Returns whether the specified embedder is permitted to access the given
+  // |instance_id|, and kills the embedder if not.
+  bool CanEmbedderAccessInstanceIDMaybeKill(int embedder_render_process_id,
+                                            int instance_id) const;
+
   void OnMessageReceived(const IPC::Message& message, int render_process_id);
 
  private:
@@ -78,10 +86,20 @@
 
   BrowserPluginGuestManager();
 
-  // Returns whether the given embedder process is allowed to access |guest|.
+  // Returns whether the given embedder process is allowed to access the
+  // provided |guest|.
   static bool CanEmbedderAccessGuest(int embedder_render_process_id,
                                      BrowserPluginGuest* guest);
 
+  // Returns whether the given embedder process is allowed to use the provided
+  // |instance_id| or access the guest associated with the |instance_id|. If the
+  // embedder can, the method returns true. If the guest does not exist but the
+  // embedder can use that |instance_id|, then it returns true. If the embedder
+  // is not permitted to use that instance ID or access the associated guest,
+  // then it returns false.
+  bool CanEmbedderAccessInstanceID(int embedder_render_process_id,
+                                   int instance_id) const;
+
   // Returns an existing SiteInstance if the current profile has a guest of the
   // given |guest_site|.
   SiteInstance* GetGuestSiteInstance(const GURL& guest_site);
diff --git a/content/browser/browser_plugin/browser_plugin_host_browsertest.cc b/content/browser/browser_plugin/browser_plugin_host_browsertest.cc
index abbf63b..26b783c 100644
--- a/content/browser/browser_plugin/browser_plugin_host_browsertest.cc
+++ b/content/browser/browser_plugin/browser_plugin_host_browsertest.cc
@@ -28,7 +28,7 @@
 #include "content/test/content_browser_test.h"
 #include "content/test/content_browser_test_utils.h"
 #include "net/base/net_util.h"
-#include "net/test/test_server.h"
+#include "net/test/spawned_test_server.h"
 #include "third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h"
 #include "webkit/glue/webdropdata.h"
 
@@ -375,13 +375,21 @@
 // guest.
 //
 // Disabled on Windows and Linux since it is flaky. crbug.com/164812
-IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, GuestUnresponsive) {
+// THIS TEST IS ALWAYS FLAKY. DO NOT ENABLE AGAIN WITHOUT REWRITING.
+#if defined(OS_WIN) || defined(OS_LINUX)
+#define MAYBE_GuestUnresponsive DISABLED_GuestUnresponsive
+#else
+#define MAYBE_GuestUnresponsive GuestUnresponsive
+#endif
+IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest,
+                       MAYBE_GuestUnresponsive) {
   // Override the hang timeout for guest to be very small.
   content::BrowserPluginGuest::set_factory_for_testing(
       TestShortHangTimeoutGuestFactory::GetInstance());
   const char kEmbedderURL[] =
       "files/browser_plugin_embedder_guest_unresponsive.html";
-  StartBrowserPluginTest(kEmbedderURL, kHTMLForGuestBusyLoop, true, "");
+  StartBrowserPluginTest(
+      kEmbedderURL, kHTMLForGuestBusyLoop, true, std::string());
   // Wait until the busy loop starts.
   {
     const string16 expected_title = ASCIIToUTF16("start");
@@ -446,7 +454,7 @@
 IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, AdvanceFocus) {
   const char kEmbedderURL[] = "files/browser_plugin_focus.html";
   const char* kGuestURL = "files/browser_plugin_focus_child.html";
-  StartBrowserPluginTest(kEmbedderURL, kGuestURL, false, "");
+  StartBrowserPluginTest(kEmbedderURL, kGuestURL, false, std::string());
 
   SimulateMouseClick(test_embedder()->web_contents(), 0,
       WebKit::WebMouseEvent::ButtonLeft);
@@ -469,15 +477,15 @@
 // a RenderViewHost swap in the web_contents. We verify that the embedder in the
 // web_contents gets cleared properly.
 IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, EmbedderChangedAfterSwap) {
-  net::TestServer https_server(
-      net::TestServer::TYPE_HTTPS,
-      net::TestServer::kLocalhost,
+  net::SpawnedTestServer https_server(
+      net::SpawnedTestServer::TYPE_HTTPS,
+      net::SpawnedTestServer::kLocalhost,
       base::FilePath(FILE_PATH_LITERAL("content/test/data")));
   ASSERT_TRUE(https_server.Start());
 
   // 1. Load an embedder page with one guest in it.
   const char kEmbedderURL[] = "files/browser_plugin_embedder.html";
-  StartBrowserPluginTest(kEmbedderURL, kHTMLForGuest, true, "");
+  StartBrowserPluginTest(kEmbedderURL, kHTMLForGuest, true, std::string());
 
   // 2. Navigate to a URL in https, so we trigger a RenderViewHost swap.
   GURL test_https_url(https_server.GetURL(
@@ -503,7 +511,7 @@
 // web_contents.
 IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, EmbedderSameAfterNav) {
   const char kEmbedderURL[] = "files/browser_plugin_embedder.html";
-  StartBrowserPluginTest(kEmbedderURL, kHTMLForGuest, true, "");
+  StartBrowserPluginTest(kEmbedderURL, kHTMLForGuest, true, std::string());
   WebContentsImpl* embedder_web_contents = test_embedder()->web_contents();
 
   // Navigate to another page in same host and port, so RenderViewHost swap
@@ -528,7 +536,7 @@
 // This test verifies that hiding the embedder also hides the guest.
 IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, BrowserPluginVisibilityChanged) {
   const char kEmbedderURL[] = "files/browser_plugin_embedder.html";
-  StartBrowserPluginTest(kEmbedderURL, kHTMLForGuest, true, "");
+  StartBrowserPluginTest(kEmbedderURL, kHTMLForGuest, true, std::string());
 
   // Hide the Browser Plugin.
   RenderViewHostImpl* rvh = static_cast<RenderViewHostImpl*>(
@@ -542,7 +550,7 @@
 
 IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, EmbedderVisibilityChanged) {
   const char kEmbedderURL[] = "files/browser_plugin_embedder.html";
-  StartBrowserPluginTest(kEmbedderURL, kHTMLForGuest, true, "");
+  StartBrowserPluginTest(kEmbedderURL, kHTMLForGuest, true, std::string());
 
   // Hide the embedder.
   test_embedder()->web_contents()->WasHidden();
@@ -554,7 +562,7 @@
 // This test verifies that calling the reload method reloads the guest.
 IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, ReloadGuest) {
   const char kEmbedderURL[] = "files/browser_plugin_embedder.html";
-  StartBrowserPluginTest(kEmbedderURL, kHTMLForGuest, true, "");
+  StartBrowserPluginTest(kEmbedderURL, kHTMLForGuest, true, std::string());
 
   test_guest()->ResetUpdateRectCount();
 
@@ -568,7 +576,7 @@
 // to the guest's WebContents.
 IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, StopGuest) {
   const char kEmbedderURL[] = "files/browser_plugin_embedder.html";
-  StartBrowserPluginTest(kEmbedderURL, kHTMLForGuest, true, "");
+  StartBrowserPluginTest(kEmbedderURL, kHTMLForGuest, true, std::string());
 
   RenderViewHostImpl* rvh = static_cast<RenderViewHostImpl*>(
       test_embedder()->web_contents()->GetRenderViewHost());
@@ -580,7 +588,8 @@
 // plugin correctly updates the touch-event handling state in the embedder.
 IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, AcceptTouchEvents) {
   const char kEmbedderURL[] = "files/browser_plugin_embedder.html";
-  StartBrowserPluginTest(kEmbedderURL, kHTMLForGuestTouchHandler, true, "");
+  StartBrowserPluginTest(
+      kEmbedderURL, kHTMLForGuestTouchHandler, true, std::string());
 
   RenderViewHostImpl* rvh = static_cast<RenderViewHostImpl*>(
       test_embedder()->web_contents()->GetRenderViewHost());
@@ -608,7 +617,7 @@
 IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, Renavigate) {
   const char kEmbedderURL[] = "files/browser_plugin_embedder.html";
   StartBrowserPluginTest(
-      kEmbedderURL, GetHTMLForGuestWithTitle("P1"), true, "");
+      kEmbedderURL, GetHTMLForGuestWithTitle("P1"), true, std::string());
   RenderViewHostImpl* rvh = static_cast<RenderViewHostImpl*>(
       test_embedder()->web_contents()->GetRenderViewHost());
 
@@ -703,7 +712,7 @@
 // and that the guest is reset.
 IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, ReloadEmbedder) {
   const char kEmbedderURL[] = "files/browser_plugin_embedder.html";
-  StartBrowserPluginTest(kEmbedderURL, kHTMLForGuest, true, "");
+  StartBrowserPluginTest(kEmbedderURL, kHTMLForGuest, true, std::string());
   RenderViewHostImpl* rvh = static_cast<RenderViewHostImpl*>(
       test_embedder()->web_contents()->GetRenderViewHost());
 
@@ -754,7 +763,7 @@
 
 IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, TerminateGuest) {
   const char kEmbedderURL[] = "files/browser_plugin_embedder.html";
-  StartBrowserPluginTest(kEmbedderURL, kHTMLForGuest, true, "");
+  StartBrowserPluginTest(kEmbedderURL, kHTMLForGuest, true, std::string());
 
   RenderViewHostImpl* rvh = static_cast<RenderViewHostImpl*>(
       test_embedder()->web_contents()->GetRenderViewHost());
@@ -769,7 +778,7 @@
 IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, BackAfterTerminateGuest) {
   const char* kEmbedderURL = "files/browser_plugin_embedder.html";
   StartBrowserPluginTest(
-      kEmbedderURL, GetHTMLForGuestWithTitle("P1"), true, "");
+      kEmbedderURL, GetHTMLForGuestWithTitle("P1"), true, std::string());
   RenderViewHostImpl* rvh = static_cast<RenderViewHostImpl*>(
       test_embedder()->web_contents()->GetRenderViewHost());
 
@@ -811,7 +820,7 @@
 
 IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, LoadStart) {
   const char kEmbedderURL[] = "files/browser_plugin_embedder.html";
-  StartBrowserPluginTest(kEmbedderURL, "about:blank", true, "");
+  StartBrowserPluginTest(kEmbedderURL, "about:blank", true, std::string());
 
   const string16 expected_title = ASCIIToUTF16(kHTMLForGuest);
   content::TitleWatcher title_watcher(test_embedder()->web_contents(),
@@ -828,7 +837,7 @@
 
 IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, LoadAbort) {
   const char kEmbedderURL[] = "files/browser_plugin_embedder.html";
-  StartBrowserPluginTest(kEmbedderURL, "about:blank", true, "");
+  StartBrowserPluginTest(kEmbedderURL, "about:blank", true, std::string());
 
   {
     // Navigate the guest to "close-socket".
@@ -875,7 +884,7 @@
 
 IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, LoadRedirect) {
   const char kEmbedderURL[] = "files/browser_plugin_embedder.html";
-  StartBrowserPluginTest(kEmbedderURL, "about:blank", true, "");
+  StartBrowserPluginTest(kEmbedderURL, "about:blank", true, std::string());
 
   const string16 expected_title = ASCIIToUTF16("redirected");
   content::TitleWatcher title_watcher(test_embedder()->web_contents(),
@@ -915,7 +924,8 @@
 // correctly.
 IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, MAYBE_AcceptDragEvents) {
   const char kEmbedderURL[] = "files/browser_plugin_dragging.html";
-  StartBrowserPluginTest(kEmbedderURL, kHTMLForGuestAcceptDrag, true, "");
+  StartBrowserPluginTest(
+      kEmbedderURL, kHTMLForGuestAcceptDrag, true, std::string());
 
   RenderViewHostImpl* rvh = static_cast<RenderViewHostImpl*>(
       test_embedder()->web_contents()->GetRenderViewHost());
@@ -971,7 +981,7 @@
   const char* kTesting = "testing123";
   const char* kEmbedderURL = "files/browser_plugin_embedder.html";
   const char* kGuestURL = "files/browser_plugin_post_message_guest.html";
-  StartBrowserPluginTest(kEmbedderURL, kGuestURL, false, "");
+  StartBrowserPluginTest(kEmbedderURL, kGuestURL, false, std::string());
   RenderViewHostImpl* rvh = static_cast<RenderViewHostImpl*>(
       test_embedder()->web_contents()->GetRenderViewHost());
   {
@@ -999,7 +1009,7 @@
   const char* kTesting = "testing123";
   const char* kEmbedderURL = "files/browser_plugin_embedder.html";
   const char* kGuestURL = "files/browser_plugin_post_message_guest.html";
-  StartBrowserPluginTest(kEmbedderURL, kGuestURL, false, "");
+  StartBrowserPluginTest(kEmbedderURL, kGuestURL, false, std::string());
   RenderViewHostImpl* rvh = static_cast<RenderViewHostImpl*>(
       test_embedder()->web_contents()->GetRenderViewHost());
   {
@@ -1045,7 +1055,7 @@
 
 IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, LoadStop) {
   const char* kEmbedderURL = "files/browser_plugin_embedder.html";
-  StartBrowserPluginTest(kEmbedderURL, "about:blank", true, "");
+  StartBrowserPluginTest(kEmbedderURL, "about:blank", true, std::string());
 
   const string16 expected_title = ASCIIToUTF16("loadStop");
   content::TitleWatcher title_watcher(
@@ -1062,7 +1072,7 @@
 
 IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, LoadCommit) {
   const char* kEmbedderURL = "files/browser_plugin_embedder.html";
-  StartBrowserPluginTest(kEmbedderURL, "about:blank", true, "");
+  StartBrowserPluginTest(kEmbedderURL, "about:blank", true, std::string());
 
   const string16 expected_title = ASCIIToUTF16(
       base::StringPrintf("loadCommit:%s", kHTMLForGuest));
@@ -1098,7 +1108,7 @@
 // the new guest will inherit the visibility state of the old guest.
 IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, VisibilityPreservation) {
   const char* kEmbedderURL = "files/browser_plugin_embedder.html";
-  StartBrowserPluginTest(kEmbedderURL, kHTMLForGuest, true, "");
+  StartBrowserPluginTest(kEmbedderURL, kHTMLForGuest, true, std::string());
   RenderViewHostImpl* rvh = static_cast<RenderViewHostImpl*>(
       test_embedder()->web_contents()->GetRenderViewHost());
   // Hide the BrowserPlugin.
@@ -1138,7 +1148,7 @@
 // crbug.com/170249
 IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, DISABLED_FocusPreservation) {
   const char* kEmbedderURL = "files/browser_plugin_embedder.html";
-  StartBrowserPluginTest(kEmbedderURL, kHTMLForGuest, true, "");
+  StartBrowserPluginTest(kEmbedderURL, kHTMLForGuest, true, std::string());
   RenderViewHostImpl* rvh = static_cast<RenderViewHostImpl*>(
       test_embedder()->web_contents()->GetRenderViewHost());
   RenderViewHostImpl* guest_rvh = static_cast<RenderViewHostImpl*>(
@@ -1177,7 +1187,7 @@
 
 IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, FocusTracksEmbedder) {
   const char* kEmbedderURL = "files/browser_plugin_embedder.html";
-  StartBrowserPluginTest(kEmbedderURL, kHTMLForGuest, true, "");
+  StartBrowserPluginTest(kEmbedderURL, kHTMLForGuest, true, std::string());
   RenderViewHostImpl* rvh = static_cast<RenderViewHostImpl*>(
       test_embedder()->web_contents()->GetRenderViewHost());
   RenderViewHostImpl* guest_rvh = static_cast<RenderViewHostImpl*>(
@@ -1222,7 +1232,7 @@
 IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, AutoSizeAfterNavigation) {
   const char* kEmbedderURL = "files/browser_plugin_embedder.html";
   StartBrowserPluginTest(
-      kEmbedderURL, kHTMLForGuestWithSize, true, "");
+      kEmbedderURL, kHTMLForGuestWithSize, true, std::string());
   RenderViewHostImpl* rvh = static_cast<RenderViewHostImpl*>(
       test_embedder()->web_contents()->GetRenderViewHost());
 
@@ -1273,10 +1283,17 @@
             test_embedder()->last_rvh_at_position_response());
 }
 
-IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, ChangeWindowName) {
+// Flaky on Win Aura Tests (1) bot.  See http://crbug.com/233087.
+#if defined(OS_WIN) && defined(USE_AURA)
+#define MAYBE_ChangeWindowName DISABLED_ChangeWindowName
+#else
+#define MAYBE_ChangeWindowName ChangeWindowName
+#endif
+
+IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, MAYBE_ChangeWindowName) {
   const char kEmbedderURL[] = "files/browser_plugin_naming_embedder.html";
   const char* kGuestURL = "files/browser_plugin_naming_guest.html";
-  StartBrowserPluginTest(kEmbedderURL, kGuestURL, false, "");
+  StartBrowserPluginTest(kEmbedderURL, kGuestURL, false, std::string());
 
   RenderViewHostImpl* rvh = static_cast<RenderViewHostImpl*>(
       test_embedder()->web_contents()->GetRenderViewHost());
diff --git a/content/browser/browser_plugin/browser_plugin_message_filter.h b/content/browser/browser_plugin/browser_plugin_message_filter.h
index 327d2f8..829c1ba 100644
--- a/content/browser/browser_plugin/browser_plugin_message_filter.h
+++ b/content/browser/browser_plugin/browser_plugin_message_filter.h
@@ -7,8 +7,6 @@
 
 #include "content/public/browser/browser_message_filter.h"
 
-struct ViewHostMsg_CreateWindow_Params;
-
 namespace content {
 
 class BrowserContext;
diff --git a/content/browser/browser_plugin/test_browser_plugin_guest.cc b/content/browser/browser_plugin/test_browser_plugin_guest.cc
index 3ca0697..083ea5a 100644
--- a/content/browser/browser_plugin/test_browser_plugin_guest.cc
+++ b/content/browser/browser_plugin/test_browser_plugin_guest.cc
@@ -17,7 +17,7 @@
 TestBrowserPluginGuest::TestBrowserPluginGuest(
     int instance_id,
     WebContentsImpl* web_contents)
-    : BrowserPluginGuest(instance_id, web_contents),
+    : BrowserPluginGuest(instance_id, web_contents, NULL, false),
       update_rect_count_(0),
       damage_buffer_call_count_(0),
       exit_observed_(false),
@@ -106,7 +106,9 @@
 
 void TestBrowserPluginGuest::RenderViewGone(base::TerminationStatus status) {
   exit_observed_ = true;
-  LOG(INFO) << "Guest crashed";
+  if (status != base::TERMINATION_STATUS_NORMAL_TERMINATION &&
+      status != base::TERMINATION_STATUS_STILL_RUNNING)
+    LOG(INFO) << "Guest crashed status: " << status;
   if (crash_message_loop_runner_)
     crash_message_loop_runner_->Quit();
   BrowserPluginGuest::RenderViewGone(status);
diff --git a/content/browser/browser_thread_impl.cc b/content/browser/browser_thread_impl.cc
index e2867c3..37f67bc 100644
--- a/content/browser/browser_thread_impl.cc
+++ b/content/browser/browser_thread_impl.cc
@@ -69,9 +69,8 @@
 }
 
 BrowserThreadImpl::BrowserThreadImpl(ID identifier,
-                                     MessageLoop* message_loop)
-    : Thread(message_loop->thread_name().c_str()),
-      identifier_(identifier) {
+                                     base::MessageLoop* message_loop)
+    : Thread(message_loop->thread_name().c_str()), identifier_(identifier) {
   set_message_loop(message_loop);
   Initialize();
 }
@@ -113,51 +112,54 @@
 MSVC_DISABLE_OPTIMIZE()
 MSVC_PUSH_DISABLE_WARNING(4748)
 
-NOINLINE void BrowserThreadImpl::UIThreadRun(MessageLoop* message_loop) {
+NOINLINE void BrowserThreadImpl::UIThreadRun(base::MessageLoop* message_loop) {
   volatile int line_number = __LINE__;
   Thread::Run(message_loop);
   CHECK_GT(line_number, 0);
 }
 
-NOINLINE void BrowserThreadImpl::DBThreadRun(MessageLoop* message_loop) {
+NOINLINE void BrowserThreadImpl::DBThreadRun(base::MessageLoop* message_loop) {
   volatile int line_number = __LINE__;
   Thread::Run(message_loop);
   CHECK_GT(line_number, 0);
 }
 
-NOINLINE void BrowserThreadImpl::WebKitThreadRun(MessageLoop* message_loop) {
+NOINLINE void BrowserThreadImpl::WebKitThreadRun(
+    base::MessageLoop* message_loop) {
   volatile int line_number = __LINE__;
   Thread::Run(message_loop);
   CHECK_GT(line_number, 0);
 }
 
-NOINLINE void BrowserThreadImpl::FileThreadRun(MessageLoop* message_loop) {
+NOINLINE void BrowserThreadImpl::FileThreadRun(
+    base::MessageLoop* message_loop) {
   volatile int line_number = __LINE__;
   Thread::Run(message_loop);
   CHECK_GT(line_number, 0);
 }
 
 NOINLINE void BrowserThreadImpl::FileUserBlockingThreadRun(
-    MessageLoop* message_loop) {
+    base::MessageLoop* message_loop) {
   volatile int line_number = __LINE__;
   Thread::Run(message_loop);
   CHECK_GT(line_number, 0);
 }
 
 NOINLINE void BrowserThreadImpl::ProcessLauncherThreadRun(
-    MessageLoop* message_loop) {
+    base::MessageLoop* message_loop) {
   volatile int line_number = __LINE__;
   Thread::Run(message_loop);
   CHECK_GT(line_number, 0);
 }
 
-NOINLINE void BrowserThreadImpl::CacheThreadRun(MessageLoop* message_loop) {
+NOINLINE void BrowserThreadImpl::CacheThreadRun(
+    base::MessageLoop* message_loop) {
   volatile int line_number = __LINE__;
   Thread::Run(message_loop);
   CHECK_GT(line_number, 0);
 }
 
-NOINLINE void BrowserThreadImpl::IOThreadRun(MessageLoop* message_loop) {
+NOINLINE void BrowserThreadImpl::IOThreadRun(base::MessageLoop* message_loop) {
   volatile int line_number = __LINE__;
   Thread::Run(message_loop);
   CHECK_GT(line_number, 0);
@@ -166,7 +168,7 @@
 MSVC_POP_WARNING()
 MSVC_ENABLE_OPTIMIZE();
 
-void BrowserThreadImpl::Run(MessageLoop* message_loop) {
+void BrowserThreadImpl::Run(base::MessageLoop* message_loop) {
   BrowserThread::ID thread_id;
   if (!GetCurrentThreadIdentifier(&thread_id))
     return Thread::Run(message_loop);
@@ -259,8 +261,9 @@
   if (!target_thread_outlives_current)
     globals.lock.Acquire();
 
-  MessageLoop* message_loop = globals.threads[identifier] ?
-      globals.threads[identifier]->message_loop() : NULL;
+  base::MessageLoop* message_loop =
+      globals.threads[identifier] ? globals.threads[identifier]->message_loop()
+                                  : NULL;
   if (message_loop) {
     if (nestable) {
       message_loop->PostDelayedTask(from_here, task, delay);
@@ -362,7 +365,7 @@
   DCHECK(identifier >= 0 && identifier < ID_COUNT);
   return globals.threads[identifier] &&
          globals.threads[identifier]->message_loop() ==
-             MessageLoop::current();
+             base::MessageLoop::current();
 }
 
 // static
@@ -434,7 +437,7 @@
   // function.
   // http://crbug.com/63678
   base::ThreadRestrictions::ScopedAllowSingleton allow_singleton;
-  MessageLoop* cur_message_loop = MessageLoop::current();
+  base::MessageLoop* cur_message_loop = base::MessageLoop::current();
   BrowserThreadGlobals& globals = g_globals.Get();
   for (int i = 0; i < ID_COUNT; ++i) {
     if (globals.threads[i] &&
@@ -450,9 +453,7 @@
 // static
 scoped_refptr<base::MessageLoopProxy>
 BrowserThread::GetMessageLoopProxyForThread(ID identifier) {
-  scoped_refptr<base::MessageLoopProxy> proxy(
-      new BrowserThreadMessageLoopProxy(identifier));
-  return proxy;
+  return make_scoped_refptr(new BrowserThreadMessageLoopProxy(identifier));
 }
 
 // static
@@ -464,7 +465,7 @@
   base::AutoLock lock(globals.lock);
   base::Thread* thread = globals.threads[identifier];
   DCHECK(thread);
-  MessageLoop* loop = thread->message_loop();
+  base::MessageLoop* loop = thread->message_loop();
   return loop;
 }
 
diff --git a/content/browser/browser_thread_impl.h b/content/browser/browser_thread_impl.h
index 7375420..b4ca49b 100644
--- a/content/browser/browser_thread_impl.h
+++ b/content/browser/browser_thread_impl.h
@@ -20,14 +20,15 @@
 
   // Special constructor for the main (UI) thread and unittests. We use a dummy
   // thread here since the main thread already exists.
-  BrowserThreadImpl(BrowserThread::ID identifier, MessageLoop* message_loop);
+  BrowserThreadImpl(BrowserThread::ID identifier,
+                    base::MessageLoop* message_loop);
   virtual ~BrowserThreadImpl();
 
   static void ShutdownThreadPool();
 
  protected:
   virtual void Init() OVERRIDE;
-  virtual void Run(MessageLoop* message_loop) OVERRIDE;
+  virtual void Run(base::MessageLoop* message_loop) OVERRIDE;
   virtual void CleanUp() OVERRIDE;
 
  private:
@@ -38,14 +39,14 @@
 
   // The following are unique function names that makes it possible to tell
   // the thread id from the callstack alone in crash dumps.
-  void UIThreadRun(MessageLoop* message_loop);
-  void DBThreadRun(MessageLoop* message_loop);
-  void WebKitThreadRun(MessageLoop* message_loop);
-  void FileThreadRun(MessageLoop* message_loop);
-  void FileUserBlockingThreadRun(MessageLoop* message_loop);
-  void ProcessLauncherThreadRun(MessageLoop* message_loop);
-  void CacheThreadRun(MessageLoop* message_loop);
-  void IOThreadRun(MessageLoop* message_loop);
+  void UIThreadRun(base::MessageLoop* message_loop);
+  void DBThreadRun(base::MessageLoop* message_loop);
+  void WebKitThreadRun(base::MessageLoop* message_loop);
+  void FileThreadRun(base::MessageLoop* message_loop);
+  void FileUserBlockingThreadRun(base::MessageLoop* message_loop);
+  void ProcessLauncherThreadRun(base::MessageLoop* message_loop);
+  void CacheThreadRun(base::MessageLoop* message_loop);
+  void IOThreadRun(base::MessageLoop* message_loop);
 
   static bool PostTaskHelper(
       BrowserThread::ID identifier,
diff --git a/content/browser/browser_thread_unittest.cc b/content/browser/browser_thread_unittest.cc
index 3dbfcf2..ec4b7cc 100644
--- a/content/browser/browser_thread_unittest.cc
+++ b/content/browser/browser_thread_unittest.cc
@@ -19,7 +19,7 @@
  public:
   void Release() const {
     CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-    loop_.PostTask(FROM_HERE, MessageLoop::QuitClosure());
+    loop_.PostTask(FROM_HERE, base::MessageLoop::QuitClosure());
   }
 
  protected:
@@ -35,17 +35,17 @@
     file_thread_->Stop();
   }
 
-  static void BasicFunction(MessageLoop* message_loop) {
+  static void BasicFunction(base::MessageLoop* message_loop) {
     CHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
-    message_loop->PostTask(FROM_HERE, MessageLoop::QuitClosure());
+    message_loop->PostTask(FROM_HERE, base::MessageLoop::QuitClosure());
   }
 
   class DeletedOnFile
       : public base::RefCountedThreadSafe<
             DeletedOnFile, BrowserThread::DeleteOnFileThread> {
    public:
-    explicit DeletedOnFile(MessageLoop* message_loop)
-        : message_loop_(message_loop) { }
+    explicit DeletedOnFile(base::MessageLoop* message_loop)
+        : message_loop_(message_loop) {}
 
    private:
     friend struct BrowserThread::DeleteOnThread<BrowserThread::FILE>;
@@ -53,25 +53,10 @@
 
     ~DeletedOnFile() {
       CHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
-      message_loop_->PostTask(FROM_HERE, MessageLoop::QuitClosure());
+      message_loop_->PostTask(FROM_HERE, base::MessageLoop::QuitClosure());
     }
 
-    MessageLoop* message_loop_;
-  };
-
-  class NeverDeleted
-      : public base::RefCountedThreadSafe<
-            NeverDeleted, BrowserThread::DeleteOnWebKitThread> {
-   public:
-
-   private:
-    friend struct BrowserThread::DeleteOnThread<
-        BrowserThread::WEBKIT_DEPRECATED>;
-    friend class base::DeleteHelper<NeverDeleted>;
-
-    ~NeverDeleted() {
-      CHECK(false);
-    }
+    base::MessageLoop* message_loop_;
   };
 
  private:
@@ -79,46 +64,43 @@
   scoped_ptr<BrowserThreadImpl> file_thread_;
   // It's kind of ugly to make this mutable - solely so we can post the Quit
   // Task from Release(). This should be fixed.
-  mutable MessageLoop loop_;
+  mutable base::MessageLoop loop_;
 };
 
 TEST_F(BrowserThreadTest, PostTask) {
   BrowserThread::PostTask(
-      BrowserThread::FILE, FROM_HERE,
-      base::Bind(&BasicFunction, MessageLoop::current()));
-  MessageLoop::current()->Run();
+      BrowserThread::FILE,
+      FROM_HERE,
+      base::Bind(&BasicFunction, base::MessageLoop::current()));
+  base::MessageLoop::current()->Run();
 }
 
 TEST_F(BrowserThreadTest, Release) {
   BrowserThread::ReleaseSoon(BrowserThread::UI, FROM_HERE, this);
-  MessageLoop::current()->Run();
+  base::MessageLoop::current()->Run();
 }
 
 TEST_F(BrowserThreadTest, ReleasedOnCorrectThread) {
   {
     scoped_refptr<DeletedOnFile> test(
-        new DeletedOnFile(MessageLoop::current()));
+        new DeletedOnFile(base::MessageLoop::current()));
   }
-  MessageLoop::current()->Run();
-}
-
-TEST_F(BrowserThreadTest, NotReleasedIfTargetThreadNonExistent) {
-  scoped_refptr<NeverDeleted> test(new NeverDeleted());
+  base::MessageLoop::current()->Run();
 }
 
 TEST_F(BrowserThreadTest, PostTaskViaMessageLoopProxy) {
   scoped_refptr<base::MessageLoopProxy> message_loop_proxy =
       BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE);
   message_loop_proxy->PostTask(
-      FROM_HERE, base::Bind(&BasicFunction, MessageLoop::current()));
-  MessageLoop::current()->Run();
+      FROM_HERE, base::Bind(&BasicFunction, base::MessageLoop::current()));
+  base::MessageLoop::current()->Run();
 }
 
 TEST_F(BrowserThreadTest, ReleaseViaMessageLoopProxy) {
   scoped_refptr<base::MessageLoopProxy> message_loop_proxy =
       BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI);
   message_loop_proxy->ReleaseSoon(FROM_HERE, this);
-  MessageLoop::current()->Run();
+  base::MessageLoop::current()->Run();
 }
 
 TEST_F(BrowserThreadTest, PostTaskAndReply) {
@@ -128,9 +110,9 @@
       BrowserThread::FILE,
       FROM_HERE,
       base::Bind(&base::DoNothing),
-      base::Bind(&MessageLoop::Quit,
-                 base::Unretained(MessageLoop::current()->current()))));
-  MessageLoop::current()->Run();
+      base::Bind(&base::MessageLoop::Quit,
+                 base::Unretained(base::MessageLoop::current()->current()))));
+  base::MessageLoop::current()->Run();
 }
 
-}
+}  // namespace content
diff --git a/content/browser/byte_stream.cc b/content/browser/byte_stream.cc
index 44f5ce3..f83e8c3 100644
--- a/content/browser/byte_stream.cc
+++ b/content/browser/byte_stream.cc
@@ -363,7 +363,7 @@
 
   bool was_empty = available_contents_.empty();
 
-  if (transfer_buffer.get()) {
+  if (transfer_buffer) {
     available_contents_.insert(available_contents_.end(),
                                         transfer_buffer->begin(),
                                         transfer_buffer->end());
diff --git a/content/browser/byte_stream_unittest.cc b/content/browser/byte_stream_unittest.cc
index 9ef45a3..aac6905 100644
--- a/content/browser/byte_stream_unittest.cc
+++ b/content/browser/byte_stream_unittest.cc
@@ -85,7 +85,7 @@
   }
 
  protected:
-  MessageLoop message_loop_;
+  base::MessageLoop message_loop_;
 
  private:
   int producing_seed_key_;
diff --git a/content/browser/cert_store_impl.h b/content/browser/cert_store_impl.h
index 5c13fa3..8a326e9 100644
--- a/content/browser/cert_store_impl.h
+++ b/content/browser/cert_store_impl.h
@@ -12,7 +12,7 @@
 #include "content/public/browser/cert_store.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
-#include "net/base/x509_certificate.h"
+#include "net/cert/x509_certificate.h"
 
 namespace content {
 
diff --git a/content/browser/child_process_launcher.cc b/content/browser/child_process_launcher.cc
index 66e7c83..bde7f93 100644
--- a/content/browser/child_process_launcher.cc
+++ b/content/browser/child_process_launcher.cc
@@ -266,30 +266,30 @@
       options.fds_to_remap = &fds_to_map;
 
 #if defined(OS_MACOSX)
-      // Use synchronization to make sure that the MachBroker is ready to
-      // receive a check-in from the new process before the new process
-      // actually tries to check in.
-      base::LaunchSynchronizationHandle synchronization_handle;
-      options.synchronize = &synchronization_handle;
+      // Hold the MachBroker lock for the duration of LaunchProcess. The child
+      // will send its task port to the parent almost immediately after startup.
+      // The Mach message will be delivered to the parent, but updating the
+      // record of the launch will wait until after the placeholder PID is
+      // inserted below. This ensures that while the child process may send its
+      // port to the parent prior to the parent leaving LaunchProcess, the
+      // order in which the record in MachBroker is updated is correct.
+      MachBroker* broker = MachBroker::GetInstance();
+      broker->GetLock().Acquire();
+
+      // Make sure the MachBroker is running, and inform it to expect a
+      // check-in from the new process.
+      broker->EnsureRunning();
 #endif  // defined(OS_MACOSX)
 
       bool launched = base::LaunchProcess(*cmd_line, options, &handle);
 
 #if defined(OS_MACOSX)
-      if (launched) {
-        MachBroker* broker = MachBroker::GetInstance();
-        {
-          base::AutoLock lock(broker->GetLock());
+      if (launched)
+        broker->AddPlaceholderForPid(handle);
 
-          // Make sure the MachBroker is running, and inform it to expect a
-          // check-in from the new process.
-          broker->EnsureRunning();
-          broker->AddPlaceholderForPid(handle);
-        }
-
-        // Now that the MachBroker is ready, the child may continue.
-        base::LaunchSynchronize(synchronization_handle);
-      }
+      // After updating the broker, release the lock and let the child's
+      // messasge be processed on the broker's thread.
+      broker->GetLock().Release();
 #endif  // defined(OS_MACOSX)
 
       if (!launched)
diff --git a/content/browser/child_process_security_policy_unittest.cc b/content/browser/child_process_security_policy_unittest.cc
index a2eed34..6aad9d9 100644
--- a/content/browser/child_process_security_policy_unittest.cc
+++ b/content/browser/child_process_security_policy_unittest.cc
@@ -55,8 +55,7 @@
   }
 
   virtual void SetUp() {
-    old_browser_client_ = GetContentClient()->browser();
-    GetContentClient()->set_browser_for_testing(&test_browser_client_);
+    old_browser_client_ = SetBrowserClientForTesting(&test_browser_client_);
 
     // Claim to always handle chrome:// URLs because the CPSP's notion of
     // allowing WebUI bindings is hard-wired to this particular scheme.
@@ -65,7 +64,7 @@
 
   virtual void TearDown() {
     test_browser_client_.ClearSchemes();
-    GetContentClient()->set_browser_for_testing(old_browser_client_);
+    SetBrowserClientForTesting(old_browser_client_);
   }
 
  protected:
diff --git a/content/browser/database_browsertest.cc b/content/browser/database_browsertest.cc
index 48f7304..29030ad 100644
--- a/content/browser/database_browsertest.cc
+++ b/content/browser/database_browsertest.cc
@@ -102,7 +102,7 @@
   CreateTable(shell());
   InsertRecord(shell(), "text");
   DeleteRecord(shell(), 0);
-  CompareRecords(shell(), "");
+  CompareRecords(shell(), std::string());
 
   InsertRecord(shell(), "0");
   InsertRecord(shell(), "1");
@@ -151,12 +151,12 @@
   for (int i = 0; i < 10; ++i)
     DeleteRecord(shell(), 0);
 
-  CompareRecords(shell(), "");
+  CompareRecords(shell(), std::string());
 
   RunScriptAndCheckResult(
       shell(), "deleteRecord(1)", "could not find row with index: 1");
 
-  CompareRecords(shell(), "");
+  CompareRecords(shell(), std::string());
 }
 
 // Create records in the database and verify they persist after reload.
@@ -186,7 +186,7 @@
   ASSERT_FALSE(HasTable(otr));
 
   CreateTable(otr);
-  CompareRecords(otr, "");
+  CompareRecords(otr, std::string());
 }
 
 // Attempt to read a database created in an off the record browser from a
@@ -200,7 +200,7 @@
   Navigate(shell());
   ASSERT_FALSE(HasTable(shell()));
   CreateTable(shell());
-  CompareRecords(shell(), "");
+  CompareRecords(shell(), std::string());
 }
 
 // Verify DB changes within first window are present in the second window.
diff --git a/content/browser/device_monitor_linux.cc b/content/browser/device_monitor_linux.cc
index 8a734b9..61aad7c 100644
--- a/content/browser/device_monitor_linux.cc
+++ b/content/browser/device_monitor_linux.cc
@@ -49,7 +49,7 @@
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
 
   // We want to be notified of IO message loop destruction to delete |udev_|.
-  MessageLoop::current()->AddDestructionObserver(this);
+  base::MessageLoop::current()->AddDestructionObserver(this);
 
   std::vector<UdevLinux::UdevMonitorFilter> filters;
   for (size_t i = 0; i < arraysize(kSubsystemMap); ++i) {
diff --git a/content/browser/device_monitor_linux.h b/content/browser/device_monitor_linux.h
index 60044c0..71f0924 100644
--- a/content/browser/device_monitor_linux.h
+++ b/content/browser/device_monitor_linux.h
@@ -20,7 +20,7 @@
 
 class UdevLinux;
 
-class DeviceMonitorLinux : public MessageLoop::DestructionObserver {
+class DeviceMonitorLinux : public base::MessageLoop::DestructionObserver {
  public:
   DeviceMonitorLinux();
   virtual ~DeviceMonitorLinux();
diff --git a/content/browser/device_orientation/data_fetcher_impl_android.cc b/content/browser/device_orientation/data_fetcher_impl_android.cc
index 287b63a..c7a066f 100644
--- a/content/browser/device_orientation/data_fetcher_impl_android.cc
+++ b/content/browser/device_orientation/data_fetcher_impl_android.cc
@@ -7,7 +7,7 @@
 #include "base/android/jni_android.h"
 #include "base/logging.h"
 #include "content/browser/device_orientation/orientation.h"
-#include "jni/DeviceOrientation_jni.h"
+#include "jni/DeviceMotionAndOrientation_jni.h"
 
 using base::android::AttachCurrentThread;
 
@@ -23,7 +23,7 @@
 
 DataFetcherImplAndroid::DataFetcherImplAndroid() {
   device_orientation_.Reset(
-      Java_DeviceOrientation_getInstance(AttachCurrentThread()));
+      Java_DeviceMotionAndOrientation_getInstance(AttachCurrentThread()));
 }
 
 void DataFetcherImplAndroid::Init(JNIEnv* env) {
@@ -31,9 +31,11 @@
   DCHECK(result);
 }
 
+// TODO(timvolodine): Modify this method to be able to distinguish
+// device motion from orientation.
 DataFetcher* DataFetcherImplAndroid::Create() {
   scoped_ptr<DataFetcherImplAndroid> fetcher(new DataFetcherImplAndroid);
-  if (fetcher->Start(kPeriodInMilliseconds))
+  if (fetcher->Start(DeviceData::kTypeOrientation, kPeriodInMilliseconds))
     return fetcher.release();
 
   LOG(ERROR) << "DataFetcherImplAndroid::Start failed!";
@@ -41,7 +43,9 @@
 }
 
 DataFetcherImplAndroid::~DataFetcherImplAndroid() {
-  Stop();
+  // TODO(timvolodine): Support device motion as well. Only stop
+  // the active event type(s).
+  Stop(DeviceData::kTypeOrientation);
 }
 
 const DeviceData* DataFetcherImplAndroid::GetDeviceData(
@@ -55,11 +59,11 @@
   // Do we have a new orientation value? (It's safe to do this outside the lock
   // because we only skip the lock if the value is null. We always enter the
   // lock if we're going to make use of the new value.)
-  if (next_orientation_.get()) {
+  if (next_orientation_) {
     base::AutoLock autolock(next_orientation_lock_);
     next_orientation_.swap(current_orientation_);
   }
-  if (!current_orientation_.get())
+  if (!current_orientation_)
     return new Orientation();
   return current_orientation_.get();
 }
@@ -76,17 +80,35 @@
   next_orientation_ = orientation;
 }
 
-bool DataFetcherImplAndroid::Start(int rate_in_milliseconds) {
-  DCHECK(!device_orientation_.is_null());
-  return Java_DeviceOrientation_start(AttachCurrentThread(),
-                                      device_orientation_.obj(),
-                                      reinterpret_cast<jint>(this),
-                                      rate_in_milliseconds);
+void DataFetcherImplAndroid::GotAcceleration(
+    JNIEnv*, jobject, double x, double y, double z) {
+  NOTIMPLEMENTED();
 }
 
-void DataFetcherImplAndroid::Stop() {
+void DataFetcherImplAndroid::GotAccelerationIncludingGravity(
+    JNIEnv*, jobject, double x, double y, double z) {
+  NOTIMPLEMENTED();
+}
+
+void DataFetcherImplAndroid::GotRotationRate(
+    JNIEnv*, jobject, double alpha, double beta, double gamma) {
+  NOTIMPLEMENTED();
+}
+
+bool DataFetcherImplAndroid::Start(
+    DeviceData::Type event_type, int rate_in_milliseconds) {
   DCHECK(!device_orientation_.is_null());
-  Java_DeviceOrientation_stop(AttachCurrentThread(), device_orientation_.obj());
+  return Java_DeviceMotionAndOrientation_start(
+      AttachCurrentThread(), device_orientation_.obj(),
+      reinterpret_cast<jint>(this), static_cast<jint>(event_type),
+      rate_in_milliseconds);
+}
+
+void DataFetcherImplAndroid::Stop(DeviceData::Type event_type) {
+  DCHECK(!device_orientation_.is_null());
+  Java_DeviceMotionAndOrientation_stop(
+      AttachCurrentThread(), device_orientation_.obj(),
+      static_cast<jint>(event_type));
 }
 
 }  // namespace content
diff --git a/content/browser/device_orientation/data_fetcher_impl_android.h b/content/browser/device_orientation/data_fetcher_impl_android.h
index cbcb363..568fe55 100644
--- a/content/browser/device_orientation/data_fetcher_impl_android.h
+++ b/content/browser/device_orientation/data_fetcher_impl_android.h
@@ -37,6 +37,12 @@
   // Called from Java via JNI.
   void GotOrientation(JNIEnv*, jobject,
                       double alpha, double beta, double gamma);
+  void GotAcceleration(JNIEnv*, jobject,
+                       double x, double y, double z);
+  void GotAccelerationIncludingGravity(JNIEnv*, jobject,
+                                       double x, double y, double z);
+  void GotRotationRate(JNIEnv*, jobject,
+                       double alpha, double beta, double gamma);
 
   // Implementation of DataFetcher.
   virtual const DeviceData* GetDeviceData(DeviceData::Type type) OVERRIDE;
@@ -46,8 +52,10 @@
   const Orientation* GetOrientation();
 
   // Wrappers for JNI methods.
-  bool Start(int rate_in_milliseconds);
-  void Stop();
+  // TODO(timvolodine): move the DeviceData::Type enum to the service class
+  // once it is implemented.
+  bool Start(DeviceData::Type event_type, int rate_in_milliseconds);
+  void Stop(DeviceData::Type event_type);
 
   // Value returned by GetDeviceData.
   scoped_refptr<Orientation> current_orientation_;
diff --git a/content/browser/device_orientation/data_fetcher_impl_win.cc b/content/browser/device_orientation/data_fetcher_impl_win.cc
new file mode 100644
index 0000000..d08ed44
--- /dev/null
+++ b/content/browser/device_orientation/data_fetcher_impl_win.cc
@@ -0,0 +1,193 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/device_orientation/data_fetcher_impl_win.h"
+
+#include <InitGuid.h>
+#include <PortableDeviceTypes.h>
+#include <Sensors.h>
+
+#include "base/logging.h"
+#include "base/win/iunknown_impl.h"
+#include "base/win/windows_version.h"
+#include "content/browser/device_orientation/orientation.h"
+
+namespace {
+
+// This should match ProviderImpl::kDesiredSamplingIntervalMs.
+const int kPeriodInMilliseconds = 100;
+
+}  // namespace
+
+namespace content {
+
+class DataFetcherImplWin::SensorEventSink : public ISensorEvents,
+                                            public base::win::IUnknownImpl {
+ public:
+  explicit SensorEventSink(DataFetcherImplWin* const fetcher)
+      : fetcher_(fetcher) {}
+
+  virtual ~SensorEventSink() {}
+
+  // IUnknown interface
+  virtual ULONG STDMETHODCALLTYPE AddRef() OVERRIDE {
+    return IUnknownImpl::AddRef();
+  }
+
+  virtual ULONG STDMETHODCALLTYPE Release() OVERRIDE {
+    return IUnknownImpl::Release();
+  }
+
+  virtual STDMETHODIMP QueryInterface(REFIID riid, void** ppv) OVERRIDE {
+    if (riid == __uuidof(ISensorEvents)) {
+      *ppv = static_cast<ISensorEvents*>(this);
+      AddRef();
+      return S_OK;
+    }
+    return IUnknownImpl::QueryInterface(riid, ppv);
+  }
+
+  // ISensorEvents interface
+  STDMETHODIMP OnEvent(ISensor* sensor,
+                       REFGUID event_id,
+                       IPortableDeviceValues* event_data) OVERRIDE {
+    return S_OK;
+  }
+
+  STDMETHODIMP OnDataUpdated(ISensor* sensor,
+                             ISensorDataReport* new_data) OVERRIDE {
+    if (NULL == new_data || NULL == sensor)
+      return E_INVALIDARG;
+
+    PROPVARIANT value = {};
+    scoped_refptr<Orientation> orientation = new Orientation();
+
+    if (SUCCEEDED(new_data->GetSensorValue(
+            SENSOR_DATA_TYPE_TILT_X_DEGREES, &value))) {
+      orientation->set_beta(value.fltVal);
+    }
+    PropVariantClear(&value);
+
+    if (SUCCEEDED(new_data->GetSensorValue(
+            SENSOR_DATA_TYPE_TILT_Y_DEGREES, &value))) {
+      orientation->set_gamma(value.fltVal);
+    }
+    PropVariantClear(&value);
+
+    if (SUCCEEDED(new_data->GetSensorValue(
+            SENSOR_DATA_TYPE_TILT_Z_DEGREES, &value))) {
+      orientation->set_alpha(value.fltVal);
+    }
+    PropVariantClear(&value);
+
+    orientation->set_absolute(true);
+    fetcher_->OnOrientationData(orientation.get());
+
+    return S_OK;
+  }
+
+  STDMETHODIMP OnLeave(REFSENSOR_ID sensor_id) OVERRIDE {
+    return S_OK;
+  }
+
+  STDMETHODIMP OnStateChanged(ISensor* sensor, SensorState state) OVERRIDE {
+    return S_OK;
+  }
+
+ private:
+  DataFetcherImplWin* const fetcher_;
+
+  DISALLOW_COPY_AND_ASSIGN(SensorEventSink);
+};
+
+// Create a DataFetcherImplWin object and return NULL if no valid sensor found.
+// static
+DataFetcher* DataFetcherImplWin::Create() {
+  scoped_ptr<DataFetcherImplWin> fetcher(new DataFetcherImplWin);
+  if (fetcher->Initialize())
+    return fetcher.release();
+
+  LOG(ERROR) << "DataFetcherImplWin::Initialize failed!";
+  return NULL;
+}
+
+DataFetcherImplWin::~DataFetcherImplWin() {
+  if (sensor_)
+    sensor_->SetEventSink(NULL);
+}
+
+DataFetcherImplWin::DataFetcherImplWin() {
+}
+
+void DataFetcherImplWin::OnOrientationData(Orientation* orientation) {
+  // This method is called on Windows sensor thread.
+  base::AutoLock autolock(next_orientation_lock_);
+  next_orientation_ = orientation;
+}
+
+const DeviceData* DataFetcherImplWin::GetDeviceData(DeviceData::Type type) {
+  if (type != DeviceData::kTypeOrientation)
+    return NULL;
+  return GetOrientation();
+}
+
+const Orientation* DataFetcherImplWin::GetOrientation() {
+  if (next_orientation_.get()) {
+    base::AutoLock autolock(next_orientation_lock_);
+    next_orientation_.swap(current_orientation_);
+  }
+  if (!current_orientation_.get())
+    return new Orientation();
+  return current_orientation_.get();
+}
+
+bool DataFetcherImplWin::Initialize() {
+  if (base::win::GetVersion() < base::win::VERSION_WIN7)
+    return false;
+
+  base::win::ScopedComPtr<ISensorManager> sensor_manager;
+  HRESULT hr = sensor_manager.CreateInstance(CLSID_SensorManager);
+  if (FAILED(hr) || !sensor_manager)
+    return false;
+
+  base::win::ScopedComPtr<ISensorCollection> sensor_collection;
+  hr = sensor_manager->GetSensorsByType(
+      SENSOR_TYPE_INCLINOMETER_3D, sensor_collection.Receive());
+
+  if (FAILED(hr) || !sensor_collection)
+    return false;
+
+  ULONG count = 0;
+  hr = sensor_collection->GetCount(&count);
+  if (FAILED(hr) || !count)
+    return false;
+
+  hr = sensor_collection->GetAt(0, sensor_.Receive());
+  if (FAILED(hr) || !sensor_)
+    return false;
+
+  base::win::ScopedComPtr<IPortableDeviceValues> device_values;
+  if (SUCCEEDED(device_values.CreateInstance(CLSID_PortableDeviceValues))) {
+    if (SUCCEEDED(device_values->SetUnsignedIntegerValue(
+            SENSOR_PROPERTY_CURRENT_REPORT_INTERVAL, kPeriodInMilliseconds))) {
+      base::win::ScopedComPtr<IPortableDeviceValues> return_values;
+      sensor_->SetProperties(device_values.get(), return_values.Receive());
+    }
+  }
+
+  scoped_refptr<SensorEventSink> sensor_event_impl(new SensorEventSink(this));
+  base::win::ScopedComPtr<ISensorEvents> sensor_events;
+  hr = sensor_event_impl->QueryInterface(
+      __uuidof(ISensorEvents), sensor_events.ReceiveVoid());
+  if (FAILED(hr) || !sensor_events)
+    return false;
+
+  hr = sensor_->SetEventSink(sensor_events);
+  if (FAILED(hr))
+    return false;
+
+  return true;
+}
+
+}  // namespace content
diff --git a/content/browser/device_orientation/data_fetcher_impl_win.h b/content/browser/device_orientation/data_fetcher_impl_win.h
new file mode 100644
index 0000000..9a06506
--- /dev/null
+++ b/content/browser/device_orientation/data_fetcher_impl_win.h
@@ -0,0 +1,63 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_DEVICE_ORIENTATION_DATA_FETCHER_IMPL_WIN_H_
+#define CONTENT_BROWSER_DEVICE_ORIENTATION_DATA_FETCHER_IMPL_WIN_H_
+
+#include <SensorsApi.h>
+
+#include "base/compiler_specific.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/synchronization/lock.h"
+#include "base/win/scoped_comptr.h"
+#include "content/browser/device_orientation/data_fetcher.h"
+#include "content/browser/device_orientation/device_data.h"
+
+namespace content {
+
+class Orientation;
+
+// Windows implementation of DeviceOrientation API.
+// The SensorEventSink is installed to Windows sensor thread to listen for
+// sensor's data. Upon each notification, DataFetcherImplWin buffers the data.
+// Then Chrome sensor polling thread pulls the buffered data via GetDeviceData.
+// The Inclinometer 3D sensor (SENSOR_TYPE_INCLINOMETER_3D) is used to get the
+// orientation data.
+
+class DataFetcherImplWin : public DataFetcher {
+ public:
+  virtual ~DataFetcherImplWin();
+
+  // Factory function. It returns NULL on error.
+  // The created object listens for events for the whole lifetime.
+  static DataFetcher* Create();
+
+  // Implement DataFetcher.
+  virtual const DeviceData* GetDeviceData(DeviceData::Type type) OVERRIDE;
+
+ private:
+  class SensorEventSink;
+  friend SensorEventSink;
+
+  DataFetcherImplWin();
+  bool Initialize();
+  void OnOrientationData(Orientation* orientation);
+  const Orientation* GetOrientation();
+
+  base::win::ScopedComPtr<ISensor> sensor_;
+
+  // Value returned by GetDeviceData.
+  scoped_refptr<Orientation> current_orientation_;
+
+  // The 1-element buffer follows DataFetcherImplAndroid implementation.
+  // It is written by OnOrientationData and read by GetDeviceData.
+  base::Lock next_orientation_lock_;
+  scoped_refptr<Orientation> next_orientation_;
+
+  DISALLOW_COPY_AND_ASSIGN(DataFetcherImplWin);
+};
+
+}  // namespace content
+
+#endif  // CONTENT_BROWSER_DEVICE_ORIENTATION_DATA_FETCHER_IMPL_WIN_H_
diff --git a/content/browser/device_orientation/device_data.h b/content/browser/device_orientation/device_data.h
index ae65618..e8c79ad 100644
--- a/content/browser/device_orientation/device_data.h
+++ b/content/browser/device_orientation/device_data.h
@@ -17,10 +17,12 @@
 class CONTENT_EXPORT DeviceData :
     public base::RefCountedThreadSafe<DeviceData> {
  public:
+  // TODO(timvolodine): move the DeviceData::Type enum to the service class
+  // once it is implemented.
   enum Type {
-    kTypeMotion,
-    kTypeOrientation,
-    kTypeTest
+    kTypeOrientation = 0,
+    kTypeMotion = 1,
+    kTypeTest = 100
   };
 
   virtual IPC::Message* CreateIPCMessage(int render_view_id) const = 0;
diff --git a/content/browser/device_orientation/observer_delegate.cc b/content/browser/device_orientation/observer_delegate.cc
index 1ffe07a..fc4273f 100644
--- a/content/browser/device_orientation/observer_delegate.cc
+++ b/content/browser/device_orientation/observer_delegate.cc
@@ -29,7 +29,7 @@
 void ObserverDelegate::OnDeviceDataUpdate(
     const DeviceData* device_data, DeviceData::Type device_data_type) {
   scoped_refptr<const DeviceData> new_device_data(device_data);
-  if (!new_device_data.get())
+  if (!new_device_data)
     new_device_data = EmptyDeviceData(device_data_type);
 
   sender_->Send(new_device_data->CreateIPCMessage(render_view_id_));
diff --git a/content/browser/device_orientation/provider.cc b/content/browser/device_orientation/provider.cc
index ead9b14..b7aa52f 100644
--- a/content/browser/device_orientation/provider.cc
+++ b/content/browser/device_orientation/provider.cc
@@ -13,6 +13,8 @@
 #include "content/browser/device_orientation/accelerometer_mac.h"
 #elif defined(OS_ANDROID)
 #include "content/browser/device_orientation/data_fetcher_impl_android.h"
+#elif defined(OS_WIN)
+#include "content/browser/device_orientation/data_fetcher_impl_win.h"
 #endif
 
 namespace content {
@@ -26,6 +28,8 @@
     default_factory = AccelerometerMac::Create;
 #elif defined(OS_ANDROID)
     default_factory = DataFetcherImplAndroid::Create;
+#elif defined(OS_WIN)
+    default_factory = DataFetcherImplWin::Create;
 #endif
 
     instance_ = new ProviderImpl(default_factory);
diff --git a/content/browser/device_orientation/provider_impl.cc b/content/browser/device_orientation/provider_impl.cc
index c490514..59bdebf 100644
--- a/content/browser/device_orientation/provider_impl.cc
+++ b/content/browser/device_orientation/provider_impl.cc
@@ -27,7 +27,7 @@
  public:
   PollingThread(const char* name,
                 base::WeakPtr<ProviderImpl> provider,
-                MessageLoop* creator_loop);
+                base::MessageLoop* creator_loop);
   virtual ~PollingThread();
 
   // Method for creating a DataFetcher and starting the polling, if the fetcher
@@ -52,7 +52,7 @@
 
   // The Message Loop on which this object was created.
   // Typically the I/O loop, but may be something else during testing.
-  MessageLoop* creator_loop_;
+  base::MessageLoop* creator_loop_;
 
   scoped_ptr<DataFetcher> data_fetcher_;
   std::map<DeviceData::Type, scoped_refptr<const DeviceData> >
@@ -62,28 +62,24 @@
   base::WeakPtr<ProviderImpl> provider_;
 };
 
-ProviderImpl::PollingThread::PollingThread(
-    const char* name,
-    base::WeakPtr<ProviderImpl> provider,
-    MessageLoop* creator_loop)
-    : base::Thread(name),
-      creator_loop_(creator_loop),
-      provider_(provider) {
-}
+ProviderImpl::PollingThread::PollingThread(const char* name,
+                                           base::WeakPtr<ProviderImpl> provider,
+                                           base::MessageLoop* creator_loop)
+    : base::Thread(name), creator_loop_(creator_loop), provider_(provider) {}
 
 ProviderImpl::PollingThread::~PollingThread() {
   Stop();
 }
 
 void ProviderImpl::PollingThread::DoAddPollingDataType(DeviceData::Type type) {
-  DCHECK(MessageLoop::current() == message_loop());
+  DCHECK(base::MessageLoop::current() == message_loop());
 
   polling_data_types_.insert(type);
 }
 
 void ProviderImpl::PollingThread::Initialize(DataFetcherFactory factory,
                                              DeviceData::Type type) {
-  DCHECK(MessageLoop::current() == message_loop());
+  DCHECK(base::MessageLoop::current() == message_loop());
 
   if (factory != NULL) {
     // Try to use factory to create a fetcher that can provide this type of
@@ -91,7 +87,7 @@
     // start polling.
     scoped_ptr<DataFetcher> fetcher(factory());
 
-    if (fetcher.get()) {
+    if (fetcher) {
       scoped_refptr<const DeviceData> device_data(fetcher->GetDeviceData(type));
       if (device_data != NULL) {
         // Pass ownership of fetcher to provider_.
@@ -115,7 +111,7 @@
 void ProviderImpl::PollingThread::ScheduleDoNotify(
     const scoped_refptr<const DeviceData>& device_data,
     DeviceData::Type device_data_type) {
-  DCHECK(MessageLoop::current() == message_loop());
+  DCHECK(base::MessageLoop::current() == message_loop());
 
   creator_loop_->PostTask(FROM_HERE,
                           base::Bind(&ProviderImpl::DoNotify, provider_,
@@ -123,7 +119,7 @@
 }
 
 void ProviderImpl::PollingThread::DoPoll() {
-  DCHECK(MessageLoop::current() == message_loop());
+  DCHECK(base::MessageLoop::current() == message_loop());
 
   // Poll the fetcher for each type of data.
   typedef std::set<DeviceData::Type>::const_iterator SetIterator;
@@ -152,7 +148,7 @@
 }
 
 void ProviderImpl::PollingThread::ScheduleDoPoll() {
-  DCHECK(MessageLoop::current() == message_loop());
+  DCHECK(base::MessageLoop::current() == message_loop());
 
   message_loop()->PostDelayedTask(
       FROM_HERE,
@@ -161,7 +157,7 @@
 }
 
 base::TimeDelta ProviderImpl::PollingThread::SamplingInterval() const {
-  DCHECK(MessageLoop::current() == message_loop());
+  DCHECK(base::MessageLoop::current() == message_loop());
   DCHECK(data_fetcher_.get());
 
   // TODO(erg): There used to be unused code here, that called a default
@@ -171,9 +167,9 @@
 }
 
 ProviderImpl::ProviderImpl(DataFetcherFactory factory)
-    : creator_loop_(MessageLoop::current()),
+    : creator_loop_(base::MessageLoop::current()),
       factory_(factory),
-      ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)),
+      weak_factory_(this),
       polling_thread_(NULL) {
 }
 
@@ -182,9 +178,9 @@
 }
 
 void ProviderImpl::ScheduleDoAddPollingDataType(DeviceData::Type type) {
-  DCHECK(MessageLoop::current() == creator_loop_);
+  DCHECK(base::MessageLoop::current() == creator_loop_);
 
-  MessageLoop* polling_loop = polling_thread_->message_loop();
+  base::MessageLoop* polling_loop = polling_thread_->message_loop();
   polling_loop->PostTask(FROM_HERE,
                          base::Bind(&PollingThread::DoAddPollingDataType,
                                     base::Unretained(polling_thread_),
@@ -192,7 +188,7 @@
 }
 
 void ProviderImpl::AddObserver(Observer* observer) {
-  DCHECK(MessageLoop::current() == creator_loop_);
+  DCHECK(base::MessageLoop::current() == creator_loop_);
 
   DeviceData::Type type = observer->device_data_type();
 
@@ -210,7 +206,7 @@
 }
 
 void ProviderImpl::RemoveObserver(Observer* observer) {
-  DCHECK(MessageLoop::current() == creator_loop_);
+  DCHECK(base::MessageLoop::current() == creator_loop_);
 
   observers_.erase(observer);
   if (observers_.empty())
@@ -218,12 +214,15 @@
 }
 
 void ProviderImpl::Start(DeviceData::Type type) {
-  DCHECK(MessageLoop::current() == creator_loop_);
+  DCHECK(base::MessageLoop::current() == creator_loop_);
   DCHECK(!polling_thread_);
 
   polling_thread_ = new PollingThread("Device data polling thread",
                                       weak_factory_.GetWeakPtr(),
                                       creator_loop_);
+#if defined(OS_WIN)
+  polling_thread_->init_com_with_mta(true);
+#endif
   if (!polling_thread_->Start()) {
     LOG(ERROR) << "Failed to start device data polling thread";
     delete polling_thread_;
@@ -234,7 +233,7 @@
 }
 
 void ProviderImpl::Stop() {
-  DCHECK(MessageLoop::current() == creator_loop_);
+  DCHECK(base::MessageLoop::current() == creator_loop_);
 
   weak_factory_.InvalidateWeakPtrs();
   if (polling_thread_) {
@@ -250,9 +249,9 @@
 
 void ProviderImpl::ScheduleInitializePollingThread(
     DeviceData::Type device_data_type) {
-  DCHECK(MessageLoop::current() == creator_loop_);
+  DCHECK(base::MessageLoop::current() == creator_loop_);
 
-  MessageLoop* polling_loop = polling_thread_->message_loop();
+  base::MessageLoop* polling_loop = polling_thread_->message_loop();
   polling_loop->PostTask(FROM_HERE,
                          base::Bind(&PollingThread::Initialize,
                                     base::Unretained(polling_thread_),
@@ -262,7 +261,7 @@
 
 void ProviderImpl::DoNotify(const scoped_refptr<const DeviceData>& data,
     DeviceData::Type device_data_type) {
-  DCHECK(MessageLoop::current() == creator_loop_);
+  DCHECK(base::MessageLoop::current() == creator_loop_);
 
   // Update last notification of this type.
   last_notifications_map_[device_data_type] = data;
diff --git a/content/browser/device_orientation/provider_impl.h b/content/browser/device_orientation/provider_impl.h
index 6706f06..be7cf3b 100644
--- a/content/browser/device_orientation/provider_impl.h
+++ b/content/browser/device_orientation/provider_impl.h
@@ -16,7 +16,9 @@
 #include "content/browser/device_orientation/provider.h"
 #include "content/common/content_export.h"
 
+namespace base {
 class MessageLoop;
+}
 
 namespace content {
 
@@ -55,7 +57,7 @@
 
   // The Message Loop on which this object was created.
   // Typically the I/O loop, but may be something else during testing.
-  MessageLoop* creator_loop_;
+  base::MessageLoop* creator_loop_;
 
   // Members below are only to be used from the creator_loop_.
   DataFetcherFactory factory_;
diff --git a/content/browser/device_orientation/provider_unittest.cc b/content/browser/device_orientation/provider_unittest.cc
index 4358c7f..ee2beed 100644
--- a/content/browser/device_orientation/provider_unittest.cc
+++ b/content/browser/device_orientation/provider_unittest.cc
@@ -150,7 +150,8 @@
     --(*expectations_count_ptr_);
 
     if (*expectations_count_ptr_ == 0) {
-      MessageLoop::current()->PostTask(FROM_HERE, MessageLoop::QuitClosure());
+      base::MessageLoop::current()->PostTask(FROM_HERE,
+                                             base::MessageLoop::QuitClosure());
     }
   }
 };
@@ -196,7 +197,8 @@
     --(*expectations_count_ptr_);
 
     if (*expectations_count_ptr_ == 0) {
-      MessageLoop::current()->PostTask(FROM_HERE, MessageLoop::QuitClosure());
+      base::MessageLoop::current()->PostTask(FROM_HERE,
+                                             base::MessageLoop::QuitClosure());
     }
   }
 };
@@ -228,7 +230,8 @@
     --(*expectations_count_ptr_);
 
     if (*expectations_count_ptr_ == 0) {
-      MessageLoop::current()->PostTask(FROM_HERE, MessageLoop::QuitClosure());
+      base::MessageLoop::current()->PostTask(FROM_HERE,
+                                             base::MessageLoop::QuitClosure());
     }
   }
 };
@@ -330,7 +333,7 @@
   scoped_refptr<Provider> provider_;
 
   // Message loop for the test thread.
-  MessageLoop message_loop_;
+  base::MessageLoop message_loop_;
 };
 
 TEST_F(DeviceOrientationProviderTest, FailingTest) {
@@ -346,11 +349,11 @@
 
   checker_a->AddExpectation(new Orientation());
   provider_->AddObserver(checker_a.get());
-  MessageLoop::current()->Run();
+  base::MessageLoop::current()->Run();
 
   checker_b->AddExpectation(new Orientation());
   provider_->AddObserver(checker_b.get());
-  MessageLoop::current()->Run();
+  base::MessageLoop::current()->Run();
 
   MockDeviceDataFactory::SetCurInstance(NULL);
 }
@@ -385,7 +388,7 @@
   device_data_factory->SetDeviceData(test_orientation,
       DeviceData::kTypeOrientation);
   provider_->AddObserver(checker.get());
-  MessageLoop::current()->Run();
+  base::MessageLoop::current()->Run();
 
   provider_->RemoveObserver(checker.get());
   MockDeviceDataFactory::SetCurInstance(NULL);
@@ -426,7 +429,7 @@
   device_data_factory->SetDeviceData(test_orientations[0],
       DeviceData::kTypeOrientation);
   provider_->AddObserver(checker_a.get());
-  MessageLoop::current()->Run();
+  base::MessageLoop::current()->Run();
 
   checker_a->AddExpectation(test_orientations[1]);
   checker_b->AddExpectation(test_orientations[0]);
@@ -434,7 +437,7 @@
   device_data_factory->SetDeviceData(test_orientations[1],
       DeviceData::kTypeOrientation);
   provider_->AddObserver(checker_b.get());
-  MessageLoop::current()->Run();
+  base::MessageLoop::current()->Run();
 
   provider_->RemoveObserver(checker_a.get());
   checker_b->AddExpectation(test_orientations[2]);
@@ -443,7 +446,7 @@
   device_data_factory->SetDeviceData(test_orientations[2],
       DeviceData::kTypeOrientation);
   provider_->AddObserver(checker_c.get());
-  MessageLoop::current()->Run();
+  base::MessageLoop::current()->Run();
 
   provider_->RemoveObserver(checker_b.get());
   provider_->RemoveObserver(checker_c.get());
@@ -472,13 +475,13 @@
 
   test_data_checker->AddExpectation(new TestData());
   provider_->AddObserver(test_data_checker.get());
-  MessageLoop::current()->Run();
+  base::MessageLoop::current()->Run();
 
   orientation_checker->AddExpectation(test_orientation);
   device_data_factory->SetDeviceData(test_orientation,
       DeviceData::kTypeOrientation);
   provider_->AddObserver(orientation_checker.get());
-  MessageLoop::current()->Run();
+  base::MessageLoop::current()->Run();
 
   provider_->RemoveObserver(test_data_checker.get());
   provider_->RemoveObserver(orientation_checker.get());
@@ -515,12 +518,12 @@
   device_data_factory->SetDeviceData(test_orientation,
       DeviceData::kTypeOrientation);
   provider_->AddObserver(checker.get());
-  MessageLoop::current()->Run();
+  base::MessageLoop::current()->Run();
 
   checker->AddExpectation(test_orientation2);
   device_data_factory->SetDeviceData(test_orientation2,
       DeviceData::kTypeOrientation);
-  MessageLoop::current()->Run();
+  base::MessageLoop::current()->Run();
 
   MockDeviceDataFactory::SetCurInstance(NULL);
 
@@ -553,15 +556,15 @@
       DeviceData::kTypeOrientation);
   checker_a->AddExpectation(test_orientation);
   provider_->AddObserver(checker_a.get());
-  MessageLoop::current()->Run();
+  base::MessageLoop::current()->Run();
 
   checker_a->AddExpectation(new Orientation());
   device_data_factory->SetFailing(true);
-  MessageLoop::current()->Run();
+  base::MessageLoop::current()->Run();
 
   checker_b->AddExpectation(new Orientation());
   provider_->AddObserver(checker_b.get());
-  MessageLoop::current()->Run();
+  base::MessageLoop::current()->Run();
 
   provider_->RemoveObserver(checker_a.get());
   provider_->RemoveObserver(checker_b.get());
@@ -595,7 +598,7 @@
   device_data_factory->SetDeviceData(test_orientation,
       DeviceData::kTypeOrientation);
   provider_->AddObserver(checker_a.get());
-  MessageLoop::current()->Run();
+  base::MessageLoop::current()->Run();
 
   provider_->RemoveObserver(checker_a.get()); // This stops the Provider.
 
@@ -603,7 +606,7 @@
   device_data_factory->SetDeviceData(test_orientation2,
       DeviceData::kTypeOrientation);
   provider_->AddObserver(checker_b.get());
-  MessageLoop::current()->Run();
+  base::MessageLoop::current()->Run();
 
   provider_->RemoveObserver(checker_b.get());
   MockDeviceDataFactory::SetCurInstance(NULL);
@@ -634,12 +637,12 @@
   device_data_factory->SetDeviceData(test_motion, DeviceData::kTypeMotion);
   checker->AddExpectation(test_motion);
   provider_->AddObserver(checker.get());
-  MessageLoop::current()->Run();
+  base::MessageLoop::current()->Run();
 
   // The observer should receive the same motion again.
   device_data_factory->SetDeviceData(test_motion, DeviceData::kTypeMotion);
   checker->AddExpectation(test_motion);
-  MessageLoop::current()->Run();
+  base::MessageLoop::current()->Run();
 
   provider_->RemoveObserver(checker.get());
   MockDeviceDataFactory::SetCurInstance(NULL);
@@ -685,20 +688,20 @@
       DeviceData::kTypeOrientation);
   checker_a->AddExpectation(first_orientation);
   provider_->AddObserver(checker_a.get());
-  MessageLoop::current()->Run();
+  base::MessageLoop::current()->Run();
 
   // The observers should not see this insignificantly different orientation.
   device_data_factory->SetDeviceData(second_orientation,
       DeviceData::kTypeOrientation);
   checker_b->AddExpectation(first_orientation);
   provider_->AddObserver(checker_b.get());
-  MessageLoop::current()->Run();
+  base::MessageLoop::current()->Run();
 
   device_data_factory->SetDeviceData(third_orientation,
       DeviceData::kTypeOrientation);
   checker_a->AddExpectation(third_orientation);
   checker_b->AddExpectation(third_orientation);
-  MessageLoop::current()->Run();
+  base::MessageLoop::current()->Run();
 
   provider_->RemoveObserver(checker_a.get());
   provider_->RemoveObserver(checker_b.get());
diff --git a/content/browser/devtools/devtools_agent_host_impl.cc b/content/browser/devtools/devtools_agent_host_impl.cc
index a4c9449..881e4bfc 100644
--- a/content/browser/devtools/devtools_agent_host_impl.cc
+++ b/content/browser/devtools/devtools_agent_host_impl.cc
@@ -9,7 +9,7 @@
 #include "base/basictypes.h"
 #include "base/guid.h"
 #include "base/lazy_instance.h"
-#include "content/common/devtools_messages.h"
+#include "content/browser/devtools/devtools_manager_impl.h"
 
 namespace content {
 
@@ -38,32 +38,11 @@
   return it->second;
 }
 
-void DevToolsAgentHostImpl::Attach() {
-  SendMessageToAgent(new DevToolsAgentMsg_Attach(MSG_ROUTING_NONE));
-  NotifyClientAttaching();
-}
-
-void DevToolsAgentHostImpl::Reattach(const std::string& saved_agent_state) {
-  SendMessageToAgent(new DevToolsAgentMsg_Reattach(
-      MSG_ROUTING_NONE,
-      saved_agent_state));
-  NotifyClientAttaching();
-}
-
-void DevToolsAgentHostImpl::Detach() {
-  SendMessageToAgent(new DevToolsAgentMsg_Detach(MSG_ROUTING_NONE));
-  NotifyClientDetaching();
-}
-
-void DevToolsAgentHostImpl::DispatchOnInspectorBackend(
-    const std::string& message) {
-  SendMessageToAgent(new DevToolsAgentMsg_DispatchOnInspectorBackend(
-      MSG_ROUTING_NONE, message));
+bool DevToolsAgentHostImpl::IsAttached() {
+  return !!DevToolsManagerImpl::GetInstance()->GetDevToolsClientHostFor(this);
 }
 
 void DevToolsAgentHostImpl::InspectElement(int x, int y) {
-  SendMessageToAgent(new DevToolsAgentMsg_InspectElement(MSG_ROUTING_NONE,
-                                                         x, y));
 }
 
 std::string DevToolsAgentHostImpl::GetId() {
diff --git a/content/browser/devtools/devtools_agent_host_impl.h b/content/browser/devtools/devtools_agent_host_impl.h
index 6e1f481..9c21650 100644
--- a/content/browser/devtools/devtools_agent_host_impl.h
+++ b/content/browser/devtools/devtools_agent_host_impl.h
@@ -27,17 +27,22 @@
     virtual ~CloseListener() {}
   };
 
-  // Sends the message to the devtools agent hosted by this object.
-  void Attach();
-  void Reattach(const std::string& saved_agent_state);
-  void Detach();
-  virtual void DispatchOnInspectorBackend(const std::string& message);
+  // Informs the hosted agent that a client host has attached.
+  virtual void Attach() = 0;
+
+  // Informs the hosted agent that a client host has detached.
+  virtual void Detach() = 0;
+
+  // Sends a message to the agent hosted by this object.
+  virtual void DispatchOnInspectorBackend(const std::string& message) = 0;
 
   void set_close_listener(CloseListener* listener) {
     close_listener_ = listener;
   }
 
   // DevToolsAgentHost implementation.
+  virtual bool IsAttached() OVERRIDE;
+
   virtual void InspectElement(int x, int y) OVERRIDE;
 
   virtual std::string GetId() OVERRIDE;
@@ -48,10 +53,6 @@
   DevToolsAgentHostImpl();
   virtual ~DevToolsAgentHostImpl();
 
-  virtual void SendMessageToAgent(IPC::Message* msg) = 0;
-  virtual void NotifyClientAttaching() = 0;
-  virtual void NotifyClientDetaching() = 0;
-
   void NotifyCloseListener();
 
  private:
diff --git a/content/browser/devtools/devtools_browser_target.cc b/content/browser/devtools/devtools_browser_target.cc
index aa5e1ac..fc563fb 100644
--- a/content/browser/devtools/devtools_browser_target.cc
+++ b/content/browser/devtools/devtools_browser_target.cc
@@ -22,7 +22,7 @@
       http_server_(http_server),
       connection_id_(connection_id),
       handlers_deleter_(&handlers_),
-      ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) {
+      weak_factory_(this) {
 }
 
 DevToolsBrowserTarget::~DevToolsBrowserTarget() {
diff --git a/content/browser/devtools/devtools_external_agent_proxy_impl.cc b/content/browser/devtools/devtools_external_agent_proxy_impl.cc
new file mode 100644
index 0000000..5ecaa57
--- /dev/null
+++ b/content/browser/devtools/devtools_external_agent_proxy_impl.cc
@@ -0,0 +1,73 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/devtools/devtools_external_agent_proxy_impl.h"
+
+#include "content/browser/devtools/devtools_agent_host_impl.h"
+#include "content/browser/devtools/devtools_manager_impl.h"
+#include "content/public/browser/devtools_external_agent_proxy_delegate.h"
+
+namespace content {
+
+class DevToolsExternalAgentProxyImpl::ForwardingAgentHost
+    : public DevToolsAgentHostImpl {
+ public:
+  ForwardingAgentHost(DevToolsExternalAgentProxyDelegate* delegate)
+      : delegate_(delegate) {
+  }
+
+  void ConnectionClosed() {
+    NotifyCloseListener();
+  }
+
+ private:
+  virtual ~ForwardingAgentHost() {
+  }
+
+  // DevToolsAgentHostImpl implementation.
+  virtual void Attach() OVERRIDE {
+    delegate_->Attach();
+  };
+
+  virtual void Detach() OVERRIDE {
+    delegate_->Detach();
+  };
+
+  virtual void DispatchOnInspectorBackend(const std::string& message) OVERRIDE {
+    delegate_->SendMessageToBackend(message);
+  }
+
+  DevToolsExternalAgentProxyDelegate* delegate_;
+};
+
+//static
+DevToolsExternalAgentProxy* DevToolsExternalAgentProxy::Create(
+    DevToolsExternalAgentProxyDelegate* delegate) {
+  return new DevToolsExternalAgentProxyImpl(delegate);
+}
+
+DevToolsExternalAgentProxyImpl::DevToolsExternalAgentProxyImpl(
+    DevToolsExternalAgentProxyDelegate* delegate)
+    : agent_host_(new ForwardingAgentHost(delegate)) {
+}
+
+DevToolsExternalAgentProxyImpl::~DevToolsExternalAgentProxyImpl() {
+}
+
+scoped_refptr<DevToolsAgentHost> DevToolsExternalAgentProxyImpl::
+    GetAgentHost() {
+  return agent_host_;
+}
+
+void DevToolsExternalAgentProxyImpl::DispatchOnClientHost(
+    const std::string& message) {
+  DevToolsManagerImpl::GetInstance()->DispatchOnInspectorFrontend(
+      agent_host_, message);
+}
+
+void DevToolsExternalAgentProxyImpl::ConnectionClosed() {
+  agent_host_->ConnectionClosed();
+}
+
+}  // content
diff --git a/content/browser/devtools/devtools_external_agent_proxy_impl.h b/content/browser/devtools/devtools_external_agent_proxy_impl.h
new file mode 100644
index 0000000..cf025ec
--- /dev/null
+++ b/content/browser/devtools/devtools_external_agent_proxy_impl.h
@@ -0,0 +1,35 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_EXTERNAL_AGENT_PROXY_IMPL_H
+#define CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_EXTERNAL_AGENT_PROXY_IMPL_H
+
+#include "base/memory/ref_counted.h"
+#include "content/public/browser/devtools_external_agent_proxy.h"
+
+namespace content {
+
+class DevToolsExternalAgentProxyImpl
+    : public DevToolsExternalAgentProxy {
+ public:
+  explicit DevToolsExternalAgentProxyImpl(
+      DevToolsExternalAgentProxyDelegate* delegate);
+  virtual ~DevToolsExternalAgentProxyImpl();
+
+  // DevToolsExternalAgentProxy implementation.
+  virtual scoped_refptr<DevToolsAgentHost> GetAgentHost() OVERRIDE;
+  virtual void DispatchOnClientHost(const std::string& message) OVERRIDE;
+  virtual void ConnectionClosed() OVERRIDE;
+
+ private:
+  class ForwardingAgentHost;
+
+  scoped_refptr<ForwardingAgentHost> agent_host_;
+
+  DISALLOW_COPY_AND_ASSIGN(DevToolsExternalAgentProxyImpl);
+};
+
+}  // namespace content
+
+#endif  // CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_EXTERNAL_AGENT_PROXY_IMPL_H
diff --git a/content/browser/devtools/devtools_http_handler_impl.cc b/content/browser/devtools/devtools_http_handler_impl.cc
index cc43682..cea2156 100644
--- a/content/browser/devtools/devtools_http_handler_impl.cc
+++ b/content/browser/devtools/devtools_http_handler_impl.cc
@@ -14,12 +14,16 @@
 #include "base/lazy_instance.h"
 #include "base/logging.h"
 #include "base/message_loop_proxy.h"
+#include "base/stl_util.h"
 #include "base/string_number_conversions.h"
 #include "base/threading/thread.h"
 #include "base/utf_string_conversions.h"
 #include "base/values.h"
 #include "content/browser/devtools/devtools_browser_target.h"
+#include "content/browser/devtools/devtools_protocol.h"
+#include "content/browser/devtools/devtools_protocol_constants.h"
 #include "content/browser/devtools/devtools_tracing_handler.h"
+#include "content/browser/devtools/tethering_handler.h"
 #include "content/browser/web_contents/web_contents_impl.h"
 #include "content/common/devtools_messages.h"
 #include "content/public/browser/browser_thread.h"
@@ -89,16 +93,14 @@
 // messages sent for DevToolsClient to a DebuggerShell instance.
 class DevToolsClientHostImpl : public DevToolsClientHost {
  public:
-  DevToolsClientHostImpl(
-      MessageLoop* message_loop,
-      net::HttpServer* server,
-      int connection_id)
+  DevToolsClientHostImpl(base::MessageLoop* message_loop,
+                         net::HttpServer* server,
+                         int connection_id)
       : message_loop_(message_loop),
         server_(server),
         connection_id_(connection_id),
         is_closed_(false),
-        detach_reason_("target_closed") {
-  }
+        detach_reason_("target_closed") {}
 
   virtual ~DevToolsClientHostImpl() {}
 
@@ -108,9 +110,8 @@
       return;
     is_closed_ = true;
 
-    std::string response =
-        WebKit::WebDevToolsAgent::inspectorDetachedEvent(
-            WebKit::WebString::fromUTF8(detach_reason_)).utf8();
+    std::string response = DevToolsProtocol::CreateNotification(
+        devtools::Inspector::detached::kName, NULL)->Serialize();
     message_loop_->PostTask(
         FROM_HERE,
         base::Bind(&net::HttpServer::SendOverWebSocket,
@@ -137,7 +138,7 @@
   }
 
  private:
-  MessageLoop* message_loop_;
+  base::MessageLoop* message_loop_;
   net::HttpServer* server_;
   int connection_id_;
   bool is_closed_;
@@ -190,7 +191,7 @@
 }
 
 void DevToolsHttpHandlerImpl::Start() {
-  if (thread_.get())
+  if (thread_)
     return;
   thread_.reset(new base::Thread(kDevToolsHandlerThreadName));
   BrowserThread::PostTask(
@@ -201,7 +202,7 @@
 // Runs on FILE thread.
 void DevToolsHttpHandlerImpl::StartHandlerThread() {
   base::Thread::Options options;
-  options.message_loop_type = MessageLoop::TYPE_IO;
+  options.message_loop_type = base::MessageLoop::TYPE_IO;
   if (!thread_->StartWithOptions(options)) {
     BrowserThread::PostTask(
         BrowserThread::UI, FROM_HERE,
@@ -224,7 +225,7 @@
 }
 
 void DevToolsHttpHandlerImpl::Stop() {
-  if (!thread_.get())
+  if (!thread_)
     return;
   BrowserThread::PostTaskAndReply(
       BrowserThread::FILE, FROM_HERE,
@@ -367,6 +368,30 @@
 void DevToolsHttpHandlerImpl::OnWebSocketMessage(
     int connection_id,
     const std::string& data) {
+  std::string error_response;
+  scoped_ptr<DevToolsProtocol::Command> command(
+      DevToolsProtocol::ParseCommand(data, &error_response));
+  if (command && command->domain() == TetheringHandler::kDomain) {
+    TetheringHandlers::iterator it = tethering_handlers_.find(connection_id);
+    TetheringHandler* tethering_handler;
+    if (it == tethering_handlers_.end()) {
+      tethering_handler = new TetheringHandler(delegate_.get());
+      tethering_handlers_[connection_id] = tethering_handler;
+      tethering_handler->SetNotifier(
+          base::Bind(&net::HttpServer::SendOverWebSocket,
+                     server_,
+                     connection_id));
+    } else {
+      tethering_handler = it->second;
+    }
+    scoped_ptr<DevToolsProtocol::Response> response(
+        tethering_handler->HandleCommand(command.get()));
+    if (!response)
+      response = command->NoSuchMethodErrorResponse();
+    server_->SendOverWebSocket(connection_id, response->Serialize());
+    return;
+  }
+
   BrowserThread::PostTask(
       BrowserThread::UI,
       FROM_HERE,
@@ -378,6 +403,12 @@
 }
 
 void DevToolsHttpHandlerImpl::OnClose(int connection_id) {
+  TetheringHandlers::iterator it = tethering_handlers_.find(connection_id);
+  if (it != tethering_handlers_.end()) {
+    delete it->second;
+    tethering_handlers_.erase(connection_id);
+  }
+
   BrowserThread::PostTask(
       BrowserThread::UI,
       FROM_HERE,
@@ -459,7 +490,7 @@
                       content::GetContentClient()->GetProduct());
     version.SetString("User-Agent",
                       webkit_glue::GetUserAgent(GURL(chrome::kAboutBlankURL)));
-    SendJson(connection_id, net::HTTP_OK, &version, "");
+    SendJson(connection_id, net::HTTP_OK, &version, std::string());
     return;
   }
 
@@ -506,7 +537,7 @@
     }
     std::string host = info.headers["Host"];
     scoped_ptr<base::DictionaryValue> dictionary(SerializePageInfo(rvh, host));
-    SendJson(connection_id, net::HTTP_OK, dictionary.get(), "");
+    SendJson(connection_id, net::HTTP_OK, dictionary.get(), std::string());
     return;
   }
 
@@ -552,7 +583,7 @@
 
 void DevToolsHttpHandlerImpl::SendTargetList(int connection_id,
                                              ListValue* target_list) {
-  SendJson(connection_id, net::HTTP_OK, target_list, "");
+  SendJson(connection_id, net::HTTP_OK, target_list, std::string());
   delete target_list;
   Release();  // Balanced OnJsonRequestUI.
 }
@@ -574,7 +605,7 @@
 void DevToolsHttpHandlerImpl::OnWebSocketRequestUI(
     int connection_id,
     const net::HttpServerRequestInfo& request) {
-  if (!thread_.get())
+  if (!thread_)
     return;
   std::string browser_prefix = "/devtools/browser";
   size_t browser_pos = request.path.find(browser_prefix);
@@ -604,8 +635,7 @@
     return;
   }
 
-  DevToolsManager* manager = DevToolsManager::GetInstance();
-  if (manager->GetDevToolsClientHostFor(agent)) {
+  if (agent->IsAttached()) {
     Send500(connection_id,
             "Target with given id is being inspected: " + page_id);
     return;
@@ -617,7 +647,8 @@
                                  connection_id);
   connection_to_client_host_ui_[connection_id] = client_host;
 
-  manager->RegisterDevToolsClientHostFor(agent, client_host);
+  DevToolsManager::GetInstance()->
+      RegisterDevToolsClientHostFor(agent, client_host);
 
   AcceptWebSocket(connection_id, request);
 }
@@ -686,6 +717,8 @@
 
 // Runs on the handler thread
 void DevToolsHttpHandlerImpl::Teardown() {
+  STLDeleteContainerPairSecondPointers(tethering_handlers_.begin(),
+                                       tethering_handlers_.end());
   server_ = NULL;
 }
 
@@ -705,7 +738,7 @@
                                        net::HttpStatusCode status_code,
                                        base::Value* value,
                                        const std::string& message) {
-  if (!thread_.get())
+  if (!thread_)
     return;
 
   // Serialize value and message.
@@ -737,7 +770,7 @@
 void DevToolsHttpHandlerImpl::Send200(int connection_id,
                                       const std::string& data,
                                       const std::string& mime_type) {
-  if (!thread_.get())
+  if (!thread_)
     return;
   thread_->message_loop()->PostTask(
       FROM_HERE,
@@ -749,7 +782,7 @@
 }
 
 void DevToolsHttpHandlerImpl::Send404(int connection_id) {
-  if (!thread_.get())
+  if (!thread_)
     return;
   thread_->message_loop()->PostTask(
       FROM_HERE,
@@ -758,7 +791,7 @@
 
 void DevToolsHttpHandlerImpl::Send500(int connection_id,
                                       const std::string& message) {
-  if (!thread_.get())
+  if (!thread_)
     return;
   thread_->message_loop()->PostTask(
       FROM_HERE,
@@ -769,7 +802,7 @@
 void DevToolsHttpHandlerImpl::AcceptWebSocket(
     int connection_id,
     const net::HttpServerRequestInfo& request) {
-  if (!thread_.get())
+  if (!thread_)
     return;
   thread_->message_loop()->PostTask(
       FROM_HERE,
@@ -814,7 +847,7 @@
   dictionary->SetString(kTargetDescriptionField,
       delegate_->GetViewDescription(rvh));
 
-  if (!DevToolsManager::GetInstance()->GetDevToolsClientHostFor(agent))
+  if (!agent->IsAttached())
     SerializeDebuggerURLs(dictionary, id, host);
   return dictionary;
 }
@@ -837,7 +870,7 @@
   dictionary->SetString(kTargetDescriptionField,
       base::StringPrintf("Worker pid:%d", base::GetProcId(worker.handle)));
 
-  if (!DevToolsManager::GetInstance()->GetDevToolsClientHostFor(agent))
+  if (!agent->IsAttached())
     SerializeDebuggerURLs(dictionary, id, host);
   return dictionary;
 }
diff --git a/content/browser/devtools/devtools_http_handler_impl.h b/content/browser/devtools/devtools_http_handler_impl.h
index ce2688b..76820e8 100644
--- a/content/browser/devtools/devtools_http_handler_impl.h
+++ b/content/browser/devtools/devtools_http_handler_impl.h
@@ -34,6 +34,7 @@
 
 class DevToolsBrowserTarget;
 class DevToolsClientHost;
+class TetheringHandler;
 
 class DevToolsHttpHandlerImpl
     : public DevToolsHttpHandler,
@@ -128,6 +129,8 @@
   DevToolsAgentHostBinding* binding_;
   scoped_ptr<DevToolsAgentHostBinding> default_binding_;
   scoped_ptr<DevToolsBrowserTarget> browser_target_;
+  typedef std::map<int, TetheringHandler*> TetheringHandlers;
+  TetheringHandlers tethering_handlers_;
   DISALLOW_COPY_AND_ASSIGN(DevToolsHttpHandlerImpl);
 };
 
diff --git a/content/browser/devtools/devtools_http_handler_unittest.cc b/content/browser/devtools/devtools_http_handler_unittest.cc
index 56f3277..9441c83 100644
--- a/content/browser/devtools/devtools_http_handler_unittest.cc
+++ b/content/browser/devtools/devtools_http_handler_unittest.cc
@@ -7,7 +7,7 @@
 #include "content/browser/browser_thread_impl.h"
 #include "content/public/browser/devtools_http_handler.h"
 #include "content/public/browser/devtools_http_handler_delegate.h"
-#include "net/base/stream_listen_socket.h"
+#include "net/socket/stream_listen_socket.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace content {
@@ -19,7 +19,7 @@
                           public StreamListenSocket::Delegate {
  public:
   DummyListenSocket()
-      : ALLOW_THIS_IN_INITIALIZER_LIST(StreamListenSocket(0, this)) {}
+      : StreamListenSocket(0, this) {}
 
   // StreamListenSocket::Delegate "implementation"
   virtual void DidAccept(StreamListenSocket* server,
@@ -56,20 +56,25 @@
 
 class DummyDelegate : public DevToolsHttpHandlerDelegate {
  public:
-  virtual std::string GetDiscoveryPageHTML() OVERRIDE { return ""; }
+  virtual std::string GetDiscoveryPageHTML() OVERRIDE { return std::string(); }
   virtual bool BundlesFrontendResources() OVERRIDE { return true; }
   virtual base::FilePath GetDebugFrontendDir() OVERRIDE {
     return base::FilePath();
   }
   virtual std::string GetPageThumbnailData(const GURL& url) OVERRIDE {
-    return "";
+    return std::string();
   }
   virtual RenderViewHost* CreateNewTarget() OVERRIDE { return NULL; }
   virtual TargetType GetTargetType(RenderViewHost*) OVERRIDE {
     return kTargetTypeTab;
   }
   virtual std::string GetViewDescription(content::RenderViewHost*) OVERRIDE {
-    return "";
+    return std::string();
+  }
+  virtual scoped_refptr<net::StreamListenSocket> CreateSocketForTethering(
+    net::StreamListenSocket::Delegate* delegate,
+    std::string* name) OVERRIDE {
+    return NULL;
   }
 };
 
@@ -89,7 +94,7 @@
     file_thread_->Stop();
   }
  private:
-  MessageLoopForIO message_loop_;
+  base::MessageLoopForIO message_loop_;
   BrowserThreadImpl ui_thread_;
   scoped_ptr<BrowserThreadImpl> file_thread_;
 };
@@ -98,9 +103,9 @@
   base::RunLoop run_loop, run_loop_2;
   content::DevToolsHttpHandler* devtools_http_handler_ =
       content::DevToolsHttpHandler::Start(
-          new DummyListenSocketFactory(
-              run_loop.QuitClosure(), run_loop_2.QuitClosure()),
-          "",
+          new DummyListenSocketFactory(run_loop.QuitClosure(),
+                                       run_loop_2.QuitClosure()),
+          std::string(),
           new DummyDelegate());
   // Our dummy socket factory will post a quit message once the server will
   // become ready.
diff --git a/content/browser/devtools/devtools_manager_impl.cc b/content/browser/devtools/devtools_manager_impl.cc
index 4ae34da..753340b 100644
--- a/content/browser/devtools/devtools_manager_impl.cc
+++ b/content/browser/devtools/devtools_manager_impl.cc
@@ -37,9 +37,7 @@
 }
 
 DevToolsClientHost* DevToolsManagerImpl::GetDevToolsClientHostFor(
-    DevToolsAgentHost* agent_host) {
-  DevToolsAgentHostImpl* agent_host_impl =
-      static_cast<DevToolsAgentHostImpl*>(agent_host);
+    DevToolsAgentHostImpl* agent_host_impl) {
   AgentToClientHostMap::iterator it =
       agent_to_client_host_.find(agent_host_impl);
   if (it != agent_to_client_host_.end())
@@ -60,6 +58,12 @@
     DevToolsClientHost* client_host) {
   DevToolsAgentHostImpl* agent_host_impl =
       static_cast<DevToolsAgentHostImpl*>(agent_host);
+  DevToolsClientHost* old_client_host =
+      GetDevToolsClientHostFor(agent_host_impl);
+  if (old_client_host) {
+    old_client_host->ReplacedWithAnotherClient();
+    UnregisterDevToolsClientHostFor(agent_host_impl);
+  }
   BindClientHost(agent_host_impl, client_host);
   agent_host_impl->Attach();
 }
@@ -79,7 +83,9 @@
 void DevToolsManagerImpl::DispatchOnInspectorFrontend(
     DevToolsAgentHost* agent_host,
     const std::string& message) {
-  DevToolsClientHost* client_host = GetDevToolsClientHostFor(agent_host);
+  DevToolsAgentHostImpl* agent_host_impl =
+      static_cast<DevToolsAgentHostImpl*>(agent_host);
+  DevToolsClientHost* client_host = GetDevToolsClientHostFor(agent_host_impl);
   if (!client_host) {
     // Client window was closed while there were messages
     // being sent to it.
@@ -102,12 +108,10 @@
 }
 
 void DevToolsManagerImpl::UnregisterDevToolsClientHostFor(
-    DevToolsAgentHost* agent_host) {
-  DevToolsClientHost* client_host = GetDevToolsClientHostFor(agent_host);
+    DevToolsAgentHostImpl* agent_host_impl) {
+  DevToolsClientHost* client_host = GetDevToolsClientHostFor(agent_host_impl);
   if (!client_host)
     return;
-  DevToolsAgentHostImpl* agent_host_impl =
-      static_cast<DevToolsAgentHostImpl*>(agent_host);
   UnbindClientHost(agent_host_impl, client_host);
   client_host->InspectedContentsClosing();
 }
@@ -129,6 +133,7 @@
   agent_to_client_host_[agent_host] = client_host;
   client_to_agent_host_[client_host] = agent_host;
   agent_host->set_close_listener(this);
+  NotifyObservers(agent_host, true);
 }
 
 void DevToolsManagerImpl::UnbindClientHost(DevToolsAgentHostImpl* agent_host,
@@ -150,22 +155,41 @@
         FROM_HERE,
         base::Bind(&DevToolsNetLogObserver::Detach));
   }
+  NotifyObservers(agent_host, false);
   // Lazy agent hosts can be deleted from within detach.
   // Do not access agent_host below this line.
   agent_host->Detach();
 }
 
 void DevToolsManagerImpl::CloseAllClientHosts() {
-  std::vector<DevToolsAgentHost*> agents;
+  std::vector<DevToolsAgentHostImpl*> agents;
   for (AgentToClientHostMap::iterator it =
            agent_to_client_host_.begin();
        it != agent_to_client_host_.end(); ++it) {
     agents.push_back(it->first);
   }
-  for (std::vector<DevToolsAgentHost*>::iterator it = agents.begin();
+  for (std::vector<DevToolsAgentHostImpl*>::iterator it = agents.begin();
        it != agents.end(); ++it) {
     UnregisterDevToolsClientHostFor(*it);
   }
 }
 
+void DevToolsManagerImpl::AddAgentStateCallback(const Callback& callback) {
+  callbacks_.push_back(&callback);
+}
+
+void DevToolsManagerImpl::RemoveAgentStateCallback(const Callback& callback) {
+  CallbackContainer::iterator it =
+      std::find(callbacks_.begin(), callbacks_.end(), &callback);
+  DCHECK(it != callbacks_.end());
+  callbacks_.erase(it);
+}
+
+void DevToolsManagerImpl::NotifyObservers(DevToolsAgentHost* agent_host,
+                                          bool attached) {
+  CallbackContainer copy(callbacks_);
+  for (CallbackContainer::iterator it = copy.begin(); it != copy.end(); ++it)
+     (*it)->Run(agent_host, attached);
+}
+
 }  // namespace content
diff --git a/content/browser/devtools/devtools_manager_impl.h b/content/browser/devtools/devtools_manager_impl.h
index 6e1607c..3232bc1 100644
--- a/content/browser/devtools/devtools_manager_impl.h
+++ b/content/browser/devtools/devtools_manager_impl.h
@@ -7,6 +7,7 @@
 
 #include <map>
 #include <string>
+#include <vector>
 
 #include "base/compiler_specific.h"
 #include "base/memory/singleton.h"
@@ -49,18 +50,17 @@
   virtual bool DispatchOnInspectorBackend(DevToolsClientHost* from,
                                           const std::string& message) OVERRIDE;
   virtual void CloseAllClientHosts() OVERRIDE;
-  virtual DevToolsClientHost* GetDevToolsClientHostFor(
-      DevToolsAgentHost* agent_host) OVERRIDE;
   virtual DevToolsAgentHost* GetDevToolsAgentHostFor(
       DevToolsClientHost* client_host) OVERRIDE;
   virtual void RegisterDevToolsClientHostFor(
       DevToolsAgentHost* agent_host,
       DevToolsClientHost* client_host) OVERRIDE;
-  virtual void UnregisterDevToolsClientHostFor(
-      DevToolsAgentHost* agent_host) OVERRIDE;
   virtual void ClientHostClosing(DevToolsClientHost* host) OVERRIDE;
+  virtual void AddAgentStateCallback(const Callback& callback) OVERRIDE;
+  virtual void RemoveAgentStateCallback(const Callback& callback) OVERRIDE;
 
  private:
+  friend class DevToolsAgentHostImpl;
   friend struct DefaultSingletonTraits<DevToolsManagerImpl>;
 
   // DevToolsAgentHost::CloseListener implementation.
@@ -71,6 +71,13 @@
   void UnbindClientHost(DevToolsAgentHostImpl* agent_host,
                         DevToolsClientHost* client_host);
 
+  DevToolsClientHost* GetDevToolsClientHostFor(
+      DevToolsAgentHostImpl* agent_host);
+
+  void UnregisterDevToolsClientHostFor(DevToolsAgentHostImpl* agent_host);
+
+  void NotifyObservers(DevToolsAgentHost* agent_host, bool attached);
+
   // These two maps are for tracking dependencies between inspected contents and
   // their DevToolsClientHosts. They are useful for routing devtools messages
   // and allow us to have at most one devtools client host per contents.
@@ -85,6 +92,9 @@
       ClientToAgentHostMap;
   ClientToAgentHostMap client_to_agent_host_;
 
+  typedef std::vector<const Callback*> CallbackContainer;
+  CallbackContainer callbacks_;
+
   DISALLOW_COPY_AND_ASSIGN(DevToolsManagerImpl);
 };
 
diff --git a/content/browser/devtools/devtools_manager_unittest.cc b/content/browser/devtools/devtools_manager_unittest.cc
index deac3c1..6923a93 100644
--- a/content/browser/devtools/devtools_manager_unittest.cc
+++ b/content/browser/devtools/devtools_manager_unittest.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "base/basictypes.h"
+#include "base/memory/scoped_ptr.h"
 #include "base/time.h"
 #include "content/browser/devtools/devtools_manager_impl.h"
 #include "content/browser/devtools/render_view_devtools_agent_host.h"
@@ -11,6 +12,8 @@
 #include "content/public/browser/content_browser_client.h"
 #include "content/public/browser/devtools_agent_host.h"
 #include "content/public/browser/devtools_client_host.h"
+#include "content/public/browser/devtools_external_agent_proxy.h"
+#include "content/public/browser/devtools_external_agent_proxy_delegate.h"
 #include "content/public/browser/web_contents_delegate.h"
 #include "content/test/test_content_browser_client.h"
 #include "content/test/test_web_contents.h"
@@ -109,8 +112,7 @@
 
  protected:
   virtual void SetUp() OVERRIDE {
-    original_browser_client_ = GetContentClient()->browser();
-    GetContentClient()->set_browser_for_testing(&browser_client_);
+    original_browser_client_ = SetBrowserClientForTesting(&browser_client_);
 
     RenderViewHostImplTestHarness::SetUp();
     TestDevToolsClientHost::ResetCounters();
@@ -118,7 +120,7 @@
 
   virtual void TearDown() OVERRIDE {
     RenderViewHostImplTestHarness::TearDown();
-    GetContentClient()->set_browser_for_testing(original_browser_client_);
+    SetBrowserClientForTesting(original_browser_client_);
   }
 
  private:
@@ -127,46 +129,39 @@
 };
 
 TEST_F(DevToolsManagerTest, OpenAndManuallyCloseDevToolsClientHost) {
-  DevToolsManagerImpl manager;
+  DevToolsManager* manager = DevToolsManager::GetInstance();
 
   scoped_refptr<DevToolsAgentHost> agent(
       DevToolsAgentHost::GetOrCreateFor(rvh()));
-  DevToolsClientHost* host = manager.GetDevToolsClientHostFor(agent);
-  EXPECT_TRUE(NULL == host);
+  EXPECT_FALSE(agent->IsAttached());
 
   TestDevToolsClientHost client_host;
-  manager.RegisterDevToolsClientHostFor(agent, &client_host);
-  // Test that just registered devtools host is returned.
-  host = manager.GetDevToolsClientHostFor(agent);
-  EXPECT_TRUE(&client_host == host);
+  manager->RegisterDevToolsClientHostFor(agent, &client_host);
+  // Test that the connection is established.
+  EXPECT_TRUE(agent->IsAttached());
+  EXPECT_EQ(agent, manager->GetDevToolsAgentHostFor(&client_host));
   EXPECT_EQ(0, TestDevToolsClientHost::close_counter);
 
-  // Test that the same devtools host is returned.
-  host = manager.GetDevToolsClientHostFor(agent);
-  EXPECT_TRUE(&client_host == host);
-  EXPECT_EQ(0, TestDevToolsClientHost::close_counter);
-
-  client_host.Close(&manager);
+  client_host.Close(manager);
   EXPECT_EQ(1, TestDevToolsClientHost::close_counter);
-  host = manager.GetDevToolsClientHostFor(agent);
-  EXPECT_TRUE(NULL == host);
+  EXPECT_FALSE(agent->IsAttached());
 }
 
 TEST_F(DevToolsManagerTest, ForwardMessageToClient) {
-  DevToolsManagerImpl manager;
+  DevToolsManagerImpl* manager = DevToolsManagerImpl::GetInstance();
 
   TestDevToolsClientHost client_host;
   scoped_refptr<DevToolsAgentHost> agent_host(
       DevToolsAgentHost::GetOrCreateFor(rvh()));
-  manager.RegisterDevToolsClientHostFor(agent_host, &client_host);
+  manager->RegisterDevToolsClientHostFor(agent_host, &client_host);
   EXPECT_EQ(0, TestDevToolsClientHost::close_counter);
 
   std::string m = "test message";
   agent_host = DevToolsAgentHost::GetOrCreateFor(rvh());
-  manager.DispatchOnInspectorFrontend(agent_host, m);
+  manager->DispatchOnInspectorFrontend(agent_host, m);
   EXPECT_TRUE(&m == client_host.last_sent_message);
 
-  client_host.Close(&manager);
+  client_host.Close(manager);
   EXPECT_EQ(1, TestDevToolsClientHost::close_counter);
 }
 
@@ -186,9 +181,11 @@
   // Start with a short timeout.
   inspected_rvh->StartHangMonitorTimeout(TimeDelta::FromMilliseconds(10));
   // Wait long enough for first timeout and see if it fired.
-  MessageLoop::current()->PostDelayedTask(
-      FROM_HERE, MessageLoop::QuitClosure(), TimeDelta::FromMilliseconds(10));
-  MessageLoop::current()->Run();
+  base::MessageLoop::current()->PostDelayedTask(
+      FROM_HERE,
+      base::MessageLoop::QuitClosure(),
+      TimeDelta::FromMilliseconds(10));
+  base::MessageLoop::current()->Run();
   EXPECT_FALSE(delegate.renderer_unresponsive_received());
 
   // Now close devtools and check that the notification is delivered.
@@ -196,9 +193,11 @@
   // Start with a short timeout.
   inspected_rvh->StartHangMonitorTimeout(TimeDelta::FromMilliseconds(10));
   // Wait long enough for first timeout and see if it fired.
-  MessageLoop::current()->PostDelayedTask(
-      FROM_HERE, MessageLoop::QuitClosure(), TimeDelta::FromMilliseconds(10));
-  MessageLoop::current()->Run();
+  base::MessageLoop::current()->PostDelayedTask(
+      FROM_HERE,
+      base::MessageLoop::QuitClosure(),
+      TimeDelta::FromMilliseconds(10));
+  base::MessageLoop::current()->Run();
   EXPECT_TRUE(delegate.renderer_unresponsive_received());
 
   contents()->SetDelegate(NULL);
@@ -224,17 +223,73 @@
   controller().LoadURL(
       url2, Referrer(), PAGE_TRANSITION_TYPED, std::string());
   EXPECT_TRUE(contents()->cross_navigation_pending());
-  EXPECT_EQ(&client_host, devtools_manager->GetDevToolsClientHostFor(
-      DevToolsAgentHost::GetOrCreateFor(pending_rvh())));
+  EXPECT_EQ(devtools_manager->GetDevToolsAgentHostFor(&client_host),
+      DevToolsAgentHost::GetOrCreateFor(pending_rvh()));
 
   // Interrupt pending navigation and navigate back to the original site.
   controller().LoadURL(
       url, Referrer(), PAGE_TRANSITION_TYPED, std::string());
   contents()->TestDidNavigate(rvh(), 1, url, PAGE_TRANSITION_TYPED);
   EXPECT_FALSE(contents()->cross_navigation_pending());
-  EXPECT_EQ(&client_host, devtools_manager->GetDevToolsClientHostFor(
-      DevToolsAgentHost::GetOrCreateFor(rvh())));
+  EXPECT_EQ(devtools_manager->GetDevToolsAgentHostFor(&client_host),
+      DevToolsAgentHost::GetOrCreateFor(rvh()));
   client_host.Close(DevToolsManager::GetInstance());
 }
 
+class TestExternalAgentDelegate: public DevToolsExternalAgentProxyDelegate {
+  std::map<std::string,int> event_counter_;
+
+  void recordEvent(const std::string& name) {
+    if (event_counter_.find(name) == event_counter_.end())
+      event_counter_[name] = 0;
+    event_counter_[name] = event_counter_[name] + 1;
+  }
+
+  void expectEvent(int count, const std::string& name) {
+    EXPECT_EQ(count, event_counter_[name]);
+  }
+
+  virtual void Attach() OVERRIDE {
+    recordEvent("Attach");
+  };
+
+  virtual void Detach() OVERRIDE {
+    recordEvent("Detach");
+  };
+
+  virtual void SendMessageToBackend(const std::string& message) OVERRIDE {
+    recordEvent(std::string("SendMessageToBackend.") + message);
+  };
+
+ public :
+  virtual ~TestExternalAgentDelegate() {
+    expectEvent(1, "Attach");
+    expectEvent(1, "Detach");
+    expectEvent(0, "SendMessageToBackend.message0");
+    expectEvent(1, "SendMessageToBackend.message1");
+    expectEvent(2, "SendMessageToBackend.message2");
+  }
+};
+
+TEST_F(DevToolsManagerTest, TestExternalProxy) {
+  TestExternalAgentDelegate delegate;
+
+  scoped_ptr<DevToolsExternalAgentProxy> proxy(
+      DevToolsExternalAgentProxy::Create(&delegate));
+
+  scoped_refptr<DevToolsAgentHost> agent_host = proxy->GetAgentHost();
+  EXPECT_EQ(agent_host, DevToolsAgentHost::GetForId(agent_host->GetId()));
+
+  DevToolsManager* manager = DevToolsManager::GetInstance();
+
+  TestDevToolsClientHost client_host;
+  manager->RegisterDevToolsClientHostFor(agent_host, &client_host);
+
+  manager->DispatchOnInspectorBackend(&client_host, "message1");
+  manager->DispatchOnInspectorBackend(&client_host, "message2");
+  manager->DispatchOnInspectorBackend(&client_host, "message2");
+
+  client_host.Close(manager);
+}
+
 }  // namespace content
diff --git a/content/browser/devtools/devtools_protocol.cc b/content/browser/devtools/devtools_protocol.cc
index 28d6fe8..1ef3085 100644
--- a/content/browser/devtools/devtools_protocol.cc
+++ b/content/browser/devtools/devtools_protocol.cc
@@ -6,6 +6,7 @@
 
 #include "base/json/json_reader.h"
 #include "base/json/json_writer.h"
+#include "base/stringprintf.h"
 
 namespace content {
 
@@ -20,25 +21,65 @@
 const char kErrorMessageParam[] = "message";
 const int kNoId = -1;
 
+// JSON RPC 2.0 spec: http://www.jsonrpc.org/specification#error_object
+enum Error {
+  kErrorParseError = -32700,
+  kErrorInvalidRequest = -32600,
+  kErrorNoSuchMethod = -32601,
+  kErrorInvalidParams = -32602,
+  kErrorInternalError = -32603
+};
+
 }  // namespace
 
 using base::DictionaryValue;
 using base::Value;
 
+DevToolsProtocol::Message::~Message() {
+}
+
+DevToolsProtocol::Message::Message(const std::string& method,
+                                   DictionaryValue* params)
+    : method_(method),
+      params_(params) {
+  size_t pos = method.find(".");
+  if (pos != std::string::npos && pos > 0)
+    domain_ = method.substr(0, pos);
+}
+
 DevToolsProtocol::Command::~Command() {
 }
 
+std::string DevToolsProtocol::Command::Serialize() {
+  DictionaryValue command;
+  command.SetInteger(kIdParam, id_);
+  command.SetString(kMethodParam, method_);
+  if (params_)
+    command.Set(kParamsParam, params_->DeepCopy());
+
+  std::string json_command;
+  base::JSONWriter::Write(&command, &json_command);
+  return json_command;
+}
+
 scoped_ptr<DevToolsProtocol::Response>
-DevToolsProtocol::Command::SuccessResponse(base::DictionaryValue* result) {
+DevToolsProtocol::Command::SuccessResponse(DictionaryValue* result) {
   return scoped_ptr<DevToolsProtocol::Response>(
       new DevToolsProtocol::Response(id_, result));
 }
 
 scoped_ptr<DevToolsProtocol::Response>
-DevToolsProtocol::Command::ErrorResponse(int error_code,
-                                         const std::string& error_message) {
+DevToolsProtocol::Command::InternalErrorResponse(const std::string& message) {
   return scoped_ptr<DevToolsProtocol::Response>(
-      new DevToolsProtocol::Response(id_, error_code, error_message));
+      new DevToolsProtocol::Response(id_, kErrorInternalError, message));
+}
+
+scoped_ptr<DevToolsProtocol::Response>
+DevToolsProtocol::Command::InvalidParamResponse(const std::string& param) {
+  std::string message =
+      base::StringPrintf("Missing or invalid '%s' parameter", param.c_str());
+  return scoped_ptr<DevToolsProtocol::Response>(
+      new DevToolsProtocol::Response(id_, kErrorInvalidParams, message));
 }
 
 scoped_ptr<DevToolsProtocol::Response>
@@ -48,13 +89,10 @@
 }
 
 DevToolsProtocol::Command::Command(int id,
-                                   const std::string& domain,
                                    const std::string& method,
                                    DictionaryValue* params)
-    : id_(id),
-      domain_(domain),
-      method_(method),
-      params_(params) {
+    : Message(method, params),
+      id_(id) {
 }
 
 std::string DevToolsProtocol::Response::Serialize() {
@@ -69,7 +107,7 @@
     error_object->SetInteger(kErrorCodeParam, error_code_);
     if (!error_message_.empty())
       error_object->SetString(kErrorMessageParam, error_message_);
-  } else if (result_.get()) {
+  } else if (result_) {
     response.Set(kResultParam, result_->DeepCopy());
   }
 
@@ -98,19 +136,16 @@
 
 DevToolsProtocol::Notification::Notification(const std::string& method,
                                              DictionaryValue* params)
-    : method_(method),
-      params_(params) {
+    : Message(method, params) {
 }
 
 DevToolsProtocol::Notification::~Notification() {
 }
 
 std::string DevToolsProtocol::Notification::Serialize() {
-  DictionaryValue response;
-
-  base::DictionaryValue notification;
+  DictionaryValue notification;
   notification.SetString(kMethodParam, method_);
-  if (params_.get())
+  if (params_)
     notification.Set(kParamsParam, params_->DeepCopy());
 
   std::string json_notification;
@@ -118,27 +153,6 @@
   return json_notification;
 }
 
-DevToolsProtocol::Event::~Event() {
-}
-
-std::string DevToolsProtocol::Event::Serialize() {
-  DictionaryValue dictionary;
-
-  dictionary.SetString(kMethodParam, method_);
-  if (params_)
-    dictionary.Set(kParamsParam, params_->DeepCopy());
-
-  std::string result;
-  base::JSONWriter::Write(&dictionary, &result);
-  return result;
-}
-
-DevToolsProtocol::Event::Event(const std::string& method,
-                               DictionaryValue* params)
-    : method_(method),
-      params_(params) {
-}
-
 DevToolsProtocol::Handler::~Handler() {
 }
 
@@ -166,62 +180,87 @@
 
 void DevToolsProtocol::Handler::SendNotification(
     const std::string& method,
-    base::DictionaryValue* params) {
+    DictionaryValue* params) {
   DevToolsProtocol::Notification notification(method, params);
   if (!notifier_.is_null())
     notifier_.Run(notification.Serialize());
 }
 
+static bool ParseMethod(DictionaryValue* command,
+                        std::string* method) {
+  if (!command->GetString(kMethodParam, method))
+    return false;
+  size_t pos = method->find(".");
+  if (pos == std::string::npos || pos == 0)
+    return false;
+  return true;
+}
+
 // static
 DevToolsProtocol::Command* DevToolsProtocol::ParseCommand(
     const std::string& json,
     std::string* error_response) {
-  int parse_error_code;
-  std::string error_message;
-  scoped_ptr<base::Value> command(
-      base::JSONReader::ReadAndReturnError(
-          json, 0, &parse_error_code, &error_message));
-
-  if (!command || !command->IsType(base::Value::TYPE_DICTIONARY)) {
-    Response response(0, kErrorParseError, error_message);
-    *error_response = response.Serialize();
+  scoped_ptr<DictionaryValue> command_dict(ParseMessage(json, error_response));
+  if (!command_dict)
     return NULL;
-  }
-
-  base::DictionaryValue* command_dict = NULL;
-  command->GetAsDictionary(&command_dict);
 
   int id;
   std::string method;
-  bool ok = true;
-  ok &= command_dict->GetInteger(kIdParam, &id);
-  ok &= id >= 0;
-  ok &= command_dict->GetString(kMethodParam, &method);
+  bool ok = command_dict->GetInteger(kIdParam, &id) && id >= 0;
+  ok = ok && ParseMethod(command_dict.get(), &method);
   if (!ok) {
-    Response response(kNoId, kErrorInvalidRequest, "Invalid request");
+    Response response(kNoId, kErrorInvalidRequest, "No such method");
     *error_response = response.Serialize();
     return NULL;
   }
 
-  size_t pos = method.find(".");
-  if (pos == std::string::npos || pos == 0) {
-    Response response(id, kErrorNoSuchMethod, "No such method");
-    *error_response = response.Serialize();
-    return NULL;
-  }
-
-  std::string domain = method.substr(0, pos);
-
-  base::DictionaryValue* params = NULL;
+  DictionaryValue* params = NULL;
   command_dict->GetDictionary(kParamsParam, &params);
-  return new Command(id, domain, method, params ? params->DeepCopy() : NULL);
+  return new Command(id, method, params ? params->DeepCopy() : NULL);
+}
+
+// static
+DevToolsProtocol::Notification*
+DevToolsProtocol::ParseNotification(const std::string& json) {
+  scoped_ptr<DictionaryValue> dict(ParseMessage(json, NULL));
+  if (!dict)
+    return NULL;
+
+  std::string method;
+  bool ok = ParseMethod(dict.get(), &method);
+  if (!ok)
+    return NULL;
+
+  DictionaryValue* params = NULL;
+  dict->GetDictionary(kParamsParam, &params);
+  return new Notification(method, params ? params->DeepCopy() : NULL);
 }
 
 //static
-DevToolsProtocol::Event* DevToolsProtocol::CreateEvent(
+DevToolsProtocol::Notification* DevToolsProtocol::CreateNotification(
     const std::string& method,
-    base::DictionaryValue* params) {
-  return new Event(method, params);
+    DictionaryValue* params) {
+  return new Notification(method, params);
+}
+
+// static
+DictionaryValue* DevToolsProtocol::ParseMessage(
+    const std::string& json,
+    std::string* error_response) {
+  int parse_error_code;
+  std::string error_message;
+  scoped_ptr<Value> message(
+      base::JSONReader::ReadAndReturnError(
+          json, 0, &parse_error_code, &error_message));
+
+  if (!message || !message->IsType(Value::TYPE_DICTIONARY)) {
+    Response response(0, kErrorParseError, error_message);
+    if (error_response)
+      *error_response = response.Serialize();
+    return NULL;
+  }
+
+  return static_cast<DictionaryValue*>(message.release());
 }
 
 }  // namespace content
diff --git a/content/browser/devtools/devtools_protocol.h b/content/browser/devtools/devtools_protocol.h
index 9755476..a2ef7db 100644
--- a/content/browser/devtools/devtools_protocol.h
+++ b/content/browser/devtools/devtools_protocol.h
@@ -21,45 +21,55 @@
  public:
   typedef base::Callback<void(const std::string& message)> Notifier;
 
-  // JSON RPC 2.0 spec: http://www.jsonrpc.org/specification#error_object
-  enum Error {
-    kErrorParseError = -32700,
-    kErrorInvalidRequest = -32600,
-    kErrorNoSuchMethod = -32601,
-    kErrorInvalidParams = -32602,
-    kErrorInternalError = -32603
-  };
-
   class Response;
 
-  class Command {
+  class Message {
    public:
-    ~Command();
+    virtual ~Message();
 
-    int id() { return id_; }
     std::string domain() { return domain_; }
     std::string method() { return method_; }
     base::DictionaryValue* params() { return params_.get(); }
+    virtual std::string Serialize() = 0;
+
+   protected:
+    Message(const std::string& method,
+            base::DictionaryValue* params);
+
+    std::string domain_;
+    std::string method_;
+    scoped_ptr<base::DictionaryValue> params_;
+
+   private:
+    DISALLOW_COPY_AND_ASSIGN(Message);
+  };
+
+  class Command : public Message {
+   public:
+    virtual  ~Command();
+
+    int id() { return id_; }
+
+    virtual std::string Serialize() OVERRIDE;
 
     // Creates success response. Takes ownership of |result|.
     scoped_ptr<Response> SuccessResponse(base::DictionaryValue* result);
 
     // Creates error response. Caller takes ownership of the return value.
-    scoped_ptr<Response> ErrorResponse(int error_code,
-                                       const std::string& error_message);
+    scoped_ptr<Response> InternalErrorResponse(const std::string& message);
+
+    // Creates error response. Caller takes ownership of the return value.
+    scoped_ptr<Response> InvalidParamResponse(const std::string& param);
 
     // Creates error response. Caller takes ownership of the return value.
     scoped_ptr<Response> NoSuchMethodErrorResponse();
 
    private:
     friend class DevToolsProtocol;
-    Command(int id, const std::string& domain, const std::string& method,
+    Command(int id, const std::string& method,
             base::DictionaryValue* params);
 
     int id_;
-    std::string domain_;
-    std::string method_;
-    scoped_ptr<base::DictionaryValue> params_;
 
     DISALLOW_COPY_AND_ASSIGN(Command);
   };
@@ -85,37 +95,20 @@
     DISALLOW_COPY_AND_ASSIGN(Response);
   };
 
-  class Notification {
+  class Notification : public Message {
    public:
-    // Takes ownership of |params|.
-    Notification(const std::string& method, base::DictionaryValue* params);
-    ~Notification();
+    virtual ~Notification();
 
-    std::string Serialize();
-
-   private:
-    std::string method_;
-    scoped_ptr<base::DictionaryValue> params_;
-
-    DISALLOW_COPY_AND_ASSIGN(Notification);
-  };
-
-  class Event {
-   public:
-    ~Event();
-
-    std::string Serialize();
+    virtual std::string Serialize() OVERRIDE;
 
    private:
     friend class DevToolsProtocol;
 
-    // Takes ownership over |params|.
-    Event(const std::string& method, base::DictionaryValue* params);
+    // Takes ownership of |params|.
+    Notification(const std::string& method,
+                 base::DictionaryValue* params);
 
-    std::string method_;
-    scoped_ptr<base::DictionaryValue> params_;
-
-    DISALLOW_COPY_AND_ASSIGN(Event);
+    DISALLOW_COPY_AND_ASSIGN(Notification);
   };
 
   class Handler {
@@ -152,10 +145,15 @@
   static Command* ParseCommand(const std::string& json,
                                std::string* error_response);
 
-  static Event* CreateEvent(const std::string& method,
-                            base::DictionaryValue* params);
+  static Notification* ParseNotification(const std::string& json);
+
+  static Notification* CreateNotification(const std::string& method,
+                                          base::DictionaryValue* params);
 
  private:
+  static DictionaryValue* ParseMessage(const std::string& json,
+                                       std::string* error_response);
+
   DevToolsProtocol() {}
   ~DevToolsProtocol() {}
 };
diff --git a/content/browser/devtools/devtools_protocol_constants.cc b/content/browser/devtools/devtools_protocol_constants.cc
index 5f7c012..0ac7344 100644
--- a/content/browser/devtools/devtools_protocol_constants.cc
+++ b/content/browser/devtools/devtools_protocol_constants.cc
@@ -8,6 +8,9 @@
 namespace devtools {
 
 namespace Inspector {
+namespace detached {
+  const char kName[] = "Inspector.detached";
+}  // detached
 namespace targetCrashed {
   const char kName[] = "Inspector.targetCrashed";
 }  // targetCrashed
@@ -30,8 +33,18 @@
   const char kName[] = "Page.navigate";
   const char kParamUrl[] = "url";
 }  // navigate
+namespace captureScreenshot {
+  const char kName[] = "Page.captureScreenshot";
+  const char kResponseData[] = "data";
+}  // captureScreenshot
 }  // Page
 
+namespace Worker {
+namespace disconnectedFromWorker {
+  extern const char kName[] = "Worker.disconnectedFromWorker";
+}  // disconnectedFromWorker
+}  // Worker
+
 }  // devtools
 }  // content
 
diff --git a/content/browser/devtools/devtools_protocol_constants.h b/content/browser/devtools/devtools_protocol_constants.h
index 79d9726..5a37a3f 100644
--- a/content/browser/devtools/devtools_protocol_constants.h
+++ b/content/browser/devtools/devtools_protocol_constants.h
@@ -15,6 +15,9 @@
 namespace devtools {
 
 namespace Inspector {
+namespace detached {
+  extern const char kName[];
+}  // detached
 namespace targetCrashed {
   extern const char kName[];
 }  // targetCrashed
@@ -37,8 +40,18 @@
   extern const char kName[];
   extern const char kParamUrl[];
 }  // navigate
+namespace captureScreenshot {
+  extern const char kName[];
+  extern const char kResponseData[];
+}  // captureScreenshot
 }  // Page
 
+namespace Worker {
+namespace disconnectedFromWorker {
+  extern const char kName[];
+}  // disconnectedFromWorker
+}  // Worker
+
 }  // devtools
 }  // content
 
diff --git a/content/browser/devtools/devtools_resources.gyp b/content/browser/devtools/devtools_resources.gyp
index 9ee2076..39c09ae 100644
--- a/content/browser/devtools/devtools_resources.gyp
+++ b/content/browser/devtools/devtools_resources.gyp
@@ -17,7 +17,7 @@
       'target_name': 'devtools_resources',
       'type': 'none',
       'dependencies': [
-        '<(webkit_src_dir)/Source/WebKit/chromium/WebKit.gyp:generate_devtools_grd',
+        '<(webkit_src_dir)/Source/devtools/devtools.gyp:generate_devtools_grd',
       ],
       'variables': {
         'grit_out_dir': '<(SHARED_INTERMEDIATE_DIR)/webkit',
diff --git a/content/browser/devtools/devtools_resources.target.darwin-arm.mk b/content/browser/devtools/devtools_resources.target.darwin-arm.mk
new file mode 100644
index 0000000..1d4262f
--- /dev/null
+++ b/content/browser/devtools/devtools_resources.target.darwin-arm.mk
@@ -0,0 +1,57 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := content_browser_devtools_devtools_resources_gyp
+LOCAL_MODULE_STEM := devtools_resources
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_devtools_generate_devtools_grd_gyp)/generate_devtools_grd.stamp
+
+### Rules for action "devtools_resources":
+$(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
+$(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
+$(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h: $(gyp_shared_intermediate_dir)/devtools/devtools_resources.grd $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/clique_unittest.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/c_format_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_writer_base_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/rc_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/rc_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/gather/txt_unittest.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grd_reader_unittest.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/grit_runner_unittest.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/lazy_re_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/base_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/include_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/io_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/message_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/misc_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/structure_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/pseudo_unittest.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/tclib_unittest.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/build_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb_unittest.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/util_unittest.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader_unittest.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: Generating resources from $(gyp_shared_intermediate_dir)/devtools/devtools_resources.grd ($@)"
+	$(hide)cd $(gyp_local_path)/content/browser/devtools; mkdir -p $(gyp_shared_intermediate_dir)/webkit/grit $(gyp_shared_intermediate_dir)/webkit; python ../../../tools/grit/grit.py -i "$(gyp_shared_intermediate_dir)/devtools/devtools_resources.grd" build -f GRIT_DIR/../gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/webkit" -D "SHARED_INTERMEDIATE_DIR=$(gyp_shared_intermediate_dir)" -D _chromium -E "CHROMIUM_BUILD=chromium" -D android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D use_concatenated_impulse_responses
+
+$(gyp_shared_intermediate_dir)/webkit/devtools_resources.pak: $(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h ;
+$(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources_map.cc: $(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h ;
+$(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources_map.h: $(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h ;
+
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h \
+	$(gyp_shared_intermediate_dir)/webkit/devtools_resources.pak \
+	$(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources_map.cc \
+	$(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources_map.h
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_browser_devtools_devtools_resources_gyp
+
+# Alias gyp target name.
+.PHONY: devtools_resources
+devtools_resources: content_browser_devtools_devtools_resources_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/content/browser/devtools/devtools_resources.target.darwin-x86.mk b/content/browser/devtools/devtools_resources.target.darwin-x86.mk
new file mode 100644
index 0000000..1d4262f
--- /dev/null
+++ b/content/browser/devtools/devtools_resources.target.darwin-x86.mk
@@ -0,0 +1,57 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := content_browser_devtools_devtools_resources_gyp
+LOCAL_MODULE_STEM := devtools_resources
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_devtools_generate_devtools_grd_gyp)/generate_devtools_grd.stamp
+
+### Rules for action "devtools_resources":
+$(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
+$(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
+$(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h: $(gyp_shared_intermediate_dir)/devtools/devtools_resources.grd $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/clique_unittest.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/c_format_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_writer_base_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/rc_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/rc_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/gather/txt_unittest.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grd_reader_unittest.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/grit_runner_unittest.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/lazy_re_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/base_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/include_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/io_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/message_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/misc_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/structure_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/pseudo_unittest.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/tclib_unittest.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/build_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb_unittest.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/util_unittest.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader_unittest.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: Generating resources from $(gyp_shared_intermediate_dir)/devtools/devtools_resources.grd ($@)"
+	$(hide)cd $(gyp_local_path)/content/browser/devtools; mkdir -p $(gyp_shared_intermediate_dir)/webkit/grit $(gyp_shared_intermediate_dir)/webkit; python ../../../tools/grit/grit.py -i "$(gyp_shared_intermediate_dir)/devtools/devtools_resources.grd" build -f GRIT_DIR/../gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/webkit" -D "SHARED_INTERMEDIATE_DIR=$(gyp_shared_intermediate_dir)" -D _chromium -E "CHROMIUM_BUILD=chromium" -D android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D use_concatenated_impulse_responses
+
+$(gyp_shared_intermediate_dir)/webkit/devtools_resources.pak: $(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h ;
+$(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources_map.cc: $(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h ;
+$(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources_map.h: $(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h ;
+
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h \
+	$(gyp_shared_intermediate_dir)/webkit/devtools_resources.pak \
+	$(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources_map.cc \
+	$(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources_map.h
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_browser_devtools_devtools_resources_gyp
+
+# Alias gyp target name.
+.PHONY: devtools_resources
+devtools_resources: content_browser_devtools_devtools_resources_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/content/browser/devtools/devtools_resources.target.linux-arm.mk b/content/browser/devtools/devtools_resources.target.linux-arm.mk
index 8685478..1d4262f 100644
--- a/content/browser/devtools/devtools_resources.target.linux-arm.mk
+++ b/content/browser/devtools/devtools_resources.target.linux-arm.mk
@@ -12,7 +12,7 @@
 
 # Make sure our deps are built first.
 GYP_TARGET_DEPENDENCIES := \
-	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_WebKit_chromium_generate_devtools_grd_gyp)/generate_devtools_grd.stamp
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_devtools_generate_devtools_grd_gyp)/generate_devtools_grd.stamp
 
 ### Rules for action "devtools_resources":
 $(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h: gyp_local_path := $(LOCAL_PATH)
@@ -21,7 +21,7 @@
 $(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
 $(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h: $(gyp_shared_intermediate_dir)/devtools/devtools_resources.grd $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/clique_unittest.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/c_format_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_writer_base_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/rc_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/rc_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/gather/txt_unittest.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grd_reader_unittest.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/grit_runner_unittest.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/lazy_re_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/base_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/include_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/io_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/message_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/misc_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/structure_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/pseudo_unittest.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/tclib_unittest.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/build_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb_unittest.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/util_unittest.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader_unittest.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
 	@echo "Gyp action: Generating resources from $(gyp_shared_intermediate_dir)/devtools/devtools_resources.grd ($@)"
-	$(hide)cd $(gyp_local_path)/content/browser/devtools; mkdir -p $(gyp_shared_intermediate_dir)/webkit/grit $(gyp_shared_intermediate_dir)/webkit; python ../../../tools/grit/grit.py -i "$(gyp_shared_intermediate_dir)/devtools/devtools_resources.grd" build -f GRIT_DIR/../gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/webkit" -D "SHARED_INTERMEDIATE_DIR=$(gyp_shared_intermediate_dir)" -D _chromium -E "CHROMIUM_BUILD=chromium" -D android
+	$(hide)cd $(gyp_local_path)/content/browser/devtools; mkdir -p $(gyp_shared_intermediate_dir)/webkit/grit $(gyp_shared_intermediate_dir)/webkit; python ../../../tools/grit/grit.py -i "$(gyp_shared_intermediate_dir)/devtools/devtools_resources.grd" build -f GRIT_DIR/../gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/webkit" -D "SHARED_INTERMEDIATE_DIR=$(gyp_shared_intermediate_dir)" -D _chromium -E "CHROMIUM_BUILD=chromium" -D android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D use_concatenated_impulse_responses
 
 $(gyp_shared_intermediate_dir)/webkit/devtools_resources.pak: $(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h ;
 $(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources_map.cc: $(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h ;
diff --git a/content/browser/devtools/devtools_resources.target.linux-x86.mk b/content/browser/devtools/devtools_resources.target.linux-x86.mk
index 8685478..1d4262f 100644
--- a/content/browser/devtools/devtools_resources.target.linux-x86.mk
+++ b/content/browser/devtools/devtools_resources.target.linux-x86.mk
@@ -12,7 +12,7 @@
 
 # Make sure our deps are built first.
 GYP_TARGET_DEPENDENCIES := \
-	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_WebKit_chromium_generate_devtools_grd_gyp)/generate_devtools_grd.stamp
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_devtools_generate_devtools_grd_gyp)/generate_devtools_grd.stamp
 
 ### Rules for action "devtools_resources":
 $(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h: gyp_local_path := $(LOCAL_PATH)
@@ -21,7 +21,7 @@
 $(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
 $(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h: $(gyp_shared_intermediate_dir)/devtools/devtools_resources.grd $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/clique_unittest.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/c_format_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_writer_base_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/rc_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/rc_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/gather/txt_unittest.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grd_reader_unittest.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/grit_runner_unittest.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/lazy_re_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/base_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/include_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/io_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/message_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/misc_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/structure_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/pseudo_unittest.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/tclib_unittest.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/build_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb_unittest.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/util_unittest.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader_unittest.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
 	@echo "Gyp action: Generating resources from $(gyp_shared_intermediate_dir)/devtools/devtools_resources.grd ($@)"
-	$(hide)cd $(gyp_local_path)/content/browser/devtools; mkdir -p $(gyp_shared_intermediate_dir)/webkit/grit $(gyp_shared_intermediate_dir)/webkit; python ../../../tools/grit/grit.py -i "$(gyp_shared_intermediate_dir)/devtools/devtools_resources.grd" build -f GRIT_DIR/../gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/webkit" -D "SHARED_INTERMEDIATE_DIR=$(gyp_shared_intermediate_dir)" -D _chromium -E "CHROMIUM_BUILD=chromium" -D android
+	$(hide)cd $(gyp_local_path)/content/browser/devtools; mkdir -p $(gyp_shared_intermediate_dir)/webkit/grit $(gyp_shared_intermediate_dir)/webkit; python ../../../tools/grit/grit.py -i "$(gyp_shared_intermediate_dir)/devtools/devtools_resources.grd" build -f GRIT_DIR/../gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/webkit" -D "SHARED_INTERMEDIATE_DIR=$(gyp_shared_intermediate_dir)" -D _chromium -E "CHROMIUM_BUILD=chromium" -D android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D use_concatenated_impulse_responses
 
 $(gyp_shared_intermediate_dir)/webkit/devtools_resources.pak: $(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h ;
 $(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources_map.cc: $(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h ;
diff --git a/content/browser/devtools/devtools_tracing_handler.cc b/content/browser/devtools/devtools_tracing_handler.cc
index 5caa2e3..5605c27 100644
--- a/content/browser/devtools/devtools_tracing_handler.cc
+++ b/content/browser/devtools/devtools_tracing_handler.cc
@@ -6,7 +6,6 @@
 
 #include "base/bind.h"
 #include "base/callback.h"
-#include "base/json/json_writer.h"
 #include "base/location.h"
 #include "base/strings/string_split.h"
 #include "base/values.h"
@@ -104,7 +103,6 @@
   return command->SuccessResponse(NULL);
 }
 
-
 scoped_ptr<DevToolsProtocol::Response>
 DevToolsTracingHandler::OnEnd(DevToolsProtocol::Command* command) {
   TraceController::GetInstance()->EndTracingAsync(this);
diff --git a/content/browser/devtools/devtools_tracing_handler.h b/content/browser/devtools/devtools_tracing_handler.h
index 86ddf00..64f1af7 100644
--- a/content/browser/devtools/devtools_tracing_handler.h
+++ b/content/browser/devtools/devtools_tracing_handler.h
@@ -11,8 +11,6 @@
 
 namespace content {
 
-class DevToolsWebSocketSender;
-
 // This class bridges DevTools remote debugging server with the trace
 // infrastructure.
 class DevToolsTracingHandler
diff --git a/content/browser/devtools/ipc_devtools_agent_host.cc b/content/browser/devtools/ipc_devtools_agent_host.cc
new file mode 100644
index 0000000..c7cd3c3
--- /dev/null
+++ b/content/browser/devtools/ipc_devtools_agent_host.cc
@@ -0,0 +1,42 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/devtools/ipc_devtools_agent_host.h"
+
+#include "content/common/devtools_messages.h"
+
+namespace content {
+
+void IPCDevToolsAgentHost::Attach() {
+  SendMessageToAgent(new DevToolsAgentMsg_Attach(MSG_ROUTING_NONE));
+  OnClientAttached();
+}
+
+void IPCDevToolsAgentHost::Detach() {
+  SendMessageToAgent(new DevToolsAgentMsg_Detach(MSG_ROUTING_NONE));
+  OnClientDetached();
+}
+
+void IPCDevToolsAgentHost::DispatchOnInspectorBackend(
+    const std::string& message) {
+  SendMessageToAgent(new DevToolsAgentMsg_DispatchOnInspectorBackend(
+      MSG_ROUTING_NONE, message));
+}
+
+void IPCDevToolsAgentHost::InspectElement(int x, int y) {
+  SendMessageToAgent(new DevToolsAgentMsg_InspectElement(MSG_ROUTING_NONE,
+                                                         x, y));
+}
+
+IPCDevToolsAgentHost::~IPCDevToolsAgentHost() {
+}
+
+void IPCDevToolsAgentHost::Reattach(const std::string& saved_agent_state) {
+  SendMessageToAgent(new DevToolsAgentMsg_Reattach(
+      MSG_ROUTING_NONE,
+      saved_agent_state));
+  OnClientAttached();
+}
+
+}  // namespace content
diff --git a/content/browser/devtools/ipc_devtools_agent_host.h b/content/browser/devtools/ipc_devtools_agent_host.h
new file mode 100644
index 0000000..98c2794
--- /dev/null
+++ b/content/browser/devtools/ipc_devtools_agent_host.h
@@ -0,0 +1,36 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_DEVTOOLS_IPC_DEVTOOLS_AGENT_HOST_H_
+#define CONTENT_BROWSER_DEVTOOLS_IPC_DEVTOOLS_AGENT_HOST_H_
+
+#include "content/browser/devtools/devtools_agent_host_impl.h"
+
+namespace IPC {
+class Message;
+}
+
+namespace content {
+
+class CONTENT_EXPORT IPCDevToolsAgentHost : public DevToolsAgentHostImpl {
+ public:
+  // DevToolsAgentHostImpl implementation.
+  virtual void Attach() OVERRIDE;
+  virtual void Detach() OVERRIDE;
+  virtual void DispatchOnInspectorBackend(const std::string& message) OVERRIDE;
+  virtual void InspectElement(int x, int y) OVERRIDE;
+
+ protected:
+  virtual ~IPCDevToolsAgentHost();
+
+  void Reattach(const std::string& saved_agent_state);
+
+  virtual void SendMessageToAgent(IPC::Message* msg) = 0;
+  virtual void OnClientAttached() = 0;
+  virtual void OnClientDetached() = 0;
+};
+
+}  // namespace content
+
+#endif  // CONTENT_BROWSER_DEVTOOLS_IPC_DEVTOOLS_AGENT_HOST_H_
diff --git a/content/browser/devtools/render_view_devtools_agent_host.cc b/content/browser/devtools/render_view_devtools_agent_host.cc
index 91f17a1..39698d3 100644
--- a/content/browser/devtools/render_view_devtools_agent_host.cc
+++ b/content/browser/devtools/render_view_devtools_agent_host.cc
@@ -4,7 +4,6 @@
 
 #include "content/browser/devtools/render_view_devtools_agent_host.h"
 
-#include "base/base64.h"
 #include "base/basictypes.h"
 #include "base/lazy_instance.h"
 #include "content/browser/child_process_security_policy_impl.h"
@@ -20,12 +19,6 @@
 #include "content/public/browser/content_browser_client.h"
 #include "content/public/browser/notification_service.h"
 #include "content/public/browser/notification_types.h"
-#include "content/public/browser/render_widget_host_view.h"
-#include "third_party/WebKit/Source/WebKit/chromium/public/WebDevToolsAgent.h"
-#include "ui/gfx/image/image_skia.h"
-#include "ui/gfx/native_widget_types.h"
-#include "ui/snapshot/snapshot.h"
-
 
 namespace content {
 
@@ -47,8 +40,6 @@
 
 }  // namespace
 
-using WebKit::WebDevToolsAgent;
-
 class RenderViewDevToolsAgentHost::DevToolsAgentHostRvhObserver
     : public RenderViewHostObserver {
  public:
@@ -99,7 +90,7 @@
     RenderViewHost* rvh = (*it)->render_view_host_;
     if (rvh && rvh->GetDelegate() != delegate)
       continue;
-    if (devtools_manager->GetDevToolsClientHostFor(*it))
+    if ((*it)->IsAttached())
       return true;
   }
   return false;
@@ -193,17 +184,16 @@
   std::string error_message;
   scoped_ptr<DevToolsProtocol::Command> command(
       DevToolsProtocol::ParseCommand(message, &error_message));
-  if (!command) {
-    OnDispatchOnInspectorFrontend(error_message);
-    return;
+  if (command) {
+    scoped_ptr<DevToolsProtocol::Response> overridden_response(
+        overrides_handler_->HandleCommand(command.get()));
+    if (overridden_response) {
+      OnDispatchOnInspectorFrontend(overridden_response->Serialize());
+      return;
+    }
   }
 
-  scoped_ptr<DevToolsProtocol::Response> overridden_response(
-      overrides_handler_->HandleCommand(command.get()));
-  if (overridden_response)
-    OnDispatchOnInspectorFrontend(overridden_response->Serialize());
-  else
-    DevToolsAgentHostImpl::DispatchOnInspectorBackend(message);
+  IPCDevToolsAgentHost::DispatchOnInspectorBackend(message);
 }
 
 void RenderViewDevToolsAgentHost::SendMessageToAgent(IPC::Message* msg) {
@@ -213,31 +203,23 @@
   render_view_host_->Send(msg);
 }
 
-void RenderViewDevToolsAgentHost::NotifyClientAttaching() {
+void RenderViewDevToolsAgentHost::OnClientAttached() {
   if (!render_view_host_)
     return;
 
   ChildProcessSecurityPolicyImpl::GetInstance()->GrantReadRawCookies(
       render_view_host_->GetProcess()->GetID());
-
-  NotificationService::current()->Notify(
-      NOTIFICATION_DEVTOOLS_AGENT_ATTACHED,
-      Source<BrowserContext>(
-          render_view_host_->GetSiteInstance()->GetProcess()->
-              GetBrowserContext()),
-      Details<RenderViewHost>(render_view_host_));
 }
 
-void RenderViewDevToolsAgentHost::NotifyClientDetaching() {
+void RenderViewDevToolsAgentHost::OnClientDetached() {
   if (!render_view_host_)
     return;
 
-  DevToolsManager* devtools_manager = DevToolsManager::GetInstance();
   bool process_has_agents = false;
   RenderProcessHost* render_process_host = render_view_host_->GetProcess();
   for (Instances::iterator it = g_instances.Get().begin();
        it != g_instances.Get().end(); ++it) {
-    if (*it == this || !devtools_manager->GetDevToolsClientHostFor(*it))
+    if (*it == this || !(*it)->IsAttached())
       continue;
     RenderViewHost* rvh = (*it)->render_view_host();
     if (rvh && rvh->GetProcess() == render_process_host)
@@ -249,13 +231,6 @@
     ChildProcessSecurityPolicyImpl::GetInstance()->RevokeReadRawCookies(
         render_process_host->GetID());
   }
-
-  NotificationService::current()->Notify(
-      NOTIFICATION_DEVTOOLS_AGENT_DETACHED,
-      Source<BrowserContext>(
-          render_view_host_->GetSiteInstance()->GetProcess()->
-              GetBrowserContext()),
-      Details<RenderViewHost>(render_view_host_));
 }
 
 RenderViewDevToolsAgentHost::~RenderViewDevToolsAgentHost() {
@@ -301,7 +276,7 @@
 }
 
 void RenderViewDevToolsAgentHost::DisconnectRenderViewHost() {
-  NotifyClientDetaching();
+  OnClientDetached();
   rvh_observer_.reset();
   render_view_host_ = NULL;
 }
@@ -316,11 +291,11 @@
 }
 
 void RenderViewDevToolsAgentHost::RenderViewCrashed() {
-  scoped_ptr<DevToolsProtocol::Event> event(
-      DevToolsProtocol::CreateEvent(
+  scoped_ptr<DevToolsProtocol::Notification> notification(
+      DevToolsProtocol::CreateNotification(
           devtools::Inspector::targetCrashed::kName, NULL));
   DevToolsManagerImpl::GetInstance()->
-      DispatchOnInspectorFrontend(this, event->Serialize());
+      DispatchOnInspectorFrontend(this, notification->Serialize());
 }
 
 bool RenderViewDevToolsAgentHost::OnRvhMessageReceived(
@@ -350,38 +325,8 @@
     const std::string& message) {
   if (!render_view_host_)
     return;
-
-  WebDevToolsAgent::BrowserDataHint dataHint =
-      WebDevToolsAgent::shouldPatchWithBrowserData(message.data(),
-                                                   message.length());
-  if (dataHint == WebDevToolsAgent::BrowserDataHintNone) {
-    DevToolsManagerImpl::GetInstance()->DispatchOnInspectorFrontend(
-        this, message);
-    return;
-  }
-
-  // Prepare the data and patch message with it.
-  std::string overriden_message;
-  switch (dataHint) {
-    case WebDevToolsAgent::BrowserDataHintScreenshot:
-      {
-        std::string base_64_data;
-        if (CaptureScreenshot(&base_64_data)) {
-          overriden_message = WebDevToolsAgent::patchWithBrowserData(
-              WebKit::WebString::fromUTF8(message),
-              dataHint,
-              WebKit::WebString::fromUTF8(base_64_data)).utf8();
-        }
-        break;
-      }
-    case WebDevToolsAgent::BrowserDataHintNone:
-      // Fall through.
-    default:
-      overriden_message = message;
-  }
-
   DevToolsManagerImpl::GetInstance()->DispatchOnInspectorFrontend(
-      this, overriden_message);
+      this, message);
 }
 
 void RenderViewDevToolsAgentHost::OnClearBrowserCache() {
@@ -394,21 +339,4 @@
     GetContentClient()->browser()->ClearCookies(render_view_host_);
 }
 
-bool RenderViewDevToolsAgentHost::CaptureScreenshot(std::string* base_64_data) {
-  DCHECK(render_view_host_);
-  gfx::Rect view_bounds = render_view_host_->GetView()->GetViewBounds();
-  gfx::Rect snapshot_bounds(view_bounds.size());
-  gfx::Size snapshot_size = snapshot_bounds.size();
-  std::vector<unsigned char> png;
-  if (!ui::GrabViewSnapshot(render_view_host_->GetView()->GetNativeView(),
-                            &png,
-                            snapshot_bounds))
-    return false;
-
-  return base::Base64Encode(base::StringPiece(
-                                reinterpret_cast<char*>(&*png.begin()),
-                                png.size()),
-                            base_64_data);
-}
-
 }  // namespace content
diff --git a/content/browser/devtools/render_view_devtools_agent_host.h b/content/browser/devtools/render_view_devtools_agent_host.h
index 436776b..bac4064 100644
--- a/content/browser/devtools/render_view_devtools_agent_host.h
+++ b/content/browser/devtools/render_view_devtools_agent_host.h
@@ -10,7 +10,7 @@
 #include "base/basictypes.h"
 #include "base/compiler_specific.h"
 #include "base/memory/scoped_ptr.h"
-#include "content/browser/devtools/devtools_agent_host_impl.h"
+#include "content/browser/devtools/ipc_devtools_agent_host.h"
 #include "content/common/content_export.h"
 #include "content/public/browser/render_view_host_observer.h"
 #include "content/public/browser/web_contents_observer.h"
@@ -21,7 +21,7 @@
 class RenderViewHost;
 
 class CONTENT_EXPORT RenderViewDevToolsAgentHost
-    : public DevToolsAgentHostImpl,
+    : public IPCDevToolsAgentHost,
       private WebContentsObserver {
  public:
   static void OnCancelPendingNavigation(RenderViewHost* pending,
@@ -40,11 +40,11 @@
   // DevTooolsAgentHost overrides.
   virtual RenderViewHost* GetRenderViewHost() OVERRIDE;
 
-  // DevToolsAgentHostImpl overrides.
+  // IPCDevToolsAgentHost overrides.
   virtual void DispatchOnInspectorBackend(const std::string& message) OVERRIDE;
   virtual void SendMessageToAgent(IPC::Message* msg) OVERRIDE;
-  virtual void NotifyClientAttaching() OVERRIDE;
-  virtual void NotifyClientDetaching() OVERRIDE;
+  virtual void OnClientAttached() OVERRIDE;
+  virtual void OnClientDetached() OVERRIDE;
 
   // WebContentsObserver overrides.
   virtual void AboutToNavigateRenderView(RenderViewHost* dest_rvh) OVERRIDE;
@@ -62,8 +62,6 @@
   void OnClearBrowserCache();
   void OnClearBrowserCookies();
 
-  bool CaptureScreenshot(std::string* base_64_data);
-
   RenderViewHost* render_view_host_;
   scoped_ptr<DevToolsAgentHostRvhObserver> rvh_observer_;
   scoped_ptr<RendererOverridesHandler> overrides_handler_;
diff --git a/content/browser/devtools/renderer_overrides_handler.cc b/content/browser/devtools/renderer_overrides_handler.cc
index 0531f8b..7b736e3 100644
--- a/content/browser/devtools/renderer_overrides_handler.cc
+++ b/content/browser/devtools/renderer_overrides_handler.cc
@@ -6,11 +6,11 @@
 
 #include <string>
 
+#include "base/base64.h"
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/files/file_path.h"
 #include "base/string16.h"
-#include "base/stringprintf.h"
 #include "base/values.h"
 #include "content/browser/child_process_security_policy_impl.h"
 #include "content/browser/devtools/devtools_protocol_constants.h"
@@ -20,11 +20,13 @@
 #include "content/public/browser/navigation_controller.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/render_view_host.h"
+#include "content/public/browser/render_widget_host_view.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_contents_delegate.h"
 #include "content/public/common/page_transition_types.h"
 #include "content/public/common/referrer.h"
 #include "googleurl/src/gurl.h"
+#include "ui/snapshot/snapshot.h"
 
 namespace content {
 
@@ -45,6 +47,11 @@
       base::Bind(
           &RendererOverridesHandler::PageNavigate,
           base::Unretained(this)));
+  RegisterCommandHandler(
+      devtools::Page::captureScreenshot::kName,
+      base::Bind(
+          &RendererOverridesHandler::PageCaptureScreenshot,
+          base::Unretained(this)));
 }
 
 RendererOverridesHandler::~RendererOverridesHandler() {}
@@ -56,22 +63,16 @@
   base::ListValue* file_list = NULL;
   const char* param =
       devtools::DOM::setFileInputFiles::kParamFiles;
-  if (!params || !params->GetList(param, &file_list)) {
-    return command->ErrorResponse(
-        DevToolsProtocol::kErrorInvalidParams,
-        base::StringPrintf("Missing or invalid '%s' parameter", param));
-  }
+  if (!params || !params->GetList(param, &file_list))
+    return command->InvalidParamResponse(param);
   RenderViewHost* host = agent_->GetRenderViewHost();
   if (!host)
     return scoped_ptr<DevToolsProtocol::Response>();
 
   for (size_t i = 0; i < file_list->GetSize(); ++i) {
     base::FilePath::StringType file;
-    if (!file_list->GetString(i, &file)) {
-      return command->ErrorResponse(
-          DevToolsProtocol::kErrorInvalidParams,
-          base::StringPrintf("'%s' must be a list of strings", param));
-    }
+    if (!file_list->GetString(i, &file))
+      return command->InvalidParamResponse(param);
     ChildProcessSecurityPolicyImpl::GetInstance()->GrantReadFile(
         host->GetProcess()->GetID(), base::FilePath(file));
   }
@@ -85,11 +86,8 @@
   const char* paramAccept =
       devtools::Page::handleJavaScriptDialog::kParamAccept;
   bool accept;
-  if (!params || !params->GetBoolean(paramAccept, &accept)) {
-    return command->ErrorResponse(
-        DevToolsProtocol::kErrorInvalidParams,
-        base::StringPrintf("Missing or invalid '%s' parameter", paramAccept));
-  }
+  if (!params || !params->GetBoolean(paramAccept, &accept))
+    return command->InvalidParamResponse(paramAccept);
   string16 prompt_override;
   string16* prompt_override_ptr = &prompt_override;
   if (!params || !params->GetString(
@@ -110,9 +108,7 @@
       }
     }
   }
-  return command->ErrorResponse(
-      DevToolsProtocol::kErrorInternalError,
-      "No JavaScript dialog to handle");
+  return command->InternalErrorResponse("No JavaScript dialog to handle");
 }
 
 scoped_ptr<DevToolsProtocol::Response>
@@ -121,30 +117,52 @@
   base::DictionaryValue* params = command->params();
   std::string url;
   const char* param = devtools::Page::navigate::kParamUrl;
-  if (!params || !params->GetString(param, &url)) {
-    return command->ErrorResponse(
-        DevToolsProtocol::kErrorInvalidParams,
-        base::StringPrintf("Missing or invalid '%s' parameter",
-                           param));
-  }
+  if (!params || !params->GetString(param, &url))
+    return command->InvalidParamResponse(param);
   GURL gurl(url);
   if (!gurl.is_valid()) {
-    return command->ErrorResponse(
-        DevToolsProtocol::kErrorInternalError,
-        "Cannot navigate to invalid URL");
+    return command->InternalErrorResponse("Cannot navigate to invalid URL");
   }
   RenderViewHost* host = agent_->GetRenderViewHost();
   if (host) {
     WebContents* web_contents = host->GetDelegate()->GetAsWebContents();
     if (web_contents) {
-      web_contents->GetController().LoadURL(
-          gurl, Referrer(), PAGE_TRANSITION_TYPED, "");
+      web_contents->GetController()
+          .LoadURL(gurl, Referrer(), PAGE_TRANSITION_TYPED, std::string());
       return command->SuccessResponse(new base::DictionaryValue());
     }
   }
-  return command->ErrorResponse(
-      DevToolsProtocol::kErrorInternalError,
-      "No WebContents to navigate");
+  return command->InternalErrorResponse("No WebContents to navigate");
+}
+
+scoped_ptr<DevToolsProtocol::Response>
+RendererOverridesHandler::PageCaptureScreenshot(
+    DevToolsProtocol::Command* command) {
+  std::string base_64_data;
+  if (!CaptureScreenshot(&base_64_data))
+    return command->InternalErrorResponse("Unable to capture a screenshot");
+
+  base::DictionaryValue* response = new base::DictionaryValue();
+  response->SetString(
+      devtools::Page::captureScreenshot::kResponseData, base_64_data);
+  return command->SuccessResponse(response);
+}
+
+bool RendererOverridesHandler::CaptureScreenshot(std::string* base_64_data) {
+  RenderViewHost* host = agent_->GetRenderViewHost();
+  gfx::Rect view_bounds = host->GetView()->GetViewBounds();
+  gfx::Rect snapshot_bounds(view_bounds.size());
+  gfx::Size snapshot_size = snapshot_bounds.size();
+  std::vector<unsigned char> png;
+  if (!ui::GrabViewSnapshot(host->GetView()->GetNativeView(),
+                            &png,
+                            snapshot_bounds))
+    return false;
+
+  return base::Base64Encode(base::StringPiece(
+                                reinterpret_cast<char*>(&*png.begin()),
+                                png.size()),
+                            base_64_data);
 }
 
 }  // namespace content
diff --git a/content/browser/devtools/renderer_overrides_handler.h b/content/browser/devtools/renderer_overrides_handler.h
index cf3989d..e175f05 100644
--- a/content/browser/devtools/renderer_overrides_handler.h
+++ b/content/browser/devtools/renderer_overrides_handler.h
@@ -29,6 +29,10 @@
       DevToolsProtocol::Command* command);
   scoped_ptr<DevToolsProtocol::Response> PageNavigate(
       DevToolsProtocol::Command* command);
+  scoped_ptr<DevToolsProtocol::Response> PageCaptureScreenshot(
+      DevToolsProtocol::Command* command);
+
+  bool CaptureScreenshot(std::string* base_64_data);
 
   DevToolsAgentHost* agent_;
 
diff --git a/content/browser/devtools/tethering_handler.cc b/content/browser/devtools/tethering_handler.cc
new file mode 100644
index 0000000..bad1ded
--- /dev/null
+++ b/content/browser/devtools/tethering_handler.cc
@@ -0,0 +1,306 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/devtools/tethering_handler.h"
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/stl_util.h"
+#include "base/values.h"
+#include "content/browser/devtools/devtools_http_handler_impl.h"
+#include "content/public/browser/devtools_client_host.h"
+#include "content/public/browser/devtools_http_handler_delegate.h"
+#include "net/base/io_buffer.h"
+#include "net/base/ip_endpoint.h"
+#include "net/base/net_errors.h"
+#include "net/base/net_log.h"
+#include "net/socket/stream_listen_socket.h"
+#include "net/socket/stream_socket.h"
+#include "net/socket/tcp_server_socket.h"
+
+namespace content {
+
+namespace {
+
+const char kTetheringBind[] = "Tethering.bind";
+const char kTetheringUnbind[] = "Tethering.unbind";
+
+const char kTetheringAccepted[] = "Tethering.accepted";
+
+const char kPortParam[] = "port";
+const char kConnectionIdParam[] = "connectionId";
+
+const char kLocalhost[] = "127.0.0.1";
+
+const int kListenBacklog = 5;
+const int kBufferSize = 16 * 1024;
+
+const int kMinTetheringPort = 5000;
+const int kMaxTetheringPort = 10000;
+
+class SocketPump : public net::StreamListenSocket::Delegate {
+ public:
+  SocketPump(DevToolsHttpHandlerDelegate* delegate,
+             net::StreamSocket* client_socket)
+      : client_socket_(client_socket),
+        delegate_(delegate),
+        wire_buffer_size_(0),
+        pending_destruction_(false) {
+  }
+
+  std::string Init() {
+    std::string channel_name;
+    server_socket_ = delegate_->CreateSocketForTethering(this, &channel_name);
+    if (!server_socket_ || channel_name.empty())
+      SelfDestruct();
+    return channel_name;
+  }
+
+  virtual ~SocketPump() { }
+
+ private:
+  virtual void DidAccept(net::StreamListenSocket* server,
+                         net::StreamListenSocket* socket) OVERRIDE {
+    if (accepted_socket_)
+      return;
+
+    buffer_ = new net::IOBuffer(kBufferSize);
+    wire_buffer_ = new net::GrowableIOBuffer();
+    wire_buffer_->SetCapacity(kBufferSize);
+
+    accepted_socket_ = socket;
+    int result = client_socket_->Read(buffer_, kBufferSize,
+                                      base::Bind(&SocketPump::OnClientRead,
+                                                 base::Unretained(this)));
+    if (result != net::ERR_IO_PENDING)
+      OnClientRead(result);
+  }
+
+  virtual void DidRead(net::StreamListenSocket* socket,
+                       const char* data,
+                       int len) OVERRIDE {
+    int old_size = wire_buffer_size_;
+    wire_buffer_size_ += len;
+    while (wire_buffer_->capacity() < wire_buffer_size_)
+      wire_buffer_->SetCapacity(wire_buffer_->capacity() * 2);
+    memcpy(wire_buffer_->StartOfBuffer() + old_size, data, len);
+    if (old_size != wire_buffer_->offset())
+      return;
+    OnClientWrite(0);
+  }
+
+  virtual void DidClose(net::StreamListenSocket* socket) OVERRIDE {
+    SelfDestruct();
+  }
+
+  void OnClientRead(int result) {
+    if (result <= 0) {
+      SelfDestruct();
+      return;
+    }
+
+    accepted_socket_->Send(buffer_->data(), result);
+    result = client_socket_->Read(buffer_, kBufferSize,
+                                  base::Bind(&SocketPump::OnClientRead,
+                                             base::Unretained(this)));
+    if (result != net::ERR_IO_PENDING)
+      OnClientRead(result);
+  }
+
+  void OnClientWrite(int result) {
+    if (result < 0)
+      SelfDestruct();
+
+    wire_buffer_->set_offset(wire_buffer_->offset() + result);
+
+    int remaining = wire_buffer_size_ - wire_buffer_->offset();
+    if (remaining == 0) {
+      if (pending_destruction_)
+        SelfDestruct();
+      return;
+    }
+
+
+    if (remaining > kBufferSize)
+      remaining = kBufferSize;
+
+    scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(remaining);
+    memcpy(buffer->data(), wire_buffer_->data(), remaining);
+    result = client_socket_->Write(
+        buffer, remaining, base::Bind(&SocketPump::OnClientWrite,
+                                      base::Unretained(this)));
+
+    // Shrink buffer
+    int offset = wire_buffer_->offset();
+    if (offset > kBufferSize) {
+      memcpy(wire_buffer_->StartOfBuffer(), wire_buffer_->data(),
+          wire_buffer_size_ - offset);
+      wire_buffer_size_ -= offset;
+      wire_buffer_->set_offset(0);
+    }
+
+    if (result != net::ERR_IO_PENDING)
+      OnClientWrite(result);
+    return;
+  }
+
+  void SelfDestruct() {
+    if (wire_buffer_->offset() != wire_buffer_size_) {
+      pending_destruction_ = true;
+      return;
+    }
+    delete this;
+  }
+
+ private:
+  scoped_ptr<net::StreamSocket> client_socket_;
+  scoped_refptr<net::StreamListenSocket> server_socket_;
+  scoped_refptr<net::StreamListenSocket> accepted_socket_;
+  scoped_refptr<net::IOBuffer> buffer_;
+  scoped_refptr<net::GrowableIOBuffer> wire_buffer_;
+  DevToolsHttpHandlerDelegate* delegate_;
+  int wire_buffer_size_;
+  bool pending_destruction_;
+};
+
+}  // namespace
+
+const char TetheringHandler::kDomain[] = "Tethering";
+
+class TetheringHandler::BoundSocket {
+ public:
+  BoundSocket(TetheringHandler* handler,
+              DevToolsHttpHandlerDelegate* delegate)
+      : handler_(handler),
+        delegate_(delegate),
+        socket_(new net::TCPServerSocket(NULL, net::NetLog::Source())),
+        port_(0) {
+  }
+
+  virtual ~BoundSocket() {
+  }
+
+  bool Listen(int port) {
+    port_ = port;
+    net::IPAddressNumber ip_number;
+    if (!net::ParseIPLiteralToNumber(kLocalhost, &ip_number))
+      return false;
+
+    net::IPEndPoint end_point(ip_number, port);
+    socket_->AllowAddressReuse();
+    int result = socket_->Listen(end_point, kListenBacklog);
+    if (result < 0)
+      return false;
+
+    net::IPEndPoint local_address;
+    result = socket_->GetLocalAddress(&local_address);
+    if (result < 0)
+      return false;
+
+    DoAccept();
+    return true;
+  }
+
+ private:
+  typedef std::map<net::IPEndPoint, net::StreamSocket*> AcceptedSocketsMap;
+
+  void DoAccept() {
+    while (true) {
+      int result = socket_->Accept(
+          &accept_socket_,
+          base::Bind(&BoundSocket::OnAccepted, base::Unretained(this)));
+      if (result == net::ERR_IO_PENDING)
+        break;
+      else
+        HandleAcceptResult(result);
+    }
+  }
+
+  void OnAccepted(int result) {
+    HandleAcceptResult(result);
+    if (result == net::OK)
+      DoAccept();
+  }
+
+  void HandleAcceptResult(int result) {
+    if (result != net::OK)
+      return;
+
+    SocketPump* pump = new SocketPump(delegate_, accept_socket_.release());
+    std::string name = pump->Init();
+    if (!name.empty())
+      handler_->Accepted(port_, name);
+  }
+
+  TetheringHandler* handler_;
+  DevToolsHttpHandlerDelegate* delegate_;
+  scoped_ptr<net::ServerSocket> socket_;
+  scoped_ptr<net::StreamSocket> accept_socket_;
+  int port_;
+};
+
+TetheringHandler::TetheringHandler(DevToolsHttpHandlerDelegate* delegate)
+    : delegate_(delegate) {
+  RegisterCommandHandler(kTetheringBind,
+                         base::Bind(&TetheringHandler::OnBind,
+                                    base::Unretained(this)));
+  RegisterCommandHandler(kTetheringUnbind,
+                         base::Bind(&TetheringHandler::OnUnbind,
+                                    base::Unretained(this)));
+}
+
+TetheringHandler::~TetheringHandler() {
+   STLDeleteContainerPairSecondPointers(bound_sockets_.begin(),
+                                        bound_sockets_.end());
+}
+
+void TetheringHandler::Accepted(int port, const std::string& name) {
+  base::DictionaryValue* params = new base::DictionaryValue();
+  params->SetInteger(kPortParam, port);
+  params->SetString(kConnectionIdParam, name);
+  SendNotification(kTetheringAccepted, params);
+}
+
+static int GetPort(DevToolsProtocol::Command* command) {
+  base::DictionaryValue* params = command->params();
+  int port = 0;
+  if (!params || !params->GetInteger(kPortParam, &port) ||
+      port < kMinTetheringPort || port > kMaxTetheringPort)
+    return 0;
+  return port;
+}
+
+scoped_ptr<DevToolsProtocol::Response>
+TetheringHandler::OnBind(DevToolsProtocol::Command* command) {
+  int port = GetPort(command);
+  if (port == 0)
+    return command->InvalidParamResponse(kPortParam);
+
+  if (bound_sockets_.find(port) != bound_sockets_.end())
+    return command->InternalErrorResponse("Port already bound");
+
+  scoped_ptr<BoundSocket> bound_socket(new BoundSocket(this, delegate_));
+  if (!bound_socket->Listen(port))
+    return command->InternalErrorResponse("Could not bind port");
+
+  bound_sockets_[port] = bound_socket.release();
+  return command->SuccessResponse(NULL);
+}
+
+scoped_ptr<DevToolsProtocol::Response>
+TetheringHandler::OnUnbind(DevToolsProtocol::Command* command) {
+  int port = GetPort(command);
+  if (port == 0)
+    return command->InvalidParamResponse(kPortParam);
+
+  BoundSockets::iterator it = bound_sockets_.find(port);
+  if (it == bound_sockets_.end())
+    return command->InternalErrorResponse("Port is not bound");
+
+  delete it->second;
+  bound_sockets_.erase(it);
+  return command->SuccessResponse(NULL);
+}
+
+}  // namespace content
diff --git a/content/browser/devtools/tethering_handler.h b/content/browser/devtools/tethering_handler.h
new file mode 100644
index 0000000..a9931cc
--- /dev/null
+++ b/content/browser/devtools/tethering_handler.h
@@ -0,0 +1,41 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_DEVTOOLS_TETHERING_HANDLER_H_
+#define CONTENT_BROWSER_DEVTOOLS_TETHERING_HANDLER_H_
+
+#include <map>
+
+#include "content/browser/devtools/devtools_protocol.h"
+
+namespace content {
+
+class DevToolsHttpHandlerDelegate;
+
+// This class implements reversed tethering handler.
+class TetheringHandler : public DevToolsProtocol::Handler {
+ public:
+  static const char kDomain[];
+
+  TetheringHandler(DevToolsHttpHandlerDelegate* delegate);
+  virtual ~TetheringHandler();
+
+  void Accepted(int port, const std::string& name);
+
+ private:
+  class BoundSocket;
+  scoped_ptr<DevToolsProtocol::Response> OnBind(
+      DevToolsProtocol::Command* command);
+  scoped_ptr<DevToolsProtocol::Response> OnUnbind(
+      DevToolsProtocol::Command* command);
+
+  typedef std::map<int, BoundSocket*> BoundSockets;
+  BoundSockets bound_sockets_;
+  DevToolsHttpHandlerDelegate* delegate_;
+  DISALLOW_COPY_AND_ASSIGN(TetheringHandler);
+};
+
+}  // namespace content
+
+#endif  // CONTENT_BROWSER_DEVTOOLS_TETHERING_HANDLER_H_
diff --git a/content/browser/devtools/worker_devtools_manager.cc b/content/browser/devtools/worker_devtools_manager.cc
index ae32629..97bfda7 100644
--- a/content/browser/devtools/worker_devtools_manager.cc
+++ b/content/browser/devtools/worker_devtools_manager.cc
@@ -9,8 +9,10 @@
 
 #include "base/bind.h"
 #include "base/lazy_instance.h"
-#include "content/browser/devtools/devtools_agent_host_impl.h"
 #include "content/browser/devtools/devtools_manager_impl.h"
+#include "content/browser/devtools/devtools_protocol.h"
+#include "content/browser/devtools/devtools_protocol_constants.h"
+#include "content/browser/devtools/ipc_devtools_agent_host.h"
 #include "content/browser/devtools/worker_devtools_message_filter.h"
 #include "content/browser/worker_host/worker_service_impl.h"
 #include "content/common/devtools_messages.h"
@@ -56,16 +58,17 @@
 
 
 class WorkerDevToolsManager::WorkerDevToolsAgentHost
-    : public DevToolsAgentHostImpl {
+    : public IPCDevToolsAgentHost {
  public:
   explicit WorkerDevToolsAgentHost(WorkerId worker_id)
       : has_worker_id_(false) {
     SetWorkerId(worker_id, false);
-    AddRef();  //  Balanced in ResetWorkerId.
   }
 
   void SetWorkerId(WorkerId worker_id, bool reattach) {
     worker_id_ = worker_id;
+    if (!has_worker_id_)
+      AddRef();  //  Balanced in ResetWorkerId.
     has_worker_id_ = true;
     g_agent_map.Get()[worker_id_] = this;
 
@@ -84,7 +87,7 @@
   void ResetWorkerId() {
     g_agent_map.Get().erase(worker_id_);
     has_worker_id_ = false;
-    Release();
+    Release();  //  Balanced in SetWorkerId.
   }
 
   void SaveAgentRuntimeState(const std::string& state) {
@@ -97,10 +100,7 @@
   }
 
  private:
-  virtual ~WorkerDevToolsAgentHost() {
-    g_agent_map.Get().erase(worker_id_);
-    g_orphan_map.Get().erase(worker_id_);
-  }
+  virtual ~WorkerDevToolsAgentHost();
 
   static void ConnectToWorker(
       int worker_process_id,
@@ -117,7 +117,7 @@
         worker_process_id, worker_route_id, *message);
   }
 
-  // DevToolsAgentHostImpl implementation.
+  // IPCDevToolsAgentHost implementation.
   virtual void SendMessageToAgent(IPC::Message* message) OVERRIDE {
     if (!has_worker_id_) {
       delete message;
@@ -132,8 +132,8 @@
             base::Owned(message)));
   }
 
-  virtual void NotifyClientAttaching() OVERRIDE {}
-  virtual void NotifyClientDetaching() OVERRIDE {}
+  virtual void OnClientAttached() OVERRIDE {}
+  virtual void OnClientDetached() OVERRIDE {}
 
   bool has_worker_id_;
   WorkerId worker_id_;
@@ -166,33 +166,30 @@
 
     WorkerDevToolsAgentHost* agent = it->second;
     DevToolsManagerImpl* devtools_manager = DevToolsManagerImpl::GetInstance();
-    DevToolsClientHost* client_host =
-        devtools_manager->GetDevToolsClientHostFor(agent);
-
-    if (!client_host) {
+    if (!agent->IsAttached()) {
       // Agent has no client hosts -> delete it.
       RemovePendingWorkerData(id);
       return;
     }
 
     // Client host is debugging this worker agent host.
-    devtools_manager->DispatchOnInspectorFrontend(
-        agent,
-        WebDevToolsAgent::workerDisconnectedFromWorkerEvent().utf8());
+    std::string notification = DevToolsProtocol::CreateNotification(
+        devtools::Worker::disconnectedFromWorker::kName, NULL)->Serialize();
+    devtools_manager->DispatchOnInspectorFrontend(agent, notification);
     g_orphan_map.Get()[id] = agent;
     agent->ResetWorkerId();
   }
 
- private:
-  DetachedClientHosts() {}
-  ~DetachedClientHosts() {}
-
   static void RemovePendingWorkerData(WorkerId id) {
     BrowserThread::PostTask(
         BrowserThread::IO, FROM_HERE,
         base::Bind(&RemoveInspectedWorkerDataOnIOThread, id));
   }
 
+ private:
+  DetachedClientHosts() {}
+  ~DetachedClientHosts() {}
+
   static void RemoveInspectedWorkerDataOnIOThread(WorkerId id) {
     WorkerDevToolsManager::GetInstance()->RemoveInspectedWorkerData(id);
   }
@@ -444,4 +441,10 @@
     process->Send(new DevToolsAgentMsg_ResumeWorkerContext(id.second));
 }
 
+WorkerDevToolsManager::WorkerDevToolsAgentHost::~WorkerDevToolsAgentHost() {
+  DetachedClientHosts::RemovePendingWorkerData(worker_id_);
+  g_agent_map.Get().erase(worker_id_);
+  g_orphan_map.Get().erase(worker_id_);
+}
+
 }  // namespace content
diff --git a/content/browser/download/base_file.cc b/content/browser/download/base_file.cc
index b5ded45..687c321 100644
--- a/content/browser/download/base_file.cc
+++ b/content/browser/download/base_file.cc
@@ -67,7 +67,7 @@
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
   DCHECK(!detached_);
 
-  if (file_stream_.get()) {
+  if (file_stream_) {
     file_stream_->SetBoundNetLogSource(bound_net_log_);
     file_stream_->EnableErrorStatistics();
   }
@@ -103,7 +103,7 @@
   if (detached_)
     RecordDownloadCount(APPEND_TO_DETACHED_FILE_COUNT);
 
-  if (!file_stream_.get())
+  if (!file_stream_)
     return LogInterruptReason("No file stream on append", 0,
                               DOWNLOAD_INTERRUPT_REASON_FILE_FAILED);
 
@@ -232,11 +232,11 @@
 
 std::string BaseFile::GetHashState() {
   if (!calculate_hash_)
-    return "";
+    return std::string();
 
   Pickle hash_state;
   if (!secure_hash_->Serialize(&hash_state))
-    return "";
+    return std::string();
 
   return std::string(reinterpret_cast<const char*>(hash_state.data()),
                      hash_state.size());
@@ -274,7 +274,7 @@
       base::Bind(&FileOpenedNetLogCallback, &full_path_, bytes_so_far_));
 
   // Create a new file stream if it is not provided.
-  if (!file_stream_.get()) {
+  if (!file_stream_) {
     CreateFileStream();
     file_stream_->EnableErrorStatistics();
     int open_result = file_stream_->OpenSync(
@@ -322,7 +322,7 @@
 
   bound_net_log_.AddEvent(net::NetLog::TYPE_DOWNLOAD_FILE_CLOSED);
 
-  if (file_stream_.get()) {
+  if (file_stream_) {
 #if defined(OS_CHROMEOS)
     // Currently we don't really care about the return value, since if it fails
     // theres not much we can do.  But we might in the future.
diff --git a/content/browser/download/base_file_unittest.cc b/content/browser/download/base_file_unittest.cc
index 799076d..7b53c4d 100644
--- a/content/browser/download/base_file_unittest.cc
+++ b/content/browser/download/base_file_unittest.cc
@@ -54,7 +54,7 @@
                                   GURL(),
                                   0,
                                   false,
-                                  "",
+                                  std::string(),
                                   scoped_ptr<net::FileStream>(),
                                   net::BoundNetLog()));
   }
@@ -105,7 +105,7 @@
                                   GURL(),
                                   0,
                                   true,
-                                  "",
+                                  std::string(),
                                   scoped_ptr<net::FileStream>(),
                                   net::BoundNetLog()));
   }
@@ -145,7 +145,7 @@
                   GURL(),
                   0,
                   false,
-                  "",
+                  std::string(),
                   scoped_ptr<net::FileStream>(),
                   net::BoundNetLog());
 
@@ -171,7 +171,7 @@
                             GURL(),
                             0,
                             false,
-                            "",
+                            std::string(),
                             scoped_ptr<net::FileStream>(),
                             net::BoundNetLog());
     EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE,
@@ -222,7 +222,7 @@
   DownloadInterruptReason expected_error_;
 
   // Mock file thread to satisfy debug checks in BaseFile.
-  MessageLoop message_loop_;
+  base::MessageLoop message_loop_;
   BrowserThreadImpl file_thread_;
 };
 
@@ -503,7 +503,7 @@
                                 GURL(),
                                 0,
                                 false,
-                                "",
+                                std::string(),
                                 mock_file_stream_scoped_ptr.Pass(),
                                 net::BoundNetLog()));
   ASSERT_TRUE(InitializeFile());
@@ -550,7 +550,7 @@
                                 GURL(),
                                 kTestDataLength4,
                                 false,
-                                "",
+                                std::string(),
                                 scoped_ptr<net::FileStream>(),
                                 net::BoundNetLog()));
 
@@ -584,7 +584,7 @@
                                 GURL(),
                                 0,
                                 false,
-                                "",
+                                std::string(),
                                 scoped_ptr<net::FileStream>(),
                                 net::BoundNetLog()));
 
@@ -609,7 +609,7 @@
   EXPECT_TRUE(BaseFile::IsEmptyHash(empty));
   std::string not_empty(BaseFile::kSha256HashLen, '\x01');
   EXPECT_FALSE(BaseFile::IsEmptyHash(not_empty));
-  EXPECT_FALSE(BaseFile::IsEmptyHash(""));
+  EXPECT_FALSE(BaseFile::IsEmptyHash(std::string()));
 }
 
 // Test that calculating speed after no writes.
diff --git a/content/browser/download/download_browsertest.cc b/content/browser/download/download_browsertest.cc
index 26e951a..f3ed766 100644
--- a/content/browser/download/download_browsertest.cc
+++ b/content/browser/download/download_browsertest.cc
@@ -29,7 +29,7 @@
 #include "content/test/net/url_request_mock_http_job.h"
 #include "content/test/net/url_request_slow_download_job.h"
 #include "googleurl/src/gurl.h"
-#include "net/test/test_server.h"
+#include "net/test/spawned_test_server.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -58,12 +58,28 @@
 
 class MockDownloadManagerObserver : public DownloadManager::Observer {
  public:
-  MockDownloadManagerObserver() {}
-  virtual ~MockDownloadManagerObserver() {}
+  MockDownloadManagerObserver(DownloadManager* manager) {
+    manager_ = manager;
+    manager->AddObserver(this);
+  }
+  virtual ~MockDownloadManagerObserver() {
+    if (manager_)
+      manager_->RemoveObserver(this);
+  }
 
   MOCK_METHOD2(OnDownloadCreated, void(DownloadManager*, DownloadItem*));
   MOCK_METHOD1(ModelChanged, void(DownloadManager*));
-  MOCK_METHOD1(ManagerGoingDown, void(DownloadManager*));
+  void ManagerGoingDown(DownloadManager* manager) {
+    DCHECK_EQ(manager_, manager);
+    MockManagerGoingDown(manager);
+
+    manager_->RemoveObserver(this);
+    manager_ = NULL;
+  }
+
+  MOCK_METHOD1(MockManagerGoingDown, void(DownloadManager*));
+ private:
+  DownloadManager* manager_;
 };
 
 class DownloadFileWithDelayFactory;
@@ -197,7 +213,7 @@
 }
 
 DownloadFileWithDelayFactory::DownloadFileWithDelayFactory()
-    : weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)),
+    : weak_ptr_factory_(this),
       waiting_(false) {}
 DownloadFileWithDelayFactory::~DownloadFileWithDelayFactory() {}
 
@@ -224,7 +240,7 @@
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   rename_callbacks_.push_back(callback);
   if (waiting_)
-    MessageLoopForUI::current()->Quit();
+    base::MessageLoopForUI::current()->Quit();
 }
 
 void DownloadFileWithDelayFactory::GetAllRenameCallbacks(
@@ -280,10 +296,12 @@
   // until data is returned.
   static int GetNumberActiveFilesFromFileThread() {
     int result = -1;
-    BrowserThread::PostTaskAndReply(BrowserThread::FILE, FROM_HERE,
+    BrowserThread::PostTaskAndReply(
+        BrowserThread::FILE,
+        FROM_HERE,
         base::Bind(&CountingDownloadFile::GetNumberActiveFiles, &result),
-        MessageLoop::current()->QuitClosure());
-    MessageLoop::current()->Run();
+        base::MessageLoop::current()->QuitClosure());
+    base::MessageLoop::current()->Run();
     DCHECK_NE(-1, result);
     return result;
   }
@@ -420,25 +438,25 @@
     manager_->AddObserver(this);
   }
 
-  ~DownloadCreateObserver() {
+  virtual ~DownloadCreateObserver() {
     if (manager_)
       manager_->RemoveObserver(this);
     manager_ = NULL;
   }
 
-  virtual void ManagerGoingDown(DownloadManager* manager) {
+  virtual void ManagerGoingDown(DownloadManager* manager) OVERRIDE {
     DCHECK_EQ(manager_, manager);
     manager_->RemoveObserver(this);
     manager_ = NULL;
   }
 
   virtual void OnDownloadCreated(DownloadManager* manager,
-                                 DownloadItem* download) {
+                                 DownloadItem* download) OVERRIDE {
     if (!item_)
       item_ = download;
 
     if (waiting_)
-      MessageLoopForUI::current()->Quit();
+      base::MessageLoopForUI::current()->Quit();
   }
 
   DownloadItem* WaitForFinished() {
@@ -552,9 +570,9 @@
     BrowserThread::PostTask(
         BrowserThread::IO, FROM_HERE,
         base::Bind(&EnsureNoPendingDownloadJobsOnIO, &result));
-    MessageLoop::current()->Run();
+    base::MessageLoop::current()->Run();
     return result &&
-        (CountingDownloadFile::GetNumberActiveFilesFromFileThread() == 0);
+           (CountingDownloadFile::GetNumberActiveFilesFromFileThread() == 0);
   }
 
   void DownloadAndWait(Shell* shell, const GURL& url,
@@ -663,7 +681,7 @@
     if (URLRequestSlowDownloadJob::NumberOutstandingRequests())
       *result = false;
     BrowserThread::PostTask(
-        BrowserThread::UI, FROM_HERE, MessageLoop::QuitClosure());
+        BrowserThread::UI, FROM_HERE, base::MessageLoop::QuitClosure());
   }
 
   // Location of the downloads directory for these tests
@@ -873,15 +891,15 @@
   // notifications in the right order.
   StrictMock<MockDownloadItemObserver> item_observer;
   items[0]->AddObserver(&item_observer);
-  MockDownloadManagerObserver manager_observer;
+  MockDownloadManagerObserver manager_observer(
+      DownloadManagerForShell(shell()));
   // Don't care about ModelChanged() events.
   EXPECT_CALL(manager_observer, ModelChanged(_))
       .WillRepeatedly(Return());
-  DownloadManagerForShell(shell())->AddObserver(&manager_observer);
   {
     InSequence notifications;
 
-    EXPECT_CALL(manager_observer, ManagerGoingDown(
+    EXPECT_CALL(manager_observer, MockManagerGoingDown(
         DownloadManagerForShell(shell())))
         .WillOnce(Return());
     EXPECT_CALL(item_observer, OnDownloadUpdated(
@@ -960,8 +978,12 @@
       base::StringPrintf("rangereset?size=%d&rst_boundary=%d",
                    GetSafeBufferChunk() * 3, GetSafeBufferChunk()));
 
+  MockDownloadManagerObserver dm_observer(DownloadManagerForShell(shell()));
+  EXPECT_CALL(dm_observer, OnDownloadCreated(_,_)).Times(1);
+
   DownloadItem* download(StartDownloadAndReturnItem(url));
   WaitForData(download, GetSafeBufferChunk());
+  ::testing::Mock::VerifyAndClearExpectations(&dm_observer);
 
   // Confirm resumption while in progress doesn't do anything.
   download->ResumeInterruptedDownload();
@@ -975,12 +997,15 @@
       base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));
 
   // Resume, confirming received bytes on resumption is correct.
+  // Make sure no creation calls are included.
+  EXPECT_CALL(dm_observer, OnDownloadCreated(_,_)).Times(0);
   int initial_size = 0;
   DownloadUpdatedObserver initial_size_observer(
       download, base::Bind(&InitialSizeFilter, &initial_size));
   download->ResumeInterruptedDownload();
   initial_size_observer.WaitForEvent();
   EXPECT_EQ(GetSafeBufferChunk(), initial_size);
+  ::testing::Mock::VerifyAndClearExpectations(&dm_observer);
 
   // and wait for expected data.
   WaitForData(download, GetSafeBufferChunk() * 2);
diff --git a/content/browser/download/download_file_impl.cc b/content/browser/download/download_file_impl.cc
index ab95900..9c064d2 100644
--- a/content/browser/download/download_file_impl.cc
+++ b/content/browser/download/download_file_impl.cc
@@ -50,7 +50,7 @@
           bytes_seen_(0),
           bound_net_log_(bound_net_log),
           observer_(observer),
-          weak_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)),
+          weak_factory_(this),
           power_save_blocker_(power_save_blocker.Pass()) {
 }
 
@@ -108,8 +108,8 @@
 
   base::FilePath new_path(full_path);
 
-  int uniquifier =
-      file_util::GetUniquePathNumber(new_path, FILE_PATH_LITERAL(""));
+  int uniquifier = file_util::GetUniquePathNumber(
+      new_path, base::FilePath::StringType());
   if (uniquifier > 0) {
     new_path = new_path.InsertBeforeExtensionASCII(
         base::StringPrintf(" (%d)", uniquifier));
diff --git a/content/browser/download/download_file_unittest.cc b/content/browser/download/download_file_unittest.cc
index 95e3a9c..982692e 100644
--- a/content/browser/download/download_file_unittest.cc
+++ b/content/browser/download/download_file_unittest.cc
@@ -77,7 +77,7 @@
 
   DownloadFileTest() :
       observer_(new StrictMock<MockDownloadDestinationObserver>),
-      observer_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(observer_.get())),
+      observer_factory_(observer_.get()),
       bytes_(-1),
       bytes_per_sec_(-1),
       hash_state_("xyzzy"),
@@ -302,7 +302,7 @@
   int64 bytes_per_sec_;
   std::string hash_state_;
 
-  MessageLoop loop_;
+  base::MessageLoop loop_;
 
  private:
   void SetRenameResult(bool* called_p,
@@ -592,8 +592,9 @@
   AppendDataToFile(chunks1, 2);
 
   // Run the message loops for 750ms and check for results.
-  loop_.PostDelayedTask(FROM_HERE, MessageLoop::QuitClosure(),
-                         base::TimeDelta::FromMilliseconds(750));
+  loop_.PostDelayedTask(FROM_HERE,
+                        base::MessageLoop::QuitClosure(),
+                        base::TimeDelta::FromMilliseconds(750));
   loop_.Run();
 
   EXPECT_EQ(static_cast<int64>(strlen(kTestData1) + strlen(kTestData2)),
diff --git a/content/browser/download/download_id_unittest.cc b/content/browser/download/download_id_unittest.cc
index 55e6494..ad84c91 100644
--- a/content/browser/download/download_id_unittest.cc
+++ b/content/browser/download/download_id_unittest.cc
@@ -44,7 +44,7 @@
 
  protected:
   scoped_refptr<DownloadManager> download_managers_[2];
-  MessageLoopForUI message_loop_;
+  base::MessageLoopForUI message_loop_;
   // Necessary to delete |DownloadManager|s.
   BrowserThreadImpl ui_thread_;
   size_t num_managers_;
diff --git a/content/browser/download/download_item_factory.h b/content/browser/download/download_item_factory.h
index 2e42c45..dfc15ec 100644
--- a/content/browser/download/download_item_factory.h
+++ b/content/browser/download/download_item_factory.h
@@ -57,14 +57,15 @@
 
   virtual DownloadItemImpl* CreateActiveItem(
       DownloadItemImplDelegate* delegate,
+      DownloadId download_id,
       const DownloadCreateInfo& info,
       const net::BoundNetLog& bound_net_log) = 0;
 
   virtual DownloadItemImpl* CreateSavePageItem(
       DownloadItemImplDelegate* delegate,
+      DownloadId download_id,
       const base::FilePath& path,
       const GURL& url,
-      DownloadId download_id,
       const std::string& mime_type,
       scoped_ptr<DownloadRequestHandleInterface> request_handle,
       const net::BoundNetLog& bound_net_log) = 0;
diff --git a/content/browser/download/download_item_impl.cc b/content/browser/download/download_item_impl.cc
index 1b43462..dfb915e 100644
--- a/content/browser/download/download_item_impl.cc
+++ b/content/browser/download/download_item_impl.cc
@@ -131,22 +131,20 @@
       opened_(opened),
       delegate_delayed_complete_(false),
       bound_net_log_(bound_net_log),
-      ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) {
+      weak_ptr_factory_(this) {
   delegate_->Attach();
-  if (state_ == IN_PROGRESS_INTERNAL) {
-    state_ = INTERRUPTED_INTERNAL;
-    last_reason_ = DOWNLOAD_INTERRUPT_REASON_CRASH;
-  }
+  DCHECK_NE(IN_PROGRESS_INTERNAL, state_);
   Init(false /* not actively downloading */, SRC_HISTORY_IMPORT);
 }
 
 // Constructing for a regular download:
 DownloadItemImpl::DownloadItemImpl(
     DownloadItemImplDelegate* delegate,
+    DownloadId download_id,
     const DownloadCreateInfo& info,
     const net::BoundNetLog& bound_net_log)
     : is_save_package_download_(false),
-      download_id_(info.download_id),
+      download_id_(download_id),
       target_disposition_(
           (info.save_info->prompt_for_save_location) ?
               TARGET_DISPOSITION_PROMPT : TARGET_DISPOSITION_OVERWRITE),
@@ -182,7 +180,7 @@
       opened_(false),
       delegate_delayed_complete_(false),
       bound_net_log_(bound_net_log),
-      ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) {
+      weak_ptr_factory_(this) {
   delegate_->Attach();
   Init(true /* actively downloading */, SRC_ACTIVE_DOWNLOAD);
 
@@ -199,9 +197,9 @@
 // Constructing for the "Save Page As..." feature:
 DownloadItemImpl::DownloadItemImpl(
     DownloadItemImplDelegate* delegate,
+    DownloadId download_id,
     const base::FilePath& path,
     const GURL& url,
-    DownloadId download_id,
     const std::string& mime_type,
     scoped_ptr<DownloadRequestHandleInterface> request_handle,
     const net::BoundNetLog& bound_net_log)
@@ -237,7 +235,7 @@
       opened_(false),
       delegate_delayed_complete_(false),
       bound_net_log_(bound_net_log),
-      ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) {
+      weak_ptr_factory_(this) {
   delegate_->Attach();
   Init(true /* actively downloading */, SRC_SAVE_PAGE_AS);
 }
@@ -349,7 +347,7 @@
   // |SavePackage| integration.
   // |download_file_| can be NULL if Interrupt() is called after the
   // download file has been released.
-  if (!is_save_package_download_ && download_file_.get())
+  if (!is_save_package_download_ && download_file_)
     ReleaseDownloadFile(true);
 
   if (state_ != INTERRUPTED_INTERNAL) {
@@ -690,7 +688,7 @@
   // paths that might be used by DownloadItems created from history import.
   // Currently such items have null request_handle_s, where other items
   // (regular and SavePackage downloads) have actual objects off the pointer.
-  if (request_handle_.get())
+  if (request_handle_)
     return request_handle_->GetWebContents();
   return NULL;
 }
@@ -1454,7 +1452,7 @@
   // |SavePackage| integration.
   // |download_file_| can be NULL if Interrupt() is called after the
   // download file has been released.
-  if (!is_save_package_download_ && download_file_.get()) {
+  if (!is_save_package_download_ && download_file_) {
     BrowserThread::PostTask(
         BrowserThread::FILE, FROM_HERE,
         // Will be deleted at end of task execution.
diff --git a/content/browser/download/download_item_impl.h b/content/browser/download/download_item_impl.h
index 25d1257..cc5e2b6 100644
--- a/content/browser/download/download_item_impl.h
+++ b/content/browser/download/download_item_impl.h
@@ -70,15 +70,16 @@
   // Constructing for a regular download.
   // |bound_net_log| is constructed externally for our use.
   DownloadItemImpl(DownloadItemImplDelegate* delegate,
+                   DownloadId download_id,
                    const DownloadCreateInfo& info,
                    const net::BoundNetLog& bound_net_log);
 
   // Constructing for the "Save Page As..." feature:
   // |bound_net_log| is constructed externally for our use.
   DownloadItemImpl(DownloadItemImplDelegate* delegate,
+                   DownloadId download_id,
                    const base::FilePath& path,
                    const GURL& url,
-                   DownloadId download_id,
                    const std::string& mime_type,
                    scoped_ptr<DownloadRequestHandleInterface> request_handle,
                    const net::BoundNetLog& bound_net_log);
diff --git a/content/browser/download/download_item_impl_unittest.cc b/content/browser/download/download_item_impl_unittest.cc
index 58c4f53..275b4d2 100644
--- a/content/browser/download/download_item_impl_unittest.cc
+++ b/content/browser/download/download_item_impl_unittest.cc
@@ -227,15 +227,16 @@
     scoped_ptr<DownloadCreateInfo> info_;
 
     info_.reset(new DownloadCreateInfo());
-    static int next_id;
-    info_->download_id = DownloadId(kValidDownloadItemIdDomain, ++next_id);
+    static int next_id = 0;
+    DownloadId id(DownloadId(kValidDownloadItemIdDomain, ++next_id));
     info_->save_info = scoped_ptr<DownloadSaveInfo>(new DownloadSaveInfo());
     info_->save_info->prompt_for_save_location = false;
     info_->url_chain.push_back(GURL());
     info_->etag = "SomethingToSatisfyResumption";
 
     DownloadItemImpl* download =
-        new DownloadItemImpl(&delegate_, *(info_.get()), net::BoundNetLog());
+        new DownloadItemImpl(
+            &delegate_, id, *(info_.get()), net::BoundNetLog());
     allocated_downloads_.insert(download);
     return download;
   }
@@ -324,7 +325,7 @@
   }
 
  private:
-  MessageLoopForUI loop_;
+  base::MessageLoopForUI loop_;
   TestBrowserThread ui_thread_;    // UI thread
   TestBrowserThread file_thread_;  // FILE thread
   StrictMock<MockDelegate> delegate_;
@@ -343,7 +344,7 @@
   DownloadItemImpl* item = CreateDownloadItem();
   MockObserver observer(item);
 
-  item->UpdateProgress(kDownloadChunkSize, kDownloadSpeed, "");
+  item->UpdateProgress(kDownloadChunkSize, kDownloadSpeed, std::string());
   ASSERT_TRUE(observer.CheckUpdated());
   EXPECT_EQ(kDownloadSpeed, item->CurrentSpeed());
 }
@@ -544,7 +545,7 @@
   DownloadItemImpl* safe_item = CreateDownloadItem();
   MockObserver safe_observer(safe_item);
 
-  safe_item->OnAllDataSaved("");
+  safe_item->OnAllDataSaved(std::string());
   EXPECT_TRUE(safe_observer.CheckUpdated());
   safe_item->OnContentCheckCompleted(DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS);
   EXPECT_TRUE(safe_observer.CheckUpdated());
@@ -554,7 +555,7 @@
       CreateDownloadItem();
   MockObserver unsafeurl_observer(unsafeurl_item);
 
-  unsafeurl_item->OnAllDataSaved("");
+  unsafeurl_item->OnAllDataSaved(std::string());
   EXPECT_TRUE(unsafeurl_observer.CheckUpdated());
   unsafeurl_item->OnContentCheckCompleted(DOWNLOAD_DANGER_TYPE_DANGEROUS_URL);
   EXPECT_TRUE(unsafeurl_observer.CheckUpdated());
@@ -566,7 +567,7 @@
       CreateDownloadItem();
   MockObserver unsafefile_observer(unsafefile_item);
 
-  unsafefile_item->OnAllDataSaved("");
+  unsafefile_item->OnAllDataSaved(std::string());
   EXPECT_TRUE(unsafefile_observer.CheckUpdated());
   unsafefile_item->OnContentCheckCompleted(DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE);
   EXPECT_TRUE(unsafefile_observer.CheckUpdated());
@@ -696,7 +697,7 @@
       .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE,
                                        final_path));
   EXPECT_CALL(*download_file, Detach());
-  item->DestinationObserverAsWeakPtr()->DestinationCompleted("");
+  item->DestinationObserverAsWeakPtr()->DestinationCompleted(std::string());
   RunAllPendingInMessageLoops();
   ::testing::Mock::VerifyAndClearExpectations(download_file);
   mock_delegate()->VerifyAndClearExpectations();
@@ -861,7 +862,7 @@
   EXPECT_CALL(*mock_delegate(), ShouldCompleteDownload(item, _))
       .WillOnce(Return(true));
   EXPECT_CALL(*download_file, Detach());
-  item->DestinationObserverAsWeakPtr()->DestinationCompleted("");
+  item->DestinationObserverAsWeakPtr()->DestinationCompleted(std::string());
   RunAllPendingInMessageLoops();
 
   ASSERT_TRUE(item->IsComplete());
@@ -888,7 +889,7 @@
       .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE,
                                        base::FilePath(kDummyPath)));
   EXPECT_CALL(*download_file, Detach());
-  item->DestinationObserverAsWeakPtr()->DestinationCompleted("");
+  item->DestinationObserverAsWeakPtr()->DestinationCompleted(std::string());
   RunAllPendingInMessageLoops();
 
   ASSERT_TRUE(item->IsComplete());
@@ -936,7 +937,7 @@
   // Drive the delegate interaction.
   EXPECT_CALL(*mock_delegate(), ShouldCompleteDownload(item, _))
       .WillOnce(Return(true));
-  item->DestinationObserverAsWeakPtr()->DestinationCompleted("");
+  item->DestinationObserverAsWeakPtr()->DestinationCompleted(std::string());
   EXPECT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
   EXPECT_FALSE(item->IsDangerous());
 
@@ -965,7 +966,7 @@
       .WillOnce(DoAll(SaveArg<1>(&delegate_callback),
                       Return(false)))
       .WillOnce(Return(true));
-  item->DestinationObserverAsWeakPtr()->DestinationCompleted("");
+  item->DestinationObserverAsWeakPtr()->DestinationCompleted(std::string());
   ASSERT_FALSE(delegate_callback.is_null());
   copy_delegate_callback = delegate_callback;
   delegate_callback.Reset();
@@ -1000,7 +1001,7 @@
       .WillOnce(DoAll(SaveArg<1>(&delegate_callback),
                       Return(false)))
       .WillOnce(Return(true));
-  item->DestinationObserverAsWeakPtr()->DestinationCompleted("");
+  item->DestinationObserverAsWeakPtr()->DestinationCompleted(std::string());
   ASSERT_FALSE(delegate_callback.is_null());
   copy_delegate_callback = delegate_callback;
   delegate_callback.Reset();
@@ -1046,7 +1047,7 @@
       .WillOnce(DoAll(SaveArg<1>(&delegate_callback),
                       Return(false)))
       .WillOnce(Return(true));
-  item->DestinationObserverAsWeakPtr()->DestinationCompleted("");
+  item->DestinationObserverAsWeakPtr()->DestinationCompleted(std::string());
   ASSERT_FALSE(delegate_callback.is_null());
   copy_delegate_callback = delegate_callback;
   delegate_callback.Reset();
diff --git a/content/browser/download/download_manager_impl.cc b/content/browser/download/download_manager_impl.cc
index 0e28d16..3fa9043 100644
--- a/content/browser/download/download_manager_impl.cc
+++ b/content/browser/download/download_manager_impl.cc
@@ -14,9 +14,9 @@
 #include "base/message_loop.h"
 #include "base/stl_util.h"
 #include "base/stringprintf.h"
+#include "base/strings/sys_string_conversions.h"
 #include "base/supports_user_data.h"
 #include "base/synchronization/lock.h"
-#include "base/sys_string_conversions.h"
 #include "build/build_config.h"
 #include "content/browser/byte_stream.h"
 #include "content/browser/download/download_create_info.h"
@@ -58,7 +58,7 @@
       params->resource_context()->GetRequestContext()->CreateRequest(
           params->url(), NULL));
   if (params->referrer().url.is_valid())
-    request->set_referrer(params->referrer().url.spec());
+    request->SetReferrer(params->referrer().url.spec());
   webkit_glue::ConfigureURLRequestForReferrerPolicy(
       request.get(), params->referrer().policy);
   request->set_load_flags(request->load_flags() | params->load_flags());
@@ -164,7 +164,7 @@
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
   *result = (DownloadFile::GetNumberOfDownloadFiles() == 0);
   BrowserThread::PostTask(
-        BrowserThread::UI, FROM_HERE, MessageLoop::QuitClosure());
+      BrowserThread::UI, FROM_HERE, base::MessageLoop::QuitClosure());
 }
 
 class DownloadItemFactoryImpl : public DownloadItemFactory {
@@ -208,20 +208,21 @@
 
   virtual DownloadItemImpl* CreateActiveItem(
       DownloadItemImplDelegate* delegate,
+      DownloadId download_id,
       const DownloadCreateInfo& info,
       const net::BoundNetLog& bound_net_log) OVERRIDE {
-      return new DownloadItemImpl(delegate, info, bound_net_log);
+    return new DownloadItemImpl(delegate, download_id, info, bound_net_log);
   }
 
   virtual DownloadItemImpl* CreateSavePageItem(
       DownloadItemImplDelegate* delegate,
+      DownloadId download_id,
       const base::FilePath& path,
       const GURL& url,
-      DownloadId download_id,
       const std::string& mime_type,
       scoped_ptr<DownloadRequestHandleInterface> request_handle,
       const net::BoundNetLog& bound_net_log) OVERRIDE {
-    return new DownloadItemImpl(delegate, path, url, download_id,
+    return new DownloadItemImpl(delegate, download_id, path, url,
                                 mime_type, request_handle.Pass(),
                                 bound_net_log);
   }
@@ -230,20 +231,30 @@
 }  // namespace
 
 DownloadManagerImpl::DownloadManagerImpl(
-    net::NetLog* net_log)
+    net::NetLog* net_log,
+    BrowserContext* browser_context)
     : item_factory_(new DownloadItemFactoryImpl()),
       file_factory_(new DownloadFileFactory()),
       history_size_(0),
-      shutdown_needed_(false),
-      browser_context_(NULL),
+      shutdown_needed_(true),
+      browser_context_(browser_context),
       delegate_(NULL),
       net_log_(net_log) {
+  DCHECK(browser_context);
 }
 
 DownloadManagerImpl::~DownloadManagerImpl() {
   DCHECK(!shutdown_needed_);
 }
 
+void DownloadManagerImpl::CreateActiveItem(
+    DownloadId id, const DownloadCreateInfo& info) {
+  net::BoundNetLog bound_net_log =
+      net::BoundNetLog::Make(net_log_, net::NetLog::SOURCE_DOWNLOAD);
+  downloads_[id.local()] =
+      item_factory_->CreateActiveItem(this, id, info, bound_net_log);
+}
+
 DownloadId DownloadManagerImpl::GetNextId() {
   DownloadId id;
   if (delegate_)
@@ -361,16 +372,6 @@
   delegate_ = NULL;
 }
 
-bool DownloadManagerImpl::Init(BrowserContext* browser_context) {
-  DCHECK(browser_context);
-  DCHECK(!shutdown_needed_)  << "DownloadManager already initialized.";
-  shutdown_needed_ = true;
-
-  browser_context_ = browser_context;
-
-  return true;
-}
-
 DownloadItem* DownloadManagerImpl::StartDownload(
     scoped_ptr<DownloadCreateInfo> info,
     scoped_ptr<ByteStreamReader> stream) {
@@ -384,10 +385,21 @@
                           &default_download_directory, &skip_dir_check);
   }
 
-  // We create the DownloadItem before the DownloadFile because the
-  // DownloadItem already needs to handle a state in which there is
-  // no associated DownloadFile (history downloads, !IN_PROGRESS downloads)
-  DownloadItemImpl* download = GetOrCreateDownloadItem(info.get());
+  // If we don't have a valid id, that's a signal to generate one.
+  DownloadId id(info->download_id);
+  if (!id.IsValid())
+    id = GetNextId();
+
+  // Create a new download item if this isn't a resumption.
+  bool new_download(!ContainsKey(downloads_, id.local()));
+  if (new_download)
+    CreateActiveItem(id, *info);
+
+  DownloadItemImpl* download(downloads_[id.local()]);
+  DCHECK(download);
+  DCHECK(new_download || download->IsInterrupted());
+
+  // Create the download file and start the download.
   scoped_ptr<DownloadFile> download_file(
       file_factory_->CreateFile(
           info->save_info.Pass(), default_download_directory,
@@ -399,9 +411,13 @@
       new DownloadRequestHandle(info->request_handle));
   download->Start(download_file.Pass(), req_handle.Pass());
 
-  // Delay notification until after Start() so that download_file is bound
-  // to download and all the usual setters (e.g. Cancel) work.
-  FOR_EACH_OBSERVER(Observer, observers_, OnDownloadCreated(this, download));
+  // For interrupted downloads, Start() will transition the state to
+  // IN_PROGRESS and consumers will be notified via OnDownloadUpdated().
+  // For new downloads, we notify here, rather than earlier, so that
+  // the download_file is bound to download and all the usual
+  // setters (e.g. Cancel) work.
+  if (new_download)
+    FOR_EACH_OBSERVER(Observer, observers_, OnDownloadCreated(this, download));
 
   return download;
 }
@@ -440,29 +456,6 @@
   return browser_context_;
 }
 
-DownloadItemImpl* DownloadManagerImpl::GetOrCreateDownloadItem(
-    DownloadCreateInfo* info) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
-  if (!info->download_id.IsValid())
-    info->download_id = GetNextId();
-
-  DownloadItemImpl* download = NULL;
-  if (ContainsKey(downloads_, info->download_id.local())) {
-    // Resuming an existing download.
-    download = downloads_[info->download_id.local()];
-    DCHECK(download->IsInterrupted());
-  } else {
-    // New download
-    net::BoundNetLog bound_net_log =
-        net::BoundNetLog::Make(net_log_, net::NetLog::SOURCE_DOWNLOAD);
-    download = item_factory_->CreateActiveItem(this, *info, bound_net_log);
-    downloads_[download->GetId()] = download;
-  }
-
-  return download;
-}
-
 DownloadItemImpl* DownloadManagerImpl::CreateSavePackageDownloadItem(
     const base::FilePath& main_file_path,
     const GURL& page_url,
@@ -473,9 +466,9 @@
       net::BoundNetLog::Make(net_log_, net::NetLog::SOURCE_DOWNLOAD);
   DownloadItemImpl* download_item = item_factory_->CreateSavePageItem(
       this,
+      GetNextId(),
       main_file_path,
       page_url,
-      GetNextId(),
       mime_type,
       request_handle.Pass(),
       bound_net_log);
diff --git a/content/browser/download/download_manager_impl.h b/content/browser/download/download_manager_impl.h
index ee6e6eb..6885068 100644
--- a/content/browser/download/download_manager_impl.h
+++ b/content/browser/download/download_manager_impl.h
@@ -35,7 +35,7 @@
  public:
   // Caller guarantees that |net_log| will remain valid
   // for the lifetime of DownloadManagerImpl (until Shutdown() is called).
-  DownloadManagerImpl(net::NetLog* net_log);
+  DownloadManagerImpl(net::NetLog* net_log, BrowserContext* browser_context);
 
   // Implementation functions (not part of the DownloadManager interface).
 
@@ -57,7 +57,6 @@
   virtual DownloadManagerDelegate* GetDelegate() const OVERRIDE;
   virtual void Shutdown() OVERRIDE;
   virtual void GetAllDownloads(DownloadVector* result) OVERRIDE;
-  virtual bool Init(BrowserContext* browser_context) OVERRIDE;
   virtual DownloadItem* StartDownload(
       scoped_ptr<DownloadCreateInfo> info,
       scoped_ptr<ByteStreamReader> stream) OVERRIDE;
@@ -107,11 +106,9 @@
 
   virtual ~DownloadManagerImpl();
 
-  // Retrieves the download item corresponding to the passed
-  // DownloadCreateInfo (generated on the IO thread).  This will create
-  // the download item if this is a new download (common case) or retrieve an
-  // existing download item if this is a resuming download.
-  virtual DownloadItemImpl* GetOrCreateDownloadItem(DownloadCreateInfo* info);
+  // Create a new active item based on the info.  Separate from
+  // StartDownload() for testing.
+  void CreateActiveItem(DownloadId id, const DownloadCreateInfo& info);
 
   // Get next download id.
   DownloadId GetNextId();
diff --git a/content/browser/download/download_manager_impl_unittest.cc b/content/browser/download/download_manager_impl_unittest.cc
index bd34e7e..2abb8f9 100644
--- a/content/browser/download/download_manager_impl_unittest.cc
+++ b/content/browser/download/download_manager_impl_unittest.cc
@@ -76,7 +76,7 @@
           base::Time(),
           0,
           0,
-          DownloadItem::IN_PROGRESS,
+          DownloadItem::COMPLETE,
           DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
           DOWNLOAD_INTERRUPT_REASON_NONE,
           false,
@@ -169,7 +169,9 @@
   MOCK_CONST_METHOD0(GetUserVerifiedFilePath, base::FilePath());
   MOCK_METHOD0(NotifyRemoved, void());
   // May be called when vlog is on.
-  virtual std::string DebugString(bool verbose) const OVERRIDE { return ""; }
+  virtual std::string DebugString(bool verbose) const OVERRIDE {
+    return std::string();
+  }
 };
 
 class MockDownloadManagerDelegate : public DownloadManagerDelegate {
@@ -240,14 +242,15 @@
       const net::BoundNetLog& bound_net_log) OVERRIDE;
   virtual DownloadItemImpl* CreateActiveItem(
       DownloadItemImplDelegate* delegate,
+      DownloadId download_id,
       const DownloadCreateInfo& info,
       const net::BoundNetLog& bound_net_log) OVERRIDE;
   virtual DownloadItemImpl* CreateSavePageItem(
       DownloadItemImplDelegate* delegate,
+      DownloadId download_id,
       const base::FilePath& path,
       const GURL& url,
-      DownloadId download_id,
-      const std::string& mime_type,
+        const std::string& mime_type,
       scoped_ptr<DownloadRequestHandleInterface> request_handle,
       const net::BoundNetLog& bound_net_log) OVERRIDE;
 
@@ -314,9 +317,10 @@
 
 DownloadItemImpl* MockDownloadItemFactory::CreateActiveItem(
     DownloadItemImplDelegate* delegate,
+    DownloadId download_id,
     const DownloadCreateInfo& info,
     const net::BoundNetLog& bound_net_log) {
-  int local_id = info.download_id.local();
+  int local_id = download_id.local();
   DCHECK(items_.find(local_id) == items_.end());
 
   MockDownloadItemImpl* result =
@@ -324,7 +328,7 @@
   EXPECT_CALL(*result, GetId())
       .WillRepeatedly(Return(local_id));
   EXPECT_CALL(*result, GetGlobalId())
-      .WillRepeatedly(Return(DownloadId(delegate, local_id)));
+      .WillRepeatedly(Return(download_id));
   items_[local_id] = result;
 
   // Active items are created and then immediately are called to start
@@ -336,9 +340,9 @@
 
 DownloadItemImpl* MockDownloadItemFactory::CreateSavePageItem(
     DownloadItemImplDelegate* delegate,
+    DownloadId download_id,
     const base::FilePath& path,
     const GURL& url,
-    DownloadId download_id,
     const std::string& mime_type,
     scoped_ptr<DownloadRequestHandleInterface> request_handle,
     const net::BoundNetLog& bound_net_log) {
@@ -454,7 +458,8 @@
     EXPECT_CALL(*mock_browser_context_.get(), IsOffTheRecord())
         .WillRepeatedly(Return(false));
 
-    download_manager_ = new DownloadManagerImpl(NULL);
+    download_manager_ = new DownloadManagerImpl(
+        NULL, mock_browser_context_.get());
     download_manager_->SetDownloadItemFactoryForTesting(
         scoped_ptr<DownloadItemFactory>(
             mock_download_item_factory_.get()).Pass());
@@ -464,7 +469,6 @@
     observer_.reset(new MockDownloadManagerObserver());
     download_manager_->AddObserver(observer_.get());
     download_manager_->SetDelegate(mock_download_manager_delegate_.get());
-    download_manager_->Init(mock_browser_context_.get());
   }
 
   virtual void TearDown() {
@@ -498,10 +502,9 @@
     // null.
     int id = next_download_id_;
     ++next_download_id_;
-    info.download_id = DownloadId(kDownloadIdDomain, id);
     info.request_handle = DownloadRequestHandle();
-    download_manager_->GetOrCreateDownloadItem(&info);
-
+    download_manager_->CreateActiveItem(DownloadId(kDownloadIdDomain, id),
+                                        info);
     DCHECK(mock_download_item_factory_->GetItem(id));
     MockDownloadItemImpl& item(*mock_download_item_factory_->GetItem(id));
     // Satisfy expectation.  If the item is created in StartDownload(),
@@ -565,7 +568,7 @@
   base::FilePath intermediate_path_;
 
  private:
-  MessageLoopForUI message_loop_;
+  base::MessageLoopForUI message_loop_;
   TestBrowserThread ui_thread_;
   TestBrowserThread file_thread_;
   base::WeakPtr<MockDownloadItemFactory> mock_download_item_factory_;
diff --git a/content/browser/download/download_resource_handler.cc b/content/browser/download/download_resource_handler.cc
index a803d01..388bcd1 100644
--- a/content/browser/download/download_resource_handler.cc
+++ b/content/browser/download/download_resource_handler.cc
@@ -380,7 +380,7 @@
 
   // Send the info down the stream.  Conditional is in case we get
   // OnResponseCompleted without OnResponseStarted.
-  if (stream_writer_.get())
+  if (stream_writer_)
     stream_writer_->Close(reason);
 
   // If the error mapped to something unknown, record it so that
@@ -480,7 +480,7 @@
   CallStartedCB(NULL, net::ERR_ACCESS_DENIED);
 
   // Remove output stream callback if a stream exists.
-  if (stream_writer_.get())
+  if (stream_writer_)
     stream_writer_->RegisterCallback(base::Closure());
 
   UMA_HISTOGRAM_TIMES("SB2.DownloadDuration",
diff --git a/content/browser/download/download_stats.cc b/content/browser/download/download_stats.cc
index cad6cbe..e13200e 100644
--- a/content/browser/download/download_stats.cc
+++ b/content/browser/download/download_stats.cc
@@ -305,8 +305,8 @@
     const std::string& content_disposition_string) {
   if (content_disposition_string.empty())
     return;
-  net::HttpContentDisposition content_disposition(
-      content_disposition_string, "");
+  net::HttpContentDisposition content_disposition(content_disposition_string,
+                                                  std::string());
   int result = content_disposition.parse_result_flags();
 
   bool is_valid = !content_disposition.filename().empty();
diff --git a/content/browser/download/drag_download_file.cc b/content/browser/download/drag_download_file.cc
index d87a7e0..5bbc9cb 100644
--- a/content/browser/download/drag_download_file.cc
+++ b/content/browser/download/drag_download_file.cc
@@ -37,7 +37,7 @@
                      const Referrer& referrer,
                      const std::string& referrer_encoding,
                      WebContents* web_contents,
-                     MessageLoop* on_completed_loop,
+                     base::MessageLoop* on_completed_loop,
                      const OnCompleted& on_completed)
       : on_completed_loop_(on_completed_loop),
         on_completed_(on_completed),
@@ -46,7 +46,7 @@
         referrer_encoding_(referrer_encoding),
         web_contents_(web_contents),
         download_item_(NULL),
-        ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) {
+        weak_ptr_factory_(this) {
     DCHECK(on_completed_loop_);
     DCHECK(!on_completed_.is_null());
     DCHECK(web_contents_);
@@ -132,7 +132,7 @@
     download_item_ = NULL;
   }
 
-  MessageLoop* on_completed_loop_;
+  base::MessageLoop* on_completed_loop_;
   OnCompleted on_completed_;
   GURL url_;
   Referrer referrer_;
@@ -154,10 +154,10 @@
                                    WebContents* web_contents)
     : file_path_(file_path),
       file_stream_(file_stream.Pass()),
-      drag_message_loop_(MessageLoop::current()),
+      drag_message_loop_(base::MessageLoop::current()),
       state_(INITIALIZED),
       drag_ui_(NULL),
-      ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) {
+      weak_ptr_factory_(this) {
   drag_ui_ = new DragDownloadFileUI(
       url,
       referrer,
@@ -231,7 +231,7 @@
 
 void DragDownloadFile::CheckThread() {
 #if defined(OS_WIN)
-  DCHECK(drag_message_loop_ == MessageLoop::current());
+  DCHECK(drag_message_loop_ == base::MessageLoop::current());
 #else
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 #endif
diff --git a/content/browser/download/drag_download_file.h b/content/browser/download/drag_download_file.h
index e97f585..2151d44 100644
--- a/content/browser/download/drag_download_file.h
+++ b/content/browser/download/drag_download_file.h
@@ -63,7 +63,7 @@
 
   base::FilePath file_path_;
   scoped_ptr<net::FileStream> file_stream_;
-  MessageLoop* drag_message_loop_;
+  base::MessageLoop* drag_message_loop_;
   State state_;
   scoped_refptr<ui::DownloadFileObserver> observer_;
   base::RunLoop nested_loop_;
diff --git a/content/browser/download/drag_download_file_browsertest.cc b/content/browser/download/drag_download_file_browsertest.cc
index e35cbfb..ebbec59 100644
--- a/content/browser/download/drag_download_file_browsertest.cc
+++ b/content/browser/download/drag_download_file_browsertest.cc
@@ -52,9 +52,9 @@
   virtual ~DragDownloadFileTest() {}
 
   void Succeed() {
-    BrowserThread::PostTask(
-        BrowserThread::UI, FROM_HERE,
-        MessageLoopForUI::current()->QuitClosure());
+    BrowserThread::PostTask(BrowserThread::UI,
+                            FROM_HERE,
+                            base::MessageLoopForUI::current()->QuitClosure());
   }
 
   void FailFast() {
@@ -116,10 +116,6 @@
   Referrer referrer;
   std::string referrer_encoding;
   net::FileStream* stream = NULL;
-#if defined(OS_POSIX)
-  stream = CreateFileStreamForDrop(
-      &name, GetContentClient()->browser()->GetNetLog());
-#endif
   SetUpServer();
   DragDownloadFile* file = new DragDownloadFile(
       name, scoped_ptr<net::FileStream>(stream), url, referrer,
diff --git a/content/browser/download/drag_download_util.cc b/content/browser/download/drag_download_util.cc
index ea1c897..c69829c 100644
--- a/content/browser/download/drag_download_util.cc
+++ b/content/browser/download/drag_download_util.cc
@@ -114,7 +114,7 @@
 PromiseFileFinalizer::~PromiseFileFinalizer() {}
 
 void PromiseFileFinalizer::Cleanup() {
-  if (drag_file_downloader_.get())
+  if (drag_file_downloader_)
     drag_file_downloader_ = NULL;
 }
 
diff --git a/content/browser/download/mhtml_generation_browsertest.cc b/content/browser/download/mhtml_generation_browsertest.cc
index 6944a6c..26835dd 100644
--- a/content/browser/download/mhtml_generation_browsertest.cc
+++ b/content/browser/download/mhtml_generation_browsertest.cc
@@ -12,7 +12,7 @@
 #include "content/shell/shell.h"
 #include "content/test/content_browser_test.h"
 #include "content/test/content_browser_test_utils.h"
-#include "net/test/test_server.h"
+#include "net/test/spawned_test_server.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace content {
@@ -24,7 +24,7 @@
   void MHTMLGenerated(const base::FilePath& path, int64 size) {
     mhtml_generated_ = true;
     file_size_ = size;
-    MessageLoopForUI::current()->Quit();
+    base::MessageLoopForUI::current()->Quit();
   }
 
  protected:
diff --git a/content/browser/download/save_file.cc b/content/browser/download/save_file.cc
index 3e7f7bd..80caf13 100644
--- a/content/browser/download/save_file.cc
+++ b/content/browser/download/save_file.cc
@@ -20,7 +20,7 @@
             GURL(),
             0,
             calculate_hash,
-            "",
+            std::string(),
             scoped_ptr<net::FileStream>(),
             net::BoundNetLog()),
       info_(info) {
diff --git a/content/browser/download/save_package.cc b/content/browser/download/save_package.cc
index c5171ee..7553a54 100644
--- a/content/browser/download/save_package.cc
+++ b/content/browser/download/save_package.cc
@@ -13,9 +13,9 @@
 #include "base/logging.h"
 #include "base/message_loop.h"
 #include "base/stl_util.h"
-#include "base/string_piece.h"
+#include "base/strings/string_piece.h"
 #include "base/strings/string_split.h"
-#include "base/sys_string_conversions.h"
+#include "base/strings/sys_string_conversions.h"
 #include "base/threading/thread.h"
 #include "base/utf_string_conversions.h"
 #include "content/browser/download/download_item_impl.h"
@@ -365,7 +365,7 @@
   // with SavePackage flow.
   if (download_->IsInProgress()) {
     download_->SetTotalBytes(size);
-    download_->UpdateProgress(size, 0, "");
+    download_->UpdateProgress(size, 0, std::string());
     // Must call OnAllDataSaved here in order for
     // GDataDownloadObserver::ShouldUpload() to return true.
     // ShouldCompleteDownload() may depend on the gdata uploader to finish.
@@ -424,7 +424,7 @@
                                           dir_path.value().length() -
                                           file_name_ext.length());
   // Need an extra space for the separator.
-  if (!file_util::EndsWithSeparator(dir_path))
+  if (!dir_path.EndsWithSeparator())
     --available_length;
 
   // Plenty of room.
@@ -449,7 +449,11 @@
                                    base::FilePath::StringType* generated_name) {
   // TODO(jungshik): Figure out the referrer charset when having one
   // makes sense and pass it to GenerateFileName.
-  base::FilePath file_path = net::GenerateFileName(url, disposition, "", "", "",
+  base::FilePath file_path = net::GenerateFileName(url,
+                                                   disposition,
+                                                   std::string(),
+                                                   std::string(),
+                                                   std::string(),
                                                    kDefaultSaveName);
 
   DCHECK(!file_path.empty());
@@ -788,7 +792,8 @@
     // with SavePackage flow.
     if (download_->IsInProgress()) {
       if (save_type_ != SAVE_PAGE_TYPE_AS_MHTML) {
-        download_->UpdateProgress(all_save_items_count_, CurrentSpeed(), "");
+        download_->UpdateProgress(
+            all_save_items_count_, CurrentSpeed(), std::string());
         download_->OnAllDataSaved(DownloadItem::kEmptyFileHash);
       }
       download_->MarkAsComplete();
@@ -818,7 +823,7 @@
   // TODO(rdsmith/benjhayden): Integrate canceling on DownloadItem
   // with SavePackage flow.
   if (download_ && download_->IsInProgress())
-    download_->UpdateProgress(completed_count(), CurrentSpeed(), "");
+    download_->UpdateProgress(completed_count(), CurrentSpeed(), std::string());
 
   if (save_item->save_source() == SaveFileCreateInfo::SAVE_FILE_FROM_DOM &&
       save_item->url() == page_url_ && !save_item->received_bytes()) {
@@ -863,7 +868,7 @@
   // TODO(rdsmith/benjhayden): Integrate canceling on DownloadItem
   // with SavePackage flow.
   if (download_ && download_->IsInProgress())
-    download_->UpdateProgress(completed_count(), CurrentSpeed(), "");
+    download_->UpdateProgress(completed_count(), CurrentSpeed(), std::string());
 
   if ((save_type_ == SAVE_PAGE_TYPE_AS_ONLY_HTML) ||
       (save_type_ == SAVE_PAGE_TYPE_AS_MHTML) ||
diff --git a/content/browser/download/save_package_unittest.cc b/content/browser/download/save_package_unittest.cc
index b5a07ae..e40af08 100644
--- a/content/browser/download/save_package_unittest.cc
+++ b/content/browser/download/save_package_unittest.cc
@@ -221,20 +221,21 @@
 
   base::FilePath::StringType filename;
   // Test that the filename is successfully shortened to fit.
-  ASSERT_TRUE(GetGeneratedFilename(true, "", url, false, &filename));
+  ASSERT_TRUE(GetGeneratedFilename(true, std::string(), url, false, &filename));
   EXPECT_TRUE(filename.length() < long_file.length());
   EXPECT_FALSE(HasOrdinalNumber(filename));
 
   // Test that the filename is successfully shortened to fit, and gets an
   // an ordinal appended.
-  ASSERT_TRUE(GetGeneratedFilename(true, "", url, false, &filename));
+  ASSERT_TRUE(GetGeneratedFilename(true, std::string(), url, false, &filename));
   EXPECT_TRUE(filename.length() < long_file.length());
   EXPECT_TRUE(HasOrdinalNumber(filename));
 
   // Test that the filename is successfully shortened to fit, and gets a
   // different ordinal appended.
   base::FilePath::StringType filename2;
-  ASSERT_TRUE(GetGeneratedFilename(true, "", url, false, &filename2));
+  ASSERT_TRUE(
+      GetGeneratedFilename(true, std::string(), url, false, &filename2));
   EXPECT_TRUE(filename2.length() < long_file.length());
   EXPECT_TRUE(HasOrdinalNumber(filename2));
   EXPECT_NE(filename, filename2);
diff --git a/content/browser/fileapi/browser_file_system_helper.cc b/content/browser/fileapi/browser_file_system_helper.cc
index 710c3bd..75a8aae7 100644
--- a/content/browser/fileapi/browser_file_system_helper.cc
+++ b/content/browser/fileapi/browser_file_system_helper.cc
@@ -12,7 +12,10 @@
 #include "base/threading/sequenced_worker_pool.h"
 #include "content/browser/child_process_security_policy_impl.h"
 #include "content/public/browser/browser_thread.h"
+#include "content/public/browser/content_browser_client.h"
+#include "content/public/common/content_client.h"
 #include "content/public/common/content_switches.h"
+#include "content/public/common/url_constants.h"
 #include "webkit/fileapi/external_mount_points.h"
 #include "webkit/fileapi/file_permission_policy.h"
 #include "webkit/fileapi/file_system_options.h"
@@ -22,34 +25,33 @@
 #include "webkit/quota/quota_manager.h"
 
 namespace content {
-namespace {
 
-const char kChromeScheme[] = "chrome";
-const char kExtensionScheme[] = "chrome-extension";
+namespace {
 
 using fileapi::FileSystemOptions;
 
 FileSystemOptions CreateBrowserFileSystemOptions(bool is_incognito) {
-  std::vector<std::string> additional_allowed_schemes;
-  additional_allowed_schemes.push_back(kChromeScheme);
-  additional_allowed_schemes.push_back(kExtensionScheme);
-  if (CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kAllowFileAccessFromFiles)) {
-    additional_allowed_schemes.push_back("file");
-  }
   FileSystemOptions::ProfileMode profile_mode =
       is_incognito ? FileSystemOptions::PROFILE_MODE_INCOGNITO
                    : FileSystemOptions::PROFILE_MODE_NORMAL;
+  std::vector<std::string> additional_allowed_schemes;
+  GetContentClient()->browser()->GetAdditionalAllowedSchemesForFileSystem(
+      &additional_allowed_schemes);
+  if (CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kAllowFileAccessFromFiles)) {
+    additional_allowed_schemes.push_back(chrome::kFileScheme);
+  }
   return FileSystemOptions(profile_mode, additional_allowed_schemes);
 }
 
-}  // anonymous namespace
+}  // namespace
 
 scoped_refptr<fileapi::FileSystemContext> CreateFileSystemContext(
-        const base::FilePath& profile_path, bool is_incognito,
-        fileapi::ExternalMountPoints* external_mount_points,
-        quota::SpecialStoragePolicy* special_storage_policy,
-        quota::QuotaManagerProxy* quota_manager_proxy) {
+    const base::FilePath& profile_path,
+    bool is_incognito,
+    fileapi::ExternalMountPoints* external_mount_points,
+    quota::SpecialStoragePolicy* special_storage_policy,
+    quota::QuotaManagerProxy* quota_manager_proxy) {
   base::SequencedWorkerPool* pool = BrowserThread::GetBlockingPool();
   base::SequencedWorkerPool::SequenceToken media_sequence_token =
       pool->GetNamedSequenceToken(fileapi::kMediaTaskRunnerName);
@@ -60,11 +62,17 @@
           BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE),
           pool->GetSequencedTaskRunner(media_sequence_token)));
 
+  // Setting up additional mount point providers.
+  ScopedVector<fileapi::FileSystemMountPointProvider> additional_providers;
+  GetContentClient()->browser()->GetAdditionalFileSystemMountPointProviders(
+      profile_path, &additional_providers);
+
   return new fileapi::FileSystemContext(
       task_runners.Pass(),
       external_mount_points,
       special_storage_policy,
       quota_manager_proxy,
+      additional_providers.Pass(),
       profile_path,
       CreateBrowserFileSystemOptions(is_incognito));
 }
diff --git a/content/browser/fileapi/file_system_browsertest.cc b/content/browser/fileapi/file_system_browsertest.cc
index 74633a0..6fe2f8c 100644
--- a/content/browser/fileapi/file_system_browsertest.cc
+++ b/content/browser/fileapi/file_system_browsertest.cc
@@ -17,7 +17,7 @@
 #include "content/test/content_browser_test.h"
 #include "content/test/content_browser_test_utils.h"
 #include "content/test/layout_browsertest.h"
-#include "net/test/test_server.h"
+#include "net/test/spawned_test_server.h"
 #include "webkit/quota/quota_manager.h"
 
 using quota::QuotaManager;
diff --git a/content/browser/fileapi/fileapi_message_filter.cc b/content/browser/fileapi/fileapi_message_filter.cc
index 7472115..966490e 100644
--- a/content/browser/fileapi/fileapi_message_filter.cc
+++ b/content/browser/fileapi/fileapi_message_filter.cc
@@ -35,6 +35,7 @@
 #include "webkit/fileapi/isolated_context.h"
 #include "webkit/fileapi/local_file_system_operation.h"
 #include "webkit/fileapi/sandbox_mount_point_provider.h"
+#include "webkit/quota/quota_manager.h"
 
 using fileapi::FileSystemFileUtil;
 using fileapi::FileSystemMountPointProvider;
@@ -89,7 +90,7 @@
 void FileAPIMessageFilter::OnChannelConnected(int32 peer_pid) {
   BrowserMessageFilter::OnChannelConnected(peer_pid);
 
-  if (request_context_getter_.get()) {
+  if (request_context_getter_) {
     DCHECK(!request_context_);
     request_context_ = request_context_getter_->GetURLRequestContext();
     request_context_getter_ = NULL;
@@ -110,20 +111,18 @@
   in_transit_snapshot_files_.clear();
 
   // Close all files that are previously OpenFile()'ed in this process.
-  if (!open_filesystem_urls_.empty()) {
+  if (!on_close_callbacks_.IsEmpty()) {
     DLOG(INFO)
         << "File API: Renderer process shut down before NotifyCloseFile"
-        << " for " << open_filesystem_urls_.size() << " files opened in PPAPI";
+        << " for " << on_close_callbacks_.size() << " files opened in PPAPI";
   }
-  for (std::multiset<GURL>::const_iterator iter =
-       open_filesystem_urls_.begin();
-       iter != open_filesystem_urls_.end(); ++iter) {
-    FileSystemURL url(context_->CrackURL(*iter));
-    FileSystemOperation* operation = context_->CreateFileSystemOperation(
-        url, NULL);
-    if (operation)
-      operation->NotifyCloseFile(url);
+
+  for (OnCloseCallbackMap::iterator itr(&on_close_callbacks_);
+       !itr.IsAtEnd(); itr.Advance()) {
+    itr.GetCurrentValue()->Run();
   }
+
+  on_close_callbacks_.Clear();
 }
 
 void FileAPIMessageFilter::OverrideThreadForMessage(
@@ -157,8 +156,6 @@
                         OnCreateSnapshotFile)
     IPC_MESSAGE_HANDLER(FileSystemHostMsg_DidReceiveSnapshotFile,
                         OnDidReceiveSnapshotFile)
-    IPC_MESSAGE_HANDLER(FileSystemHostMsg_CreateSnapshotFile_Deprecated,
-                        OnCreateSnapshotFile_Deprecated)
     IPC_MESSAGE_HANDLER(FileSystemHostMsg_WillUpdate, OnWillUpdate)
     IPC_MESSAGE_HANDLER(FileSystemHostMsg_DidUpdate, OnDidUpdate)
     IPC_MESSAGE_HANDLER(FileSystemHostMsg_SyncGetPlatformPath,
@@ -453,31 +450,39 @@
     return;
   }
 
+  quota::QuotaLimitType quota_policy = quota::kQuotaLimitTypeUnknown;
+  quota::QuotaManagerProxy* quota_manager_proxy =
+      context_->quota_manager_proxy();
+  CHECK(quota_manager_proxy);
+  CHECK(quota_manager_proxy->quota_manager());
+
+  if (quota_manager_proxy->quota_manager()->IsStorageUnlimited(
+          url.origin(), FileSystemTypeToQuotaStorageType(url.type()))) {
+    quota_policy = quota::kQuotaLimitTypeUnlimited;
+  } else {
+    quota_policy = quota::kQuotaLimitTypeLimited;
+  }
+
   FileSystemOperation* operation = GetNewOperation(url, request_id);
   if (!operation)
     return;
   operation->OpenFile(
       url, file_flags, peer_handle(),
-      base::Bind(&FileAPIMessageFilter::DidOpenFile, this, request_id, path));
+      base::Bind(&FileAPIMessageFilter::DidOpenFile, this, request_id,
+                 quota_policy));
 }
 
-void FileAPIMessageFilter::OnNotifyCloseFile(const GURL& path) {
+void FileAPIMessageFilter::OnNotifyCloseFile(int file_open_id) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
 
-  // Remove |path| from the set of opened urls. It must only be called for a URL
-  // that is successfully opened and enrolled in DidOpenFile.
-  std::multiset<GURL>::iterator iter = open_filesystem_urls_.find(path);
-  DCHECK(iter != open_filesystem_urls_.end());
-  open_filesystem_urls_.erase(iter);
-
-  FileSystemURL url(context_->CrackURL(path));
-
-  // Do not use GetNewOperation() here, because NotifyCloseFile is a one-way
-  // operation that does not have request_id by which we respond back.
-  FileSystemOperation* operation = context_->CreateFileSystemOperation(
-      url, NULL);
-  if (operation)
-    operation->NotifyCloseFile(url);
+  // Remove |file_open_id| from the map of |on_close_callback|s.
+  // It must only be called for a ID that is successfully opened and enrolled in
+  // DidOpenFile.
+  base::Closure* on_close_callback = on_close_callbacks_.Lookup(file_open_id);
+  if (on_close_callback && !on_close_callback->is_null()) {
+    on_close_callback->Run();
+    on_close_callbacks_.Remove(file_open_id);
+  }
 }
 
 void FileAPIMessageFilter::OnWillUpdate(const GURL& path) {
@@ -538,32 +543,6 @@
   in_transit_snapshot_files_.erase(request_id);
 }
 
-void FileAPIMessageFilter::OnCreateSnapshotFile_Deprecated(
-    int request_id, const GURL& blob_url, const GURL& path) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-  FileSystemURL url(context_->CrackURL(path));
-  base::Callback<void(const base::FilePath&)> register_file_callback =
-      base::Bind(&FileAPIMessageFilter::RegisterFileAsBlob,
-                 this, blob_url, url);
-
-  // Make sure if this file can be read by the renderer as this is
-  // called when the renderer is about to create a new File object
-  // (for reading the file).
-  base::PlatformFileError error;
-  if (!HasPermissionsForFile(url, fileapi::kReadFilePermissions, &error)) {
-    Send(new FileSystemMsg_DidFail(request_id, error));
-    return;
-  }
-
-  FileSystemOperation* operation = GetNewOperation(url, request_id);
-  if (!operation)
-    return;
-  operation->CreateSnapshotFile(
-      url,
-      base::Bind(&FileAPIMessageFilter::DidCreateSnapshot_Deprecated,
-                 this, request_id, register_file_callback));
-}
-
 void FileAPIMessageFilter::OnStartBuildingBlob(const GURL& url) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
   blob_storage_context_->controller()->StartBuildingBlob(url);
@@ -681,19 +660,26 @@
 }
 
 void FileAPIMessageFilter::DidOpenFile(int request_id,
-                                       const GURL& path,
+                                       quota::QuotaLimitType quota_policy,
                                        base::PlatformFileError result,
                                        base::PlatformFile file,
+                                       const base::Closure& on_close_callback,
                                        base::ProcessHandle peer_handle) {
   if (result == base::PLATFORM_FILE_OK) {
     IPC::PlatformFileForTransit file_for_transit =
         file != base::kInvalidPlatformFileValue ?
             IPC::GetFileHandleForProcess(file, peer_handle, true) :
             IPC::InvalidPlatformFileForTransit();
-    open_filesystem_urls_.insert(path);
-    Send(new FileSystemMsg_DidOpenFile(request_id, file_for_transit));
+    int file_open_id = on_close_callbacks_.Add(
+        new base::Closure(on_close_callback));
+
+    Send(new FileSystemMsg_DidOpenFile(request_id,
+                                       file_for_transit,
+                                       file_open_id,
+                                       quota_policy));
   } else {
-    Send(new FileSystemMsg_DidFail(request_id, result));
+    Send(new FileSystemMsg_DidFail(request_id,
+                                   result));
   }
   UnregisterOperation(request_id);
 }
@@ -766,7 +752,7 @@
     //   already been granted read permission for the file's nominal path, but
     //   for drive files, platform paths differ from the nominal paths.
     DCHECK(snapshot_file ||
-           fileapi::SandboxMountPointProvider::CanHandleType(url.type()) ||
+           fileapi::SandboxMountPointProvider::IsSandboxType(url.type()) ||
            url.type() == fileapi::kFileSystemTypeDrive);
     ChildProcessSecurityPolicyImpl::GetInstance()->GrantReadFile(
         process_id_, platform_path);
@@ -788,80 +774,6 @@
                request_id, info, platform_path));
 }
 
-void FileAPIMessageFilter::DidCreateSnapshot_Deprecated(
-    int request_id,
-    const base::Callback<void(const base::FilePath&)>& register_file_callback,
-    base::PlatformFileError result,
-    const base::PlatformFileInfo& info,
-    const base::FilePath& platform_path,
-    const scoped_refptr<webkit_blob::ShareableFileReference>& unused) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-  if (result != base::PLATFORM_FILE_OK) {
-    Send(new FileSystemMsg_DidFail(request_id, result));
-    return;
-  }
-
-  // Register the created file to the blob registry by calling
-  // RegisterFileAsBlob.
-  // Blob storage automatically finds and refs the file_ref, so we don't
-  // need to do anything for the returned file reference (|unused|) here.
-  register_file_callback.Run(platform_path);
-
-  // Return the file info and platform_path.
-  Send(new FileSystemMsg_DidReadMetadata(request_id, info, platform_path));
-}
-
-void FileAPIMessageFilter::RegisterFileAsBlob(
-    const GURL& blob_url,
-    const FileSystemURL& url,
-    const base::FilePath& platform_path) {
-  // Use the virtual path's extension to determine MIME type.
-  base::FilePath::StringType extension = url.path().Extension();
-  if (!extension.empty())
-    extension = extension.substr(1);  // Strip leading ".".
-
-  scoped_refptr<webkit_blob::ShareableFileReference> shareable_file =
-      webkit_blob::ShareableFileReference::Get(platform_path);
-  if (!ChildProcessSecurityPolicyImpl::GetInstance()->CanReadFile(
-          process_id_, platform_path)) {
-    // In order for the renderer to be able to read the file, it must be granted
-    // read permission for the file's platform path. By now, it has already been
-    // verified that the renderer has sufficient permissions to read the file.
-    // It is still possible that ChildProcessSecurityPolicyImpl doesn't reflect
-    // that the renderer can read the file's platform path. If this is the case
-    // the renderer should be granted read permission for the file's platform
-    // path. This can happen in the following situations:
-    // - the file comes from sandboxed filesystem. Reading sandboxed files is
-    //   always permitted, but only implicitly.
-    // - the underlying filesystem returned newly created snapshot file.
-    // - the file comes from an external drive filesystem. The renderer has
-    //   already been granted read permission for the file's nominal path, but
-    //   for drive files, platform paths differ from the nominal paths.
-    DCHECK(shareable_file ||
-           fileapi::SandboxMountPointProvider::CanHandleType(url.type()) ||
-           url.type() == fileapi::kFileSystemTypeDrive);
-    ChildProcessSecurityPolicyImpl::GetInstance()->GrantReadFile(
-        process_id_, platform_path);
-    if (shareable_file) {
-      // This will revoke all permissions for the file when the last ref
-      // of the file is dropped (assuming it's ok).
-      shareable_file->AddFinalReleaseCallback(
-          base::Bind(&RevokeFilePermission, process_id_));
-    }
-  }
-
-  // This may fail, but then we'll be just setting the empty mime type.
-  std::string mime_type;
-  net::GetWellKnownMimeTypeFromExtension(extension, &mime_type);
-  BlobData::Item item;
-  item.SetToFilePathRange(platform_path, 0, -1, base::Time());
-  BlobStorageController* controller = blob_storage_context_->controller();
-  controller->StartBuildingBlob(blob_url);
-  controller->AppendBlobDataItem(blob_url, item);
-  controller->FinishBuildingBlob(blob_url, mime_type);
-  blob_urls_.insert(blob_url.spec());
-}
-
 bool FileAPIMessageFilter::HasPermissionsForFile(
     const FileSystemURL& url, int permissions, base::PlatformFileError* error) {
   return CheckFileSystemPermissionsForProcess(context_, process_id_, url,
diff --git a/content/browser/fileapi/fileapi_message_filter.h b/content/browser/fileapi/fileapi_message_filter.h
index 4f8ce5b..99c3a1e 100644
--- a/content/browser/fileapi/fileapi_message_filter.h
+++ b/content/browser/fileapi/fileapi_message_filter.h
@@ -18,6 +18,7 @@
 #include "content/public/browser/browser_message_filter.h"
 #include "webkit/blob/blob_data.h"
 #include "webkit/fileapi/file_system_types.h"
+#include "webkit/quota/quota_types.h"
 
 class GURL;
 
@@ -110,7 +111,7 @@
                    const base::Time& last_modified_time);
   void OnCancel(int request_id, int request_to_cancel);
   void OnOpenFile(int request_id, const GURL& path, int file_flags);
-  void OnNotifyCloseFile(const GURL& path);
+  void OnNotifyCloseFile(int file_open_id);
   void OnWillUpdate(const GURL& path);
   void OnDidUpdate(const GURL& path, int64 delta);
   void OnSyncGetPlatformPath(const GURL& path,
@@ -119,10 +120,6 @@
                             const GURL& path);
   void OnDidReceiveSnapshotFile(int request_id);
 
-  void OnCreateSnapshotFile_Deprecated(int request_id,
-                                       const GURL& blob_url,
-                                       const GURL& path);
-
   void OnStartBuildingBlob(const GURL& url);
   void OnAppendBlobDataItem(const GURL& url,
                             const webkit_blob::BlobData::Item& item);
@@ -144,9 +141,10 @@
                         const std::vector<base::FileUtilProxy::Entry>& entries,
                         bool has_more);
   void DidOpenFile(int request_id,
-                   const GURL& path,
+                   quota::QuotaLimitType quota_policy,
                    base::PlatformFileError result,
                    base::PlatformFile file,
+                   const base::Closure& on_close_callback,
                    base::ProcessHandle peer_handle);
   void DidWrite(int request_id,
                 base::PlatformFileError result,
@@ -166,19 +164,6 @@
       const base::FilePath& platform_path,
       const scoped_refptr<webkit_blob::ShareableFileReference>& file_ref);
 
-  void DidCreateSnapshot_Deprecated(
-      int request_id,
-      const base::Callback<void(const base::FilePath&)>& register_file_callback,
-      base::PlatformFileError result,
-      const base::PlatformFileInfo& info,
-      const base::FilePath& platform_path,
-      const scoped_refptr<webkit_blob::ShareableFileReference>& file_ref);
-  // Registers the given file pointed by |virtual_path| and backed by
-  // |platform_path| as the |blob_url|.  Called by DidCreateSnapshot_Deprecated.
-  void RegisterFileAsBlob(const GURL& blob_url,
-                          const fileapi::FileSystemURL& url,
-                          const base::FilePath& platform_path);
-
   // Checks renderer's access permissions for single file.
   bool HasPermissionsForFile(const fileapi::FileSystemURL& url,
                              int permissions,
@@ -213,9 +198,10 @@
   std::map<int, scoped_refptr<webkit_blob::ShareableFileReference> >
       in_transit_snapshot_files_;
 
-  // Keep track of file system file URLs opened by OpenFile() in this process.
+  // Keep track of file system file opened by OpenFile() in this process.
   // Need to close all of them when the renderer process dies.
-  std::multiset<GURL> open_filesystem_urls_;
+  typedef IDMap<base::Closure, IDMapOwnPointer> OnCloseCallbackMap;
+  OnCloseCallbackMap on_close_callbacks_;
 
   DISALLOW_COPY_AND_ASSIGN(FileAPIMessageFilter);
 };
diff --git a/content/browser/font_list_async.cc b/content/browser/font_list_async.cc
index 819e62b..4225319 100644
--- a/content/browser/font_list_async.cc
+++ b/content/browser/font_list_async.cc
@@ -38,7 +38,9 @@
   DCHECK(well_known_thread)
       << "Can only call GetFontList from a well-known thread.";
 
-  BrowserThread::PostBlockingPoolTask(FROM_HERE,
+  BrowserThread::PostBlockingPoolSequencedTask(
+      kFontListSequenceToken,
+      FROM_HERE,
       base::Bind(&GetFontListInBlockingPool, id, callback));
 }
 
diff --git a/content/browser/gamepad/gamepad_platform_data_fetcher_mac.mm b/content/browser/gamepad/gamepad_platform_data_fetcher_mac.mm
index 8748730..84bad06 100644
--- a/content/browser/gamepad/gamepad_platform_data_fetcher_mac.mm
+++ b/content/browser/gamepad/gamepad_platform_data_fetcher_mac.mm
@@ -301,7 +301,7 @@
 
   // Copy to the current state to the output buffer, using the mapping
   // function, if there is one available.
-  pads->length = data_.length;
+  pads->length = WebKit::WebGamepads::itemsLengthCap;
   for (size_t i = 0; i < WebKit::WebGamepads::itemsLengthCap; ++i) {
     if (associated_[i].mapper)
       associated_[i].mapper(data_.items[i], &pads->items[i]);
diff --git a/content/browser/gamepad/gamepad_provider.cc b/content/browser/gamepad/gamepad_provider.cc
index 8231683..1dad482 100644
--- a/content/browser/gamepad/gamepad_provider.cc
+++ b/content/browser/gamepad/gamepad_provider.cc
@@ -68,7 +68,7 @@
     base::AutoLock lock(is_paused_lock_);
     is_paused_ = true;
   }
-  MessageLoop* polling_loop = polling_thread_->message_loop();
+  base::MessageLoop* polling_loop = polling_thread_->message_loop();
   polling_loop->PostTask(
       FROM_HERE,
       base::Bind(&GamepadProvider::SendPauseHint, Unretained(this), true));
@@ -82,7 +82,7 @@
     is_paused_ = false;
   }
 
-  MessageLoop* polling_loop = polling_thread_->message_loop();
+  base::MessageLoop* polling_loop = polling_thread_->message_loop();
   polling_loop->PostTask(
       FROM_HERE,
       base::Bind(&GamepadProvider::SendPauseHint, Unretained(this), false));
@@ -93,8 +93,8 @@
 
 void GamepadProvider::RegisterForUserGesture(const base::Closure& closure) {
   base::AutoLock lock(user_gesture_lock_);
-  user_gesture_observers_.push_back(
-      ClosureAndThread(closure, MessageLoop::current()->message_loop_proxy()));
+  user_gesture_observers_.push_back(ClosureAndThread(
+      closure, base::MessageLoop::current()->message_loop_proxy()));
 }
 
 void GamepadProvider::OnDevicesChanged(base::SystemMonitor::DeviceType type) {
@@ -114,7 +114,7 @@
 
   polling_thread_.reset(new base::Thread("Gamepad polling thread"));
   polling_thread_->StartWithOptions(
-      base::Thread::Options(MessageLoop::TYPE_IO, 0));
+      base::Thread::Options(base::MessageLoop::TYPE_IO, 0));
 
   polling_thread_->message_loop()->PostTask(
       FROM_HERE,
@@ -125,22 +125,22 @@
 
 void GamepadProvider::DoInitializePollingThread(
     scoped_ptr<GamepadDataFetcher> fetcher) {
-  DCHECK(MessageLoop::current() == polling_thread_->message_loop());
+  DCHECK(base::MessageLoop::current() == polling_thread_->message_loop());
   DCHECK(!data_fetcher_.get());  // Should only initialize once.
 
-  if (!fetcher.get())
+  if (!fetcher)
     fetcher.reset(new GamepadPlatformDataFetcher);
   data_fetcher_ = fetcher.Pass();
 }
 
 void GamepadProvider::SendPauseHint(bool paused) {
-  DCHECK(MessageLoop::current() == polling_thread_->message_loop());
-  if (data_fetcher_.get())
+  DCHECK(base::MessageLoop::current() == polling_thread_->message_loop());
+  if (data_fetcher_)
     data_fetcher_->PauseHint(paused);
 }
 
 void GamepadProvider::DoPoll() {
-  DCHECK(MessageLoop::current() == polling_thread_->message_loop());
+  DCHECK(base::MessageLoop::current() == polling_thread_->message_loop());
   DCHECK(have_scheduled_do_poll_);
   have_scheduled_do_poll_ = false;
 
@@ -171,7 +171,7 @@
 }
 
 void GamepadProvider::ScheduleDoPoll() {
-  DCHECK(MessageLoop::current() == polling_thread_->message_loop());
+  DCHECK(base::MessageLoop::current() == polling_thread_->message_loop());
   if (have_scheduled_do_poll_)
     return;
 
@@ -181,7 +181,7 @@
       return;
   }
 
-  MessageLoop::current()->PostDelayedTask(
+  base::MessageLoop::current()->PostDelayedTask(
       FROM_HERE,
       base::Bind(&GamepadProvider::DoPoll, Unretained(this)),
       base::TimeDelta::FromMilliseconds(kDesiredSamplingIntervalMs));
diff --git a/content/browser/gamepad/gamepad_provider_unittest.cc b/content/browser/gamepad/gamepad_provider_unittest.cc
index 18bafc3..12d8845 100644
--- a/content/browser/gamepad/gamepad_provider_unittest.cc
+++ b/content/browser/gamepad/gamepad_provider_unittest.cc
@@ -22,7 +22,7 @@
 class UserGestureListener {
  public:
   UserGestureListener()
-      : weak_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)),
+      : weak_factory_(this),
         has_user_gesture_(false) {
   }
 
diff --git a/content/browser/gamepad/gamepad_service.cc b/content/browser/gamepad/gamepad_service.cc
index 2f6b6bd..11a6964 100644
--- a/content/browser/gamepad/gamepad_service.cc
+++ b/content/browser/gamepad/gamepad_service.cc
@@ -35,7 +35,7 @@
 
   num_readers_++;
   DCHECK(num_readers_ > 0);
-  if (!provider_.get())
+  if (!provider_)
     provider_.reset(new GamepadProvider);
   provider_->Resume();
 }
diff --git a/content/browser/gamepad/gamepad_standard_mappings.h b/content/browser/gamepad/gamepad_standard_mappings.h
index 35b01f8..6f5d72f 100644
--- a/content/browser/gamepad/gamepad_standard_mappings.h
+++ b/content/browser/gamepad/gamepad_standard_mappings.h
@@ -5,7 +5,7 @@
 #ifndef CONTENT_BROWSER_GAMEPAD_GAMEPAD_STANDARD_MAPPINGS_H_
 #define CONTENT_BROWSER_GAMEPAD_GAMEPAD_STANDARD_MAPPINGS_H_
 
-#include "base/string_piece.h"
+#include "base/strings/string_piece.h"
 
 namespace WebKit {
 class WebGamepad;
diff --git a/content/browser/gamepad/gamepad_test_helpers.cc b/content/browser/gamepad/gamepad_test_helpers.cc
index abf4187..e4db14c 100644
--- a/content/browser/gamepad/gamepad_test_helpers.cc
+++ b/content/browser/gamepad/gamepad_test_helpers.cc
@@ -4,7 +4,6 @@
 
 #include "content/browser/gamepad/gamepad_test_helpers.h"
 
-#include "base/system_monitor/system_monitor.h"
 #include "content/browser/gamepad/gamepad_service.h"
 
 namespace content {
@@ -37,10 +36,6 @@
 }
 
 GamepadTestHelper::GamepadTestHelper() {
-#if defined(OS_MACOSX)
-  base::SystemMonitor::AllocateSystemIOPorts();
-#endif
-  system_monitor_.reset(new base::SystemMonitor);
 }
 
 GamepadTestHelper::~GamepadTestHelper() {
diff --git a/content/browser/gamepad/gamepad_test_helpers.h b/content/browser/gamepad/gamepad_test_helpers.h
index 9abba01..7b8bb4b 100644
--- a/content/browser/gamepad/gamepad_test_helpers.h
+++ b/content/browser/gamepad/gamepad_test_helpers.h
@@ -12,10 +12,6 @@
 #include "content/browser/gamepad/gamepad_data_fetcher.h"
 #include "third_party/WebKit/Source/Platform/chromium/public/WebGamepads.h"
 
-namespace base {
-class SystemMonitor;
-}
-
 namespace content {
 
 class GamepadService;
@@ -54,13 +50,11 @@
   GamepadTestHelper();
   virtual ~GamepadTestHelper();
 
-  MessageLoop& message_loop() { return message_loop_; }
+  base::MessageLoop& message_loop() { return message_loop_; }
 
  private:
   // This must be constructed before the system monitor.
-  MessageLoop message_loop_;
-
-  scoped_ptr<base::SystemMonitor> system_monitor_;
+  base::MessageLoop message_loop_;
 
   DISALLOW_COPY_AND_ASSIGN(GamepadTestHelper);
 };
diff --git a/content/browser/geolocation/core_location_data_provider_mac.mm b/content/browser/geolocation/core_location_data_provider_mac.mm
index 8c0d338..9942502 100644
--- a/content/browser/geolocation/core_location_data_provider_mac.mm
+++ b/content/browser/geolocation/core_location_data_provider_mac.mm
@@ -192,7 +192,7 @@
 namespace content {
 
 CoreLocationDataProviderMac::CoreLocationDataProviderMac() {
-  if (MessageLoop::current() !=
+  if (base::MessageLoop::current() !=
       GeolocationProvider::GetInstance()->message_loop()) {
     NOTREACHED() << "CoreLocation data provider must be created on "
         "the Geolocation thread.";
@@ -247,7 +247,7 @@
 }
 
 void CoreLocationDataProviderMac::PositionUpdated(Geoposition position) {
-  DCHECK(MessageLoop::current() ==
+  DCHECK(base::MessageLoop::current() ==
          GeolocationProvider::GetInstance()->message_loop());
   if (provider_)
     provider_->SetPosition(&position);
diff --git a/content/browser/geolocation/device_data_provider.h b/content/browser/geolocation/device_data_provider.h
index 4918e30..431d706 100644
--- a/content/browser/geolocation/device_data_provider.h
+++ b/content/browser/geolocation/device_data_provider.h
@@ -92,7 +92,7 @@
 class DeviceDataProviderImplBase : public DeviceDataProviderImplBaseHack {
  public:
   DeviceDataProviderImplBase()
-      : container_(NULL), client_loop_(MessageLoop::current()) {
+      : container_(NULL), client_loop_(base::MessageLoop::current()) {
     DCHECK(client_loop_);
   }
 
@@ -138,12 +138,10 @@
   }
 
   bool CalledOnClientThread() const {
-    return MessageLoop::current() == this->client_loop_;
+    return base::MessageLoop::current() == this->client_loop_;
   }
 
-  MessageLoop* client_loop() const {
-    return client_loop_;
-  }
+  base::MessageLoop* client_loop() const { return client_loop_; }
 
  private:
   void NotifyListenersInClientLoop() {
@@ -162,7 +160,7 @@
 
   // Reference to the client's message loop, all callbacks and access to
   // the listeners_ member should happen in this context.
-  MessageLoop* client_loop_;
+  base::MessageLoop* client_loop_;
 
   ListenersSet listeners_;
 
diff --git a/content/browser/geolocation/device_data_provider_unittest.cc b/content/browser/geolocation/device_data_provider_unittest.cc
index 0f0c957..42a678c 100644
--- a/content/browser/geolocation/device_data_provider_unittest.cc
+++ b/content/browser/geolocation/device_data_provider_unittest.cc
@@ -22,7 +22,7 @@
   // run for correct behaviour, but we run it in this test to help smoke out
   // any race conditions between processing in the main loop and the setup /
   // tear down of the DeviceDataProvider thread.
-  MessageLoopForUI main_message_loop;
+  base::MessageLoopForUI main_message_loop;
   NullWifiDataListenerInterface listener;
   for (int i = 0; i < 10; i++) {
     DeviceDataProvider<WifiData>::Register(&listener);
diff --git a/content/browser/geolocation/geolocation_provider.cc b/content/browser/geolocation/geolocation_provider.cc
index 80420b9..7a2b689 100644
--- a/content/browser/geolocation/geolocation_provider.cc
+++ b/content/browser/geolocation/geolocation_provider.cc
@@ -95,7 +95,7 @@
 }
 
 bool GeolocationProvider::OnGeolocationThread() const {
-  return MessageLoop::current() == message_loop();
+  return base::MessageLoop::current() == message_loop();
 }
 
 void GeolocationProvider::OnClientsChanged() {
diff --git a/content/browser/geolocation/geolocation_provider_unittest.cc b/content/browser/geolocation/geolocation_provider_unittest.cc
index dcffef0..ea22700 100644
--- a/content/browser/geolocation/geolocation_provider_unittest.cc
+++ b/content/browser/geolocation/geolocation_provider_unittest.cc
@@ -67,7 +67,7 @@
   // GeolocationObserver
   virtual void OnLocationUpdate(const Geoposition& position) OVERRIDE {
     MockGeolocationObserver::OnLocationUpdate(position);
-    MessageLoop::current()->Quit();
+    base::MessageLoop::current()->Quit();
   }
 };
 
@@ -134,7 +134,7 @@
   // Called on provider thread.
   void GetProvidersStarted(bool* started);
 
-  MessageLoop message_loop_;
+  base::MessageLoop message_loop_;
   TestBrowserThread io_thread_;
   scoped_ptr<LocationProviderForTestArbitrator> provider_;
 };
@@ -142,31 +142,31 @@
 
 bool GeolocationProviderTest::ProvidersStarted() {
   DCHECK(provider_->IsRunning());
-  DCHECK(MessageLoop::current() == &message_loop_);
+  DCHECK(base::MessageLoop::current() == &message_loop_);
   bool started;
   provider_->message_loop_proxy()->PostTaskAndReply(
       FROM_HERE,
       base::Bind(&GeolocationProviderTest::GetProvidersStarted,
                  base::Unretained(this),
                  &started),
-      MessageLoop::QuitClosure());
+      base::MessageLoop::QuitClosure());
   message_loop_.Run();
   return started;
 }
 
 void GeolocationProviderTest::GetProvidersStarted(bool* started) {
-  DCHECK(MessageLoop::current() == provider_->message_loop());
+  DCHECK(base::MessageLoop::current() == provider_->message_loop());
   *started = provider_->mock_arbitrator()->providers_started();
 }
 
 void GeolocationProviderTest::SendMockLocation(const Geoposition& position) {
   DCHECK(provider_->IsRunning());
-  DCHECK(MessageLoop::current() == &message_loop_);
-  provider_->message_loop()->PostTask(
-      FROM_HERE,
-      base::Bind(&GeolocationProvider::OnLocationUpdate,
-                 base::Unretained(provider_.get()),
-                 position));
+  DCHECK(base::MessageLoop::current() == &message_loop_);
+  provider_->message_loop()
+      ->PostTask(FROM_HERE,
+                 base::Bind(&GeolocationProvider::OnLocationUpdate,
+                            base::Unretained(provider_.get()),
+                            position));
 }
 
 // Regression test for http://crbug.com/59377
@@ -201,7 +201,7 @@
   EXPECT_CALL(first_observer, OnLocationUpdate(GeopositionEq(first_position)));
   provider()->AddObserver(&first_observer, options);
   SendMockLocation(first_position);
-  MessageLoop::current()->Run();
+  base::MessageLoop::current()->Run();
 
   provider()->RemoveObserver(&first_observer);
 
@@ -217,13 +217,13 @@
   // is sent.
   EXPECT_CALL(second_observer, OnLocationUpdate(testing::_)).Times(0);
   provider()->AddObserver(&second_observer, options);
-  MessageLoop::current()->RunUntilIdle();
+  base::MessageLoop::current()->RunUntilIdle();
 
   // The second observer should receive the new position now.
   EXPECT_CALL(second_observer,
               OnLocationUpdate(GeopositionEq(second_position)));
   SendMockLocation(second_position);
-  MessageLoop::current()->Run();
+  base::MessageLoop::current()->Run();
 
   provider()->RemoveObserver(&second_observer);
   EXPECT_FALSE(ProvidersStarted());
diff --git a/content/browser/geolocation/gps_location_provider_linux.cc b/content/browser/geolocation/gps_location_provider_linux.cc
index 74a9537..e511e52 100644
--- a/content/browser/geolocation/gps_location_provider_linux.cc
+++ b/content/browser/geolocation/gps_location_provider_linux.cc
@@ -216,7 +216,7 @@
       poll_period_moving_millis_(kPollPeriodMovingMillis),
       poll_period_stationary_millis_(kPollPeriodStationaryMillis),
       libgps_factory_(libgps_factory),
-      ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) {
+      weak_factory_(this) {
   DCHECK(libgps_factory_);
 }
 
@@ -285,7 +285,7 @@
 
 void GpsLocationProviderLinux::ScheduleNextGpsPoll(int interval) {
   weak_factory_.InvalidateWeakPtrs();
-  MessageLoop::current()->PostDelayedTask(
+  base::MessageLoop::current()->PostDelayedTask(
       FROM_HERE,
       base::Bind(&GpsLocationProviderLinux::DoGpsPollTask,
                  weak_factory_.GetWeakPtr()),
diff --git a/content/browser/geolocation/gps_location_provider_unittest_linux.cc b/content/browser/geolocation/gps_location_provider_unittest_linux.cc
index 6aaff15..985479f 100644
--- a/content/browser/geolocation/gps_location_provider_unittest_linux.cc
+++ b/content/browser/geolocation/gps_location_provider_unittest_linux.cc
@@ -53,7 +53,7 @@
   // LocationProviderBase::ListenerInterface
   virtual void LocationUpdateAvailable(
       LocationProviderBase* provider) OVERRIDE {
-    MessageLoop::current()->Quit();
+    base::MessageLoop::current()->Quit();
   }
 };
 
@@ -70,7 +70,7 @@
   }
 
  protected:
-  MessageLoop message_loop_;
+  base::MessageLoop message_loop_;
   BrowserThreadImpl ui_thread_;
   LocaionProviderListenerLoopQuitter location_listener_;
   scoped_ptr<GpsLocationProviderLinux> provider_;
@@ -151,7 +151,7 @@
   MockLibGps::g_instance_->get_position_.timestamp =
       base::Time::FromDoubleT(200);
   EXPECT_TRUE(MockLibGps::g_instance_->get_position_.Validate());
-  MessageLoop::current()->Run();
+  base::MessageLoop::current()->Run();
   EXPECT_EQ(1, MockLibGps::g_instance_->get_position_calls_);
   EXPECT_EQ(1, MockLibGps::g_instance_->gps_open_calls_);
   EXPECT_EQ(1, MockLibGps::g_instance_->gps_read_calls_);
@@ -160,7 +160,7 @@
 
   // Movement. This will block for up to half a second.
   MockLibGps::g_instance_->get_position_.latitude += 0.01;
-  MessageLoop::current()->Run();
+  base::MessageLoop::current()->Run();
   provider_->GetPosition(&position);
   EXPECT_EQ(2, MockLibGps::g_instance_->get_position_calls_);
   EXPECT_EQ(1, MockLibGps::g_instance_->gps_open_calls_);
@@ -194,11 +194,11 @@
   EXPECT_TRUE(MockLibGps::g_instance_->get_position_.Validate());
   // This task makes gps_open() and LibGps::Start() to succeed after
   // 1500ms.
-  MessageLoop::current()->PostDelayedTask(
+  base::MessageLoop::current()->PostDelayedTask(
       FROM_HERE,
       base::Bind(&EnableGpsOpenCallback),
       base::TimeDelta::FromMilliseconds(1500));
-  MessageLoop::current()->Run();
+  base::MessageLoop::current()->Run();
   provider_->GetPosition(&position);
   EXPECT_TRUE(position.Validate());
   // 3 gps_open() calls are expected (2 failures and 1 success)
diff --git a/content/browser/geolocation/location_arbitrator_impl.cc b/content/browser/geolocation/location_arbitrator_impl.cc
index 97cae8e..9b1594f 100644
--- a/content/browser/geolocation/location_arbitrator_impl.cc
+++ b/content/browser/geolocation/location_arbitrator_impl.cc
@@ -125,7 +125,7 @@
 }
 
 AccessTokenStore* GeolocationArbitratorImpl::GetAccessTokenStore() {
-  if (!access_token_store_.get())
+  if (!access_token_store_)
     access_token_store_ = NewAccessTokenStore();
   return access_token_store_.get();
 }
diff --git a/content/browser/geolocation/location_arbitrator_impl_unittest.cc b/content/browser/geolocation/location_arbitrator_impl_unittest.cc
index e2b39ee..1beb07f 100644
--- a/content/browser/geolocation/location_arbitrator_impl_unittest.cc
+++ b/content/browser/geolocation/location_arbitrator_impl_unittest.cc
@@ -144,7 +144,7 @@
   scoped_refptr<FakeAccessTokenStore> access_token_store_;
   scoped_ptr<MockLocationObserver> observer_;
   scoped_ptr<TestingGeolocationArbitrator> arbitrator_;
-  MessageLoop loop_;
+  base::MessageLoop loop_;
 };
 
 TEST_F(GeolocationLocationArbitratorTest, CreateDestroy) {
diff --git a/content/browser/geolocation/mock_location_provider.cc b/content/browser/geolocation/mock_location_provider.cc
index e146f38..7c083c7 100644
--- a/content/browser/geolocation/mock_location_provider.cc
+++ b/content/browser/geolocation/mock_location_provider.cc
@@ -72,7 +72,7 @@
   AutoMockLocationProvider(bool has_valid_location,
                            bool requires_permission_to_start)
       : MockLocationProvider(&instance_),
-        ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)),
+        weak_factory_(this),
         requires_permission_to_start_(requires_permission_to_start),
         listeners_updated_(false) {
     if (has_valid_location) {
@@ -104,10 +104,11 @@
   void UpdateListenersIfNeeded() {
     if (!listeners_updated_) {
       listeners_updated_ = true;
-      MessageLoop::current()->PostTask(
+      base::MessageLoop::current()->PostTask(
           FROM_HERE,
           base::Bind(&MockLocationProvider::HandlePositionChanged,
-                     weak_factory_.GetWeakPtr(), position_));
+                     weak_factory_.GetWeakPtr(),
+                     position_));
     }
   }
 
diff --git a/content/browser/geolocation/network_location_provider.cc b/content/browser/geolocation/network_location_provider.cc
index 0167fd9..8cf98bb 100644
--- a/content/browser/geolocation/network_location_provider.cc
+++ b/content/browser/geolocation/network_location_provider.cc
@@ -114,7 +114,7 @@
       access_token_(access_token),
       is_permission_granted_(false),
       is_new_data_available_(false),
-      ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) {
+      weak_factory_(this) {
   // Create the position cache.
   position_cache_.reset(new PositionCache());
 
@@ -194,7 +194,7 @@
   // provider and it will be deleted by ref counting.
   wifi_data_provider_ = WifiDataProvider::Register(this);
 
-  MessageLoop::current()->PostDelayedTask(
+  base::MessageLoop::current()->PostDelayedTask(
       FROM_HERE,
       base::Bind(&NetworkLocationProvider::RequestPosition,
                  weak_factory_.GetWeakPtr()),
diff --git a/content/browser/geolocation/network_location_provider_unittest.cc b/content/browser/geolocation/network_location_provider_unittest.cc
index fb01795..ccbfc1b 100644
--- a/content/browser/geolocation/network_location_provider_unittest.cc
+++ b/content/browser/geolocation/network_location_provider_unittest.cc
@@ -31,7 +31,7 @@
     : public LocationProviderBase::ListenerInterface {
  public:
   MessageLoopQuitListener()
-      : client_message_loop_(MessageLoop::current()),
+      : client_message_loop_(base::MessageLoop::current()),
         updated_provider_(NULL),
         movement_provider_(NULL) {
     CHECK(client_message_loop_);
@@ -39,11 +39,11 @@
   // ListenerInterface
   virtual void LocationUpdateAvailable(
       LocationProviderBase* provider) OVERRIDE {
-    EXPECT_EQ(client_message_loop_, MessageLoop::current());
+    EXPECT_EQ(client_message_loop_, base::MessageLoop::current());
     updated_provider_ = provider;
     client_message_loop_->Quit();
   }
-  MessageLoop* client_message_loop_;
+  base::MessageLoop* client_message_loop_;
   LocationProviderBase* updated_provider_;
   LocationProviderBase* movement_provider_;
 };
@@ -324,7 +324,7 @@
   }
 
   GURL test_server_url_;
-  MessageLoop main_message_loop_;
+  base::MessageLoop main_message_loop_;
   scoped_refptr<FakeAccessTokenStore> access_token_store_;
   net::TestURLFetcherFactory url_fetcher_factory_;
   scoped_refptr<MockDeviceDataProviderImpl<WifiData> > wifi_data_provider_;
@@ -332,7 +332,7 @@
 
 TEST_F(GeolocationNetworkProviderTest, CreateDestroy) {
   // Test fixture members were SetUp correctly.
-  EXPECT_EQ(&main_message_loop_, MessageLoop::current());
+  EXPECT_EQ(&main_message_loop_, base::MessageLoop::current());
   scoped_ptr<LocationProviderBase> provider(CreateProvider(true));
   EXPECT_TRUE(NULL != provider.get());
   provider.reset();
@@ -344,7 +344,7 @@
   EXPECT_TRUE(provider->StartProvider(false));
   net::TestURLFetcher* fetcher = get_url_fetcher_and_advance_id();
   ASSERT_TRUE(fetcher != NULL);
-  CheckRequestIsValid(*fetcher, 0, 0, 0, "");
+  CheckRequestIsValid(*fetcher, 0, 0, 0, std::string());
 }
 
 TEST_F(GeolocationNetworkProviderTest, StartProviderDefaultUrl) {
@@ -353,10 +353,9 @@
   EXPECT_TRUE(provider->StartProvider(false));
   net::TestURLFetcher* fetcher = get_url_fetcher_and_advance_id();
   ASSERT_TRUE(fetcher != NULL);
-  CheckRequestIsValid(*fetcher, 0, 0, 0, "");
+  CheckRequestIsValid(*fetcher, 0, 0, 0, std::string());
 }
 
-
 TEST_F(GeolocationNetworkProviderTest, StartProviderLongRequest) {
   scoped_ptr<LocationProviderBase> provider(CreateProvider(true));
   EXPECT_TRUE(provider->StartProvider(false));
@@ -369,7 +368,7 @@
   // in length by not including access points with the lowest signal strength
   // in the request.
   EXPECT_LT(fetcher->GetOriginalURL().spec().size(), size_t(2048));
-  CheckRequestIsValid(*fetcher, 0, 16, 4, "");
+  CheckRequestIsValid(*fetcher, 0, 16, 4, std::string());
 }
 
 TEST_F(GeolocationNetworkProviderTest, MultiRegistrations) {
@@ -418,7 +417,7 @@
   fetcher = get_url_fetcher_and_advance_id();
   ASSERT_TRUE(fetcher != NULL);
   // The request should have the wifi data.
-  CheckRequestIsValid(*fetcher, 0, kFirstScanAps, 0, "");
+  CheckRequestIsValid(*fetcher, 0, kFirstScanAps, 0, std::string());
 
   // Send a reply with good position fix.
   const char* kReferenceNetworkResponse =
@@ -472,7 +471,7 @@
   fetcher->set_url(test_server_url_);
   fetcher->set_status(net::URLRequestStatus(net::URLRequestStatus::FAILED, -1));
   fetcher->set_response_code(200);  // should be ignored
-  fetcher->SetResponseString("");
+  fetcher->SetResponseString(std::string());
   fetcher->delegate()->OnURLFetchComplete(fetcher);
 
   // Error means we now no longer have a fix.
diff --git a/content/browser/geolocation/wifi_data_provider_chromeos_unittest.cc b/content/browser/geolocation/wifi_data_provider_chromeos_unittest.cc
index 8fcb6c5..6672715 100644
--- a/content/browser/geolocation/wifi_data_provider_chromeos_unittest.cc
+++ b/content/browser/geolocation/wifi_data_provider_chromeos_unittest.cc
@@ -60,7 +60,7 @@
     message_loop_.RunUntilIdle();
   }
 
-  MessageLoopForUI message_loop_;
+  base::MessageLoopForUI message_loop_;
   scoped_refptr<WifiDataProviderChromeOs> provider_;
   chromeos::ShillManagerClient* manager_client_;
   chromeos::ShillManagerClient::TestInterface* manager_test_;
diff --git a/content/browser/geolocation/wifi_data_provider_common.cc b/content/browser/geolocation/wifi_data_provider_common.cc
index fd5667a..b00b0a2 100644
--- a/content/browser/geolocation/wifi_data_provider_common.cc
+++ b/content/browser/geolocation/wifi_data_provider_common.cc
@@ -27,7 +27,7 @@
 WifiDataProviderCommon::WifiDataProviderCommon()
     : Thread("Geolocation_wifi_provider"),
       is_first_scan_complete_(false),
-      ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) {
+      weak_factory_(this) {
 }
 
 WifiDataProviderCommon::~WifiDataProviderCommon() {
diff --git a/content/browser/geolocation/wifi_data_provider_common_unittest.cc b/content/browser/geolocation/wifi_data_provider_common_unittest.cc
index 84b1d15..341f392 100644
--- a/content/browser/geolocation/wifi_data_provider_common_unittest.cc
+++ b/content/browser/geolocation/wifi_data_provider_common_unittest.cc
@@ -61,7 +61,7 @@
 class MessageLoopQuitListener
     : public WifiDataProviderCommon::ListenerInterface {
  public:
-  explicit MessageLoopQuitListener(MessageLoop* message_loop)
+  explicit MessageLoopQuitListener(base::MessageLoop* message_loop)
       : message_loop_to_quit_(message_loop) {
     CHECK(message_loop_to_quit_ != NULL);
   }
@@ -69,11 +69,11 @@
   virtual void DeviceDataUpdateAvailable(
       DeviceDataProvider<WifiData>* provider) OVERRIDE {
     // Provider should call back on client's thread.
-    EXPECT_EQ(MessageLoop::current(), message_loop_to_quit_);
+    EXPECT_EQ(base::MessageLoop::current(), message_loop_to_quit_);
     provider_ = provider;
     message_loop_to_quit_->QuitNow();
   }
-  MessageLoop* message_loop_to_quit_;
+  base::MessageLoop* message_loop_to_quit_;
   DeviceDataProvider<WifiData>* provider_;
 };
 
@@ -127,7 +127,7 @@
   }
 
  protected:
-  MessageLoop main_message_loop_;
+  base::MessageLoop main_message_loop_;
   MessageLoopQuitListener quit_listener_;
   scoped_refptr<WifiDataProviderCommonWithMock> provider_;
   MockWlanApi* wlan_api_;
@@ -136,7 +136,7 @@
 
 TEST_F(GeolocationWifiDataProviderCommonTest, CreateDestroy) {
   // Test fixture members were SetUp correctly.
-  EXPECT_EQ(&main_message_loop_, MessageLoop::current());
+  EXPECT_EQ(&main_message_loop_, base::MessageLoop::current());
   EXPECT_TRUE(NULL != provider_.get());
   EXPECT_TRUE(NULL != wlan_api_);
 }
diff --git a/content/browser/geolocation/wifi_data_provider_corewlan_mac.mm b/content/browser/geolocation/wifi_data_provider_corewlan_mac.mm
index f552984..ab4a729 100644
--- a/content/browser/geolocation/wifi_data_provider_corewlan_mac.mm
+++ b/content/browser/geolocation/wifi_data_provider_corewlan_mac.mm
@@ -12,7 +12,7 @@
 #include "base/mac/scoped_nsautorelease_pool.h"
 #include "base/memory/scoped_nsobject.h"
 #include "base/metrics/histogram.h"
-#include "base/sys_string_conversions.h"
+#include "base/strings/sys_string_conversions.h"
 
 // Define a subset of the CoreWLAN interfaces we require. We can't depend on
 // CoreWLAN.h existing as we need to build on 10.5 SDKs. We can't just send
@@ -89,7 +89,7 @@
   }
   // "Leak" dl_handle rather than dlclose it, to ensure |merge_key_|
   // remains valid.
-  if (!merge_key_.get()) {
+  if (!merge_key_) {
     // Fall back to a known-working value should the lookup fail (if
     // this value is itself wrong it's not the end of the world, we might just
     // get very slightly lower quality location fixes due to SSID merges).
diff --git a/content/browser/geolocation/wifi_data_provider_linux.cc b/content/browser/geolocation/wifi_data_provider_linux.cc
index 709063a..09a60f3 100644
--- a/content/browser/geolocation/wifi_data_provider_linux.cc
+++ b/content/browser/geolocation/wifi_data_provider_linux.cc
@@ -148,7 +148,7 @@
         device_proxy->CallMethodAndBlock(
             &method_call,
             dbus::ObjectProxy::TIMEOUT_USE_DEFAULT));
-    if (!response.get()) {
+    if (!response) {
       LOG(WARNING) << "Failed to get the device type for "
                    << device_path.value();
       continue;  // Check the next device.
@@ -180,7 +180,7 @@
       network_manager_proxy_->CallMethodAndBlock(
           &method_call,
           dbus::ObjectProxy::TIMEOUT_USE_DEFAULT));
-  if (!response.get()) {
+  if (!response) {
     LOG(WARNING) << "Failed to get the device list";
     return false;
   }
@@ -208,7 +208,7 @@
       device_proxy->CallMethodAndBlock(
           &method_call,
           dbus::ObjectProxy::TIMEOUT_USE_DEFAULT));
-  if (!response.get()) {
+  if (!response) {
     LOG(WARNING) << "Failed to get access points data for "
                  << adapter_path.value();
     return false;
@@ -236,7 +236,7 @@
     {
       scoped_ptr<dbus::Response> response(
           GetAccessPointProperty(access_point_proxy, "Ssid"));
-      if (!response.get())
+      if (!response)
         continue;
       // The response should contain a variant that contains an array of bytes.
       dbus::MessageReader reader(response.get());
@@ -260,7 +260,7 @@
     { // Read the mac address
       scoped_ptr<dbus::Response> response(
           GetAccessPointProperty(access_point_proxy, "HwAddress"));
-      if (!response.get())
+      if (!response)
         continue;
       dbus::MessageReader reader(response.get());
       std::string mac;
@@ -270,7 +270,7 @@
         continue;
       }
 
-      ReplaceSubstringsAfterOffset(&mac, 0U, ":", "");
+      ReplaceSubstringsAfterOffset(&mac, 0U, ":", std::string());
       std::vector<uint8> mac_bytes;
       if (!base::HexStringToBytes(mac, &mac_bytes) || mac_bytes.size() != 6) {
         LOG(WARNING) << "Can't parse mac address (found " << mac_bytes.size()
@@ -284,7 +284,7 @@
     {  // Read signal strength.
       scoped_ptr<dbus::Response> response(
           GetAccessPointProperty(access_point_proxy, "Strength"));
-      if (!response.get())
+      if (!response)
         continue;
       dbus::MessageReader reader(response.get());
       uint8 strength = 0;
@@ -300,7 +300,7 @@
     { // Read the channel
       scoped_ptr<dbus::Response> response(
           GetAccessPointProperty(access_point_proxy, "Frequency"));
-      if (!response.get())
+      if (!response)
         continue;
       dbus::MessageReader reader(response.get());
       uint32 frequency = 0;
@@ -335,7 +335,7 @@
   scoped_ptr<dbus::Response> response = access_point_proxy->CallMethodAndBlock(
       &method_call,
       dbus::ObjectProxy::TIMEOUT_USE_DEFAULT);
-  if (!response.get()) {
+  if (!response) {
     LOG(WARNING) << "Failed to get property for " << property_name;
   }
   return response.Pass();
diff --git a/content/browser/geolocation/wifi_data_provider_linux_unittest.cc b/content/browser/geolocation/wifi_data_provider_linux_unittest.cc
index 4585008..718fb5d 100644
--- a/content/browser/geolocation/wifi_data_provider_linux_unittest.cc
+++ b/content/browser/geolocation/wifi_data_provider_linux_unittest.cc
@@ -104,7 +104,7 @@
   // DeviceDataProviderImplBase, a super class of WifiDataProviderLinux,
   // requires a message loop to be present. message_loop_ is defined here,
   // as it should outlive wifi_provider_linux_.
-  MessageLoop message_loop_;
+  base::MessageLoop message_loop_;
   scoped_refptr<dbus::MockBus> mock_bus_;
   scoped_refptr<dbus::MockObjectProxy> mock_network_manager_proxy_;
   scoped_refptr<dbus::MockObjectProxy> mock_access_point_proxy_;
diff --git a/content/browser/geolocation/wifi_data_provider_unittest_win.cc b/content/browser/geolocation/wifi_data_provider_unittest_win.cc
index e4cd77b..c74f42c 100644
--- a/content/browser/geolocation/wifi_data_provider_unittest_win.cc
+++ b/content/browser/geolocation/wifi_data_provider_unittest_win.cc
@@ -12,7 +12,7 @@
 
 TEST(GeolocationWin32WifiDataProviderTest, CreateDestroy) {
   // WifiDataProviderCommon requires the client to have a message loop.
-  MessageLoop dummy_loop;
+  base::MessageLoop dummy_loop;
   scoped_refptr<Win32WifiDataProvider> instance(new Win32WifiDataProvider);
   instance = NULL;
   SUCCEED();
diff --git a/content/browser/geolocation/wifi_data_provider_win.cc b/content/browser/geolocation/wifi_data_provider_win.cc
index abd21ac..bdf50f3 100644
--- a/content/browser/geolocation/wifi_data_provider_win.cc
+++ b/content/browser/geolocation/wifi_data_provider_win.cc
@@ -618,7 +618,7 @@
   if (buffer_size == 0) {
     return false;
   }
-  scoped_array<char16> buffer(new char16[buffer_size]);
+  scoped_ptr<char16[]> buffer(new char16[buffer_size]);
 
   // Return value excludes terminating NULL.
   int characters_written = ::GetSystemDirectory(buffer.get(), buffer_size);
diff --git a/content/browser/geolocation/win7_location_provider_unittest_win.cc b/content/browser/geolocation/win7_location_provider_unittest_win.cc
index 9c2e299..6083db2 100644
--- a/content/browser/geolocation/win7_location_provider_unittest_win.cc
+++ b/content/browser/geolocation/win7_location_provider_unittest_win.cc
@@ -63,17 +63,17 @@
 class LocationProviderListenerLoopQuitter
     : public LocationProviderBase::ListenerInterface {
  public:
-  explicit LocationProviderListenerLoopQuitter(MessageLoop* message_loop)
+  explicit LocationProviderListenerLoopQuitter(base::MessageLoop* message_loop)
       : message_loop_to_quit_(message_loop) {
     CHECK(message_loop_to_quit_ != NULL);
   }
   virtual void LocationUpdateAvailable(LocationProviderBase* provider) {
-    EXPECT_EQ(MessageLoop::current(), message_loop_to_quit_);
+    EXPECT_EQ(base::MessageLoop::current(), message_loop_to_quit_);
     provider_ = provider;
     message_loop_to_quit_->Quit();
   }
 
-  MessageLoop* message_loop_to_quit_;
+  base::MessageLoop* message_loop_to_quit_;
   LocationProviderBase* provider_;
 };
 
@@ -97,7 +97,7 @@
  protected:
   MockWin7LocationApi* api_;
   LocationProviderListenerLoopQuitter location_listener_;
-  MessageLoop main_message_loop_;
+  base::MessageLoop main_message_loop_;
   Win7LocationProvider* provider_;
 };
 
diff --git a/content/browser/geolocation/win7_location_provider_win.cc b/content/browser/geolocation/win7_location_provider_win.cc
index fa7122d..ae33c2f 100644
--- a/content/browser/geolocation/win7_location_provider_win.cc
+++ b/content/browser/geolocation/win7_location_provider_win.cc
@@ -46,7 +46,7 @@
 }
 
 Win7LocationProvider::Win7LocationProvider(Win7LocationApi* api)
-    : ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) {
+    : weak_factory_(this) {
   DCHECK(api != NULL);
   api_.reset(api);
 }
@@ -91,7 +91,7 @@
 }
 
 void Win7LocationProvider::ScheduleNextPoll(int interval) {
-  MessageLoop::current()->PostDelayedTask(
+  base::MessageLoop::current()->PostDelayedTask(
       FROM_HERE,
       base::Bind(&Win7LocationProvider::DoPollTask, weak_factory_.GetWeakPtr()),
       base::TimeDelta::FromMilliseconds(interval));
diff --git a/content/browser/gpu/OWNERS b/content/browser/gpu/OWNERS
index 584b4f7..fed3782 100644
--- a/content/browser/gpu/OWNERS
+++ b/content/browser/gpu/OWNERS
@@ -2,5 +2,4 @@
 kbr@chromium.org
 gman@chromium.org
 piman@chromium.org
-jbates@chromium.org
 zmo@chromium.org
diff --git a/content/browser/gpu/browser_gpu_channel_host_factory.cc b/content/browser/gpu/browser_gpu_channel_host_factory.cc
index ca18691..00ab6c3 100644
--- a/content/browser/gpu/browser_gpu_channel_host_factory.cc
+++ b/content/browser/gpu/browser_gpu_channel_host_factory.cc
@@ -251,7 +251,7 @@
 
 GpuChannelHost* BrowserGpuChannelHostFactory::EstablishGpuChannelSync(
     CauseForGpuLaunch cause_for_gpu_launch) {
-  if (gpu_channel_.get()) {
+  if (gpu_channel_) {
     // Recreate the channel if it has been lost.
     if (gpu_channel_->state() == GpuChannelHost::kLost)
       gpu_channel_ = NULL;
diff --git a/content/browser/gpu/browser_gpu_channel_host_factory.h b/content/browser/gpu/browser_gpu_channel_host_factory.h
index f9290bb..2d3c021 100644
--- a/content/browser/gpu/browser_gpu_channel_host_factory.h
+++ b/content/browser/gpu/browser_gpu_channel_host_factory.h
@@ -23,7 +23,7 @@
   // GpuChannelHostFactory implementation.
   virtual bool IsMainThread() OVERRIDE;
   virtual bool IsIOThread() OVERRIDE;
-  virtual MessageLoop* GetMainLoop() OVERRIDE;
+  virtual base::MessageLoop* GetMainLoop() OVERRIDE;
   virtual scoped_refptr<base::MessageLoopProxy> GetIOLoopProxy() OVERRIDE;
   virtual base::WaitableEvent* GetShutDownEvent() OVERRIDE;
   virtual scoped_ptr<base::SharedMemory> AllocateSharedMemory(
diff --git a/content/browser/gpu/compositor_util.cc b/content/browser/gpu/compositor_util.cc
index 9e679b0..0b34932 100644
--- a/content/browser/gpu/compositor_util.cc
+++ b/content/browser/gpu/compositor_util.cc
@@ -9,24 +9,23 @@
 #include "content/public/browser/gpu_data_manager.h"
 #include "content/public/common/content_constants.h"
 #include "content/public/common/content_switches.h"
+#include "content/public/common/gpu_feature_type.h"
 
 namespace content {
 
 namespace {
 
 bool CanDoAcceleratedCompositing() {
-  const GpuDataManager* gpu_data_manager = GpuDataManager::GetInstance();
-  GpuFeatureType blacklisted_features =
-      gpu_data_manager->GetBlacklistedFeatures();
+  const GpuDataManager* manager = GpuDataManager::GetInstance();
 
   // Don't run the field trial if gpu access has been blocked or
   // accelerated compositing is blacklisted.
-  if (!gpu_data_manager->GpuAccessAllowed() ||
-      blacklisted_features & GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING)
+  if (!manager->GpuAccessAllowed(NULL) ||
+      manager->IsFeatureBlacklisted(GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING))
     return false;
 
-  // Check for the software rasterizer (SwiftShader).
-  if (gpu_data_manager->ShouldUseSoftwareRendering())
+  // Check for SwiftShader.
+  if (manager->ShouldUseSwiftShader())
     return false;
 
   const CommandLine& command_line = *CommandLine::ForCurrentProcess();
@@ -37,10 +36,8 @@
 }
 
 bool IsForceCompositingModeBlacklisted() {
-  GpuFeatureType blacklisted_features =
-      GpuDataManager::GetInstance()->GetBlacklistedFeatures();
-  return GPU_FEATURE_TYPE_FORCE_COMPOSITING_MODE ==
-      (blacklisted_features & GPU_FEATURE_TYPE_FORCE_COMPOSITING_MODE);
+  return GpuDataManager::GetInstance()->IsFeatureBlacklisted(
+      GPU_FEATURE_TYPE_FORCE_COMPOSITING_MODE);
 }
 
 }  // namespace
diff --git a/content/browser/gpu/gpu_blacklist.cc b/content/browser/gpu/gpu_blacklist.cc
index cd080f4..c8fcbfa 100644
--- a/content/browser/gpu/gpu_blacklist.cc
+++ b/content/browser/gpu/gpu_blacklist.cc
@@ -18,34 +18,33 @@
 // static
 GpuBlacklist* GpuBlacklist::Create() {
   GpuBlacklist* list = new GpuBlacklist();
-  list->AddFeature("accelerated_2d_canvas",
-                   GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS);
-  list->AddFeature("accelerated_compositing",
-                   GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING);
-  list->AddFeature("webgl",
-                   GPU_FEATURE_TYPE_WEBGL);
-  list->AddFeature("multisampling",
-                   GPU_FEATURE_TYPE_MULTISAMPLING);
-  list->AddFeature("flash_3d",
-                   GPU_FEATURE_TYPE_FLASH3D);
-  list->AddFeature("flash_stage3d",
-                   GPU_FEATURE_TYPE_FLASH_STAGE3D);
-  list->AddFeature("flash_stage3d_baseline",
-                   GPU_FEATURE_TYPE_FLASH_STAGE3D_BASELINE);
-  list->AddFeature("texture_sharing",
-                   GPU_FEATURE_TYPE_TEXTURE_SHARING);
-  list->AddFeature("accelerated_video_decode",
-                   GPU_FEATURE_TYPE_ACCELERATED_VIDEO_DECODE);
-  list->AddFeature("3d_css",
-                   GPU_FEATURE_TYPE_3D_CSS);
-  list->AddFeature("accelerated_video",
-                   GPU_FEATURE_TYPE_ACCELERATED_VIDEO);
-  list->AddFeature("panel_fitting",
-                   GPU_FEATURE_TYPE_PANEL_FITTING);
-  list->AddFeature("force_compositing_mode",
-                   GPU_FEATURE_TYPE_FORCE_COMPOSITING_MODE);
-  list->AddFeature("all",
-                   GPU_FEATURE_TYPE_ALL);
+  list->AddSupportedFeature("accelerated_2d_canvas",
+                            GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS);
+  list->AddSupportedFeature("accelerated_compositing",
+                            GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING);
+  list->AddSupportedFeature("webgl",
+                            GPU_FEATURE_TYPE_WEBGL);
+  list->AddSupportedFeature("multisampling",
+                            GPU_FEATURE_TYPE_MULTISAMPLING);
+  list->AddSupportedFeature("flash_3d",
+                            GPU_FEATURE_TYPE_FLASH3D);
+  list->AddSupportedFeature("flash_stage3d",
+                            GPU_FEATURE_TYPE_FLASH_STAGE3D);
+  list->AddSupportedFeature("flash_stage3d_baseline",
+                            GPU_FEATURE_TYPE_FLASH_STAGE3D_BASELINE);
+  list->AddSupportedFeature("texture_sharing",
+                            GPU_FEATURE_TYPE_TEXTURE_SHARING);
+  list->AddSupportedFeature("accelerated_video_decode",
+                            GPU_FEATURE_TYPE_ACCELERATED_VIDEO_DECODE);
+  list->AddSupportedFeature("3d_css",
+                            GPU_FEATURE_TYPE_3D_CSS);
+  list->AddSupportedFeature("accelerated_video",
+                            GPU_FEATURE_TYPE_ACCELERATED_VIDEO);
+  list->AddSupportedFeature("panel_fitting",
+                            GPU_FEATURE_TYPE_PANEL_FITTING);
+  list->AddSupportedFeature("force_compositing_mode",
+                            GPU_FEATURE_TYPE_FORCE_COMPOSITING_MODE);
+  list->set_supports_feature_type_all(true);
   return list;
 }
 
diff --git a/content/browser/gpu/gpu_blacklist_unittest.cc b/content/browser/gpu/gpu_blacklist_unittest.cc
index 43d0bc0..89c0b10 100644
--- a/content/browser/gpu/gpu_blacklist_unittest.cc
+++ b/content/browser/gpu/gpu_blacklist_unittest.cc
@@ -51,9 +51,10 @@
 
     scoped_ptr<GpuBlacklist> blacklist(GpuBlacklist::Create());
     EXPECT_TRUE(blacklist->LoadList(json, GpuBlacklist::kAllOs));
-    int type = blacklist->MakeDecision(
+    std::set<int> type = blacklist->MakeDecision(
         GpuBlacklist::kOsMacosx, kOsVersion, gpu_info());
-    EXPECT_EQ(static_cast<int>(feature_type), type);
+    EXPECT_EQ(1u, type.size());
+    EXPECT_EQ(1u, type.count(feature_type));
   }
 
  protected:
@@ -90,7 +91,7 @@
   int64 data_file_size64 = 0;
   ASSERT_TRUE(file_util::GetFileSize(data_file, &data_file_size64));
   int data_file_size = static_cast<int>(data_file_size64);
-  scoped_array<char> data(new char[data_file_size]);
+  scoped_ptr<char[]> data(new char[data_file_size]);
   ASSERT_EQ(data_file_size,
             file_util::ReadFile(data_file, data.get(), data_file_size));
   std::string json_string(data.get(), data_file_size);
@@ -156,8 +157,4 @@
                            "force_compositing_mode",
                            GPU_FEATURE_TYPE_FORCE_COMPOSITING_MODE)
 
-GPU_BLACKLIST_FEATURE_TEST(All,
-                           "all",
-                           GPU_FEATURE_TYPE_ALL)
-
 }  // namespace content
diff --git a/content/browser/gpu/gpu_control_list.cc b/content/browser/gpu/gpu_control_list.cc
index 0d57e7b..0fba7c8 100644
--- a/content/browser/gpu/gpu_control_list.cc
+++ b/content/browser/gpu/gpu_control_list.cc
@@ -7,8 +7,8 @@
 #include "base/cpu.h"
 #include "base/json/json_reader.h"
 #include "base/logging.h"
-#include "base/string_number_conversions.h"
 #include "base/string_util.h"
+#include "base/strings/string_number_conversions.h"
 #include "base/strings/string_split.h"
 #include "base/sys_info.h"
 #include "content/browser/gpu/gpu_util.h"
@@ -217,8 +217,8 @@
                              const std::string& version_string2) {
   type_ = StringToOsType(os);
   if (type_ != kOsUnknown) {
-    version_info_.reset(
-        new VersionInfo(version_op, "", version_string, version_string2));
+    version_info_.reset(new VersionInfo(
+        version_op, std::string(), version_string, version_string2));
   }
 }
 
@@ -265,8 +265,8 @@
     const std::string& version_string,
     const std::string& version_string2) {
   name_info_.reset(new StringInfo(name_op, name_value));
-  version_info_.reset(
-      new VersionInfo(version_op, "", version_string, version_string2));
+  version_info_.reset(new VersionInfo(
+      version_op, std::string(), version_string, version_string2));
 }
 
 GpuControlList::MachineModelInfo::~MachineModelInfo() {}
@@ -329,13 +329,15 @@
     : op_(kUnknown),
       value_(0.f),
       value2_(0.f) {
+  op_ = StringToNumericOp(float_op);
+  if (op_ == kAny)
+    return;
   double dvalue = 0;
   if (!base::StringToDouble(float_value, &dvalue)) {
     op_ = kUnknown;
     return;
   }
   value_ = static_cast<float>(dvalue);
-  op_ = StringToNumericOp(float_op);
   if (op_ == kBetween) {
     if (!base::StringToDouble(float_value2, &dvalue)) {
       op_ = kUnknown;
@@ -375,11 +377,13 @@
     : op_(kUnknown),
       value_(0),
       value2_(0) {
+  op_ = StringToNumericOp(int_op);
+  if (op_ == kAny)
+    return;
   if (!base::StringToInt(int_value, &value_)) {
     op_ = kUnknown;
     return;
   }
-  op_ = StringToNumericOp(int_op);
   if (op_ == kBetween &&
       !base::StringToInt(int_value2, &value2_))
     op_ = kUnknown;
@@ -413,7 +417,8 @@
 GpuControlList::ScopedGpuControlListEntry
 GpuControlList::GpuControlListEntry::GetEntryFromValue(
     const base::DictionaryValue* value, bool top_level,
-    const FeatureMap& feature_map) {
+    const FeatureMap& feature_map,
+    bool supports_feature_type_all) {
   DCHECK(value);
   ScopedGpuControlListEntry entry(new GpuControlListEntry());
 
@@ -720,7 +725,8 @@
           return NULL;
         }
       }
-      if (!entry->SetFeatures(feature_list, feature_map)) {
+      if (!entry->SetFeatures(
+              feature_list, feature_map, supports_feature_type_all)) {
         LOG(WARNING) << "Malformed feature entry " << entry->id();
         return NULL;
       }
@@ -737,8 +743,8 @@
           LOG(WARNING) << "Malformed exceptions entry " << entry->id();
           return NULL;
         }
-        ScopedGpuControlListEntry exception(
-            GetEntryFromValue(exception_value, false, feature_map));
+        ScopedGpuControlListEntry exception(GetEntryFromValue(
+            exception_value, false, feature_map, supports_feature_type_all));
         if (exception == NULL) {
           LOG(WARNING) << "Malformed exceptions entry " << entry->id();
           return NULL;
@@ -858,7 +864,7 @@
     const std::string& date_string,
     const std::string& date_string2) {
   driver_date_info_.reset(
-      new VersionInfo(date_op, "", date_string, date_string2));
+      new VersionInfo(date_op, std::string(), date_string, date_string2));
   return driver_date_info_->IsValid();
 }
 
@@ -928,20 +934,25 @@
 
 bool GpuControlList::GpuControlListEntry::SetFeatures(
     const std::vector<std::string>& feature_strings,
-    const FeatureMap& feature_map) {
+    const FeatureMap& feature_map,
+    bool supports_feature_type_all) {
   size_t size = feature_strings.size();
   if (size == 0)
     return false;
-  int features = 0;
+  features_.clear();
   for (size_t i = 0; i < size; ++i) {
     int feature = 0;
-    bool valid = StringToFeature(feature_strings[i], &feature, feature_map);
-    if (valid)
-        features |= feature;
+    if (supports_feature_type_all && feature_strings[i] == "all") {
+      for (FeatureMap::const_iterator iter = feature_map.begin();
+           iter != feature_map.end(); ++iter)
+        features_.insert(iter->second);
+      continue;
+    }
+    if (StringToFeature(feature_strings[i], &feature, feature_map))
+      features_.insert(feature);
     else
-        contains_unknown_features_ = true;
+      contains_unknown_features_ = true;
   }
-  features_ = features;
   return true;
 }
 
@@ -1103,7 +1114,7 @@
   return disabled_;
 }
 
-int GpuControlList::GpuControlListEntry::GetFeatures() const {
+const std::set<int>& GpuControlList::GpuControlListEntry::features() const {
   return features_;
 }
 
@@ -1122,7 +1133,8 @@
 GpuControlList::GpuControlList()
     : max_entry_id_(0),
       contains_unknown_fields_(false),
-      needs_more_info_(false) {
+      needs_more_info_(false),
+      supports_feature_type_all_(false) {
 }
 
 GpuControlList::~GpuControlList() {
@@ -1184,8 +1196,8 @@
     if (browser_version_support == kUnsupported)
       continue;
     DCHECK(browser_version_support == kSupported);
-    ScopedGpuControlListEntry entry(
-        GpuControlListEntry::GetEntryFromValue(list_item, true, feature_map_));
+    ScopedGpuControlListEntry entry(GpuControlListEntry::GetEntryFromValue(
+        list_item, true, feature_map_, supports_feature_type_all_));
     if (entry == NULL)
       return false;
     if (entry->id() > max_entry_id)
@@ -1207,22 +1219,22 @@
     OsType entry_os = entries[i]->GetOsType();
     if (os_filter == GpuControlList::kAllOs ||
         entry_os == kOsAny || entry_os == my_os)
-      feature_list_.push_back(entries[i]);
+      entries_.push_back(entries[i]);
   }
   max_entry_id_ = max_entry_id;
   contains_unknown_fields_ = contains_unknown_fields;
   return true;
 }
 
-int GpuControlList::MakeDecision(
+std::set<int> GpuControlList::MakeDecision(
     GpuControlList::OsType os,
     std::string os_version,
     const GPUInfo& gpu_info) {
   active_entries_.clear();
-  int features = 0;
+  std::set<int> features;
 
   needs_more_info_ = false;
-  int possible_features = 0;
+  std::set<int> possible_features;
 
   if (os == kOsAny)
     os = GetOsType();
@@ -1236,20 +1248,18 @@
   if (!ProcessVersionString(os_version, '.', &pieces))
     os_version = "0";
 
-  for (size_t i = 0; i < feature_list_.size(); ++i) {
-    if (feature_list_[i]->Contains(os, os_version, gpu_info)) {
-      if (!feature_list_[i]->disabled()) {
-        bool not_final = feature_list_[i]->NeedsMoreInfo(gpu_info);
-        if (not_final)
-          possible_features |= feature_list_[i]->GetFeatures();
-        else
-          features |= feature_list_[i]->GetFeatures();
+  for (size_t i = 0; i < entries_.size(); ++i) {
+    if (entries_[i]->Contains(os, os_version, gpu_info)) {
+      if (!entries_[i]->disabled()) {
+        MergeFeatureSets(&possible_features, entries_[i]->features());
+        if (!entries_[i]->NeedsMoreInfo(gpu_info))
+          MergeFeatureSets(&features, entries_[i]->features());
       }
-      active_entries_.push_back(feature_list_[i]);
+      active_entries_.push_back(entries_[i]);
     }
   }
 
-  if (possible_features != 0 && (possible_features | features) != features)
+  if (possible_features.size() > features.size())
     needs_more_info_ = true;
 
   return features;
@@ -1291,14 +1301,14 @@
 }
 
 size_t GpuControlList::num_entries() const {
-  return feature_list_.size();
+  return entries_.size();
 }
 
 uint32 GpuControlList::max_entry_id() const {
   return max_entry_id_;
 }
 
-std::string GpuControlList::GetVersion() const {
+std::string GpuControlList::version() const {
   return version_;
 }
 
@@ -1319,7 +1329,7 @@
 }
 
 void GpuControlList::Clear() {
-  feature_list_.clear();
+  entries_.clear();
   active_entries_.clear();
   max_entry_id_ = 0;
   contains_unknown_fields_ = false;
@@ -1338,8 +1348,8 @@
     browser_version_value->GetString("number", &version_string);
     browser_version_value->GetString("number2", &version_string2);
     scoped_ptr<VersionInfo> browser_version_info;
-    browser_version_info.reset(
-        new VersionInfo(version_op, "", version_string, version_string2));
+    browser_version_info.reset(new VersionInfo(
+        version_op, std::string(), version_string, version_string2));
     if (!browser_version_info->IsValid())
       return kMalformed;
     if (browser_version_info->Contains(browser_version_))
@@ -1369,10 +1379,14 @@
   return kUnknown;
 }
 
-void GpuControlList::AddFeature(
+void GpuControlList::AddSupportedFeature(
     const std::string& feature_name, int feature_id) {
   feature_map_[feature_name] = feature_id;
 }
 
+void GpuControlList::set_supports_feature_type_all(bool supported) {
+  supports_feature_type_all_ = supported;
+}
+
 }  // namespace content
 
diff --git a/content/browser/gpu/gpu_control_list.h b/content/browser/gpu/gpu_control_list.h
index 1f7e9e1..cd7f69b 100644
--- a/content/browser/gpu/gpu_control_list.h
+++ b/content/browser/gpu/gpu_control_list.h
@@ -5,6 +5,7 @@
 #ifndef CONTENT_BROWSER_GPU_GPU_CONTROL_LIST_H_
 #define CONTENT_BROWSER_GPU_GPU_CONTROL_LIST_H_
 
+#include <set>
 #include <string>
 #include <vector>
 
@@ -53,7 +54,7 @@
   // system and returns the union of features specified in each entry.
   // If os is kOsAny, use the current OS; if os_version is empty, use the
   // current OS version.
-  int MakeDecision(
+  std::set<int> MakeDecision(
       OsType os, std::string os_version, const GPUInfo& gpu_info);
 
   // Collects the active entries from the last MakeDecision() call.
@@ -76,8 +77,8 @@
   // Return the largest entry id.  This is used for histogramming.
   uint32 max_entry_id() const;
 
-  // Returns the version of the current blacklist.
-  std::string GetVersion() const;
+  // Returns the version of the control list.
+  std::string version() const;
 
   // Check if we need more gpu info to make the decisions.
   // This is computed from the last MakeDecision() call.
@@ -91,9 +92,18 @@
   size_t num_entries() const;
 
   // Register a feature to FeatureMap - used to construct a GpuControlList.
-  void AddFeature(const std::string& feature_name, int feature_id);
+  void AddSupportedFeature(const std::string& feature_name, int feature_id);
+  // Register whether "all" is recognized as all features.
+  void set_supports_feature_type_all(bool supported);
 
  private:
+  friend class GpuControlListEntryTest;
+  friend class MachineModelInfoTest;
+  friend class NumberInfoTest;
+  friend class OsInfoTest;
+  friend class StringInfoTest;
+  friend class VersionInfoTest;
+
   enum BrowserVersionSupport {
     kSupported,
     kUnsupported,
@@ -111,7 +121,7 @@
     kUnknown  // Indicates the data is invalid.
   };
 
-  class VersionInfo {
+  class CONTENT_EXPORT VersionInfo {
    public:
     // If version_style is empty, it defaults to kNumerical.
     VersionInfo(const std::string& version_op,
@@ -145,10 +155,9 @@
     // Return 1 if version > version_ref,
     //        0 if version = version_ref,
     //       -1 if version < version_ref.
-    // Note that we only compare as many as segments as version_ref contains.
-    // If version_ref is xxx.yyy, it's considered as xxx.yyy.*
+    // Note that we only compare as many segments as both versions contain.
     // For example: Compare("10.3.1", "10.3") returns 0,
-    //              Compare("10.3", "10.3.1") returns -1.
+    //              Compare("10.3", "10.3.1") returns 0.
     // If "version_style" is Lexical, the first segment is compared
     // numerically, all other segments are compared lexically.
     // Lexical is used for AMD Linux driver versions only.
@@ -162,7 +171,7 @@
     std::vector<std::string> version2_;
   };
 
-  class OsInfo {
+  class CONTENT_EXPORT OsInfo {
    public:
     OsInfo(const std::string& os,
            const std::string& version_op,
@@ -186,7 +195,7 @@
     scoped_ptr<VersionInfo> version_info_;
   };
 
-  class StringInfo {
+  class CONTENT_EXPORT StringInfo {
    public:
     StringInfo(const std::string& string_op, const std::string& string_value);
 
@@ -212,7 +221,7 @@
     std::string value_;
   };
 
-  class FloatInfo {
+  class CONTENT_EXPORT FloatInfo {
    public:
     FloatInfo(const std::string& float_op,
               const std::string& float_value,
@@ -230,7 +239,7 @@
     float value2_;
   };
 
-  class IntInfo {
+  class CONTENT_EXPORT IntInfo {
    public:
     IntInfo(const std::string& int_op,
             const std::string& int_value,
@@ -248,7 +257,7 @@
     int value2_;
   };
 
-  class MachineModelInfo {
+  class CONTENT_EXPORT MachineModelInfo {
    public:
     MachineModelInfo(const std::string& name_op,
                      const std::string& name_value,
@@ -273,13 +282,15 @@
 
   typedef base::hash_map<std::string, int> FeatureMap;
 
-  class GpuControlListEntry : public base::RefCounted<GpuControlListEntry> {
+  class CONTENT_EXPORT GpuControlListEntry
+      : public base::RefCounted<GpuControlListEntry> {
    public:
     // Constructs GpuControlListEntry from DictionaryValue loaded from json.
     // Top-level entry must have an id number.  Others are exceptions.
     static ScopedGpuControlListEntry GetEntryFromValue(
         const base::DictionaryValue* value, bool top_level,
-        const FeatureMap& feature_map);
+        const FeatureMap& feature_map,
+        bool supports_feature_type_all);
 
     // Determines if a given os/gc/machine_model/driver is included in the
     // Entry set.
@@ -306,8 +317,8 @@
     const std::vector<int>& cr_bugs() const { return cr_bugs_; }
     const std::vector<int>& webkit_bugs() const { return webkit_bugs_; }
 
-    // Returns the features.
-    int GetFeatures() const;
+    // Returns the blacklisted features in this entry.
+    const std::set<int>& features() const;
 
     // Returns true if an unknown field is encountered.
     bool contains_unknown_fields() const {
@@ -398,7 +409,8 @@
                          const std::string& int_string2);
 
     bool SetFeatures(const std::vector<std::string>& features,
-                     const FeatureMap& feature_map);
+                     const FeatureMap& feature_map,
+                     bool supports_feature_type_all);
 
     void AddException(ScopedGpuControlListEntry exception);
 
@@ -434,7 +446,7 @@
     scoped_ptr<FloatInfo> perf_overall_info_;
     scoped_ptr<MachineModelInfo> machine_model_info_;
     scoped_ptr<IntInfo> gpu_count_info_;
-    int features_;
+    std::set<int> features_;
     std::vector<ScopedGpuControlListEntry> exceptions_;
     bool contains_unknown_fields_;
     bool contains_unknown_features_;
@@ -456,13 +468,13 @@
   static NumericOp StringToNumericOp(const std::string& op);
 
   std::string version_;
-  std::vector<ScopedGpuControlListEntry> feature_list_;
+  std::vector<ScopedGpuControlListEntry> entries_;
 
   std::string browser_version_;
 
   // This records all the blacklist entries that are appliable to the current
-  // user machine.  It is updated everytime MakeBlacklistDecision() is
-  // called and is used later by GetDecisionEntries().
+  // user machine.  It is updated everytime MakeDecision() is called and is
+  // used later by GetDecisionEntries().
   std::vector<ScopedGpuControlListEntry> active_entries_;
 
   uint32 max_entry_id_;
@@ -473,6 +485,7 @@
 
   // The features a GpuControlList recognizes and handles.
   FeatureMap feature_map_;
+  bool supports_feature_type_all_;
 };
 
 }  // namespace content
diff --git a/content/browser/gpu/gpu_control_list_entry_unittest.cc b/content/browser/gpu/gpu_control_list_entry_unittest.cc
new file mode 100644
index 0000000..16b2eb3
--- /dev/null
+++ b/content/browser/gpu/gpu_control_list_entry_unittest.cc
@@ -0,0 +1,748 @@
+// Copyright (c) 2013 The Chromium Authors. 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/json/json_reader.h"
+#include "content/browser/gpu/gpu_control_list.h"
+#include "content/public/common/gpu_info.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+#define LONG_STRING_CONST(...) #__VA_ARGS__
+
+namespace content {
+
+enum TestFeatureType {
+  TEST_FEATURE_0 = 0,
+  TEST_FEATURE_1,
+  TEST_FEATURE_2
+};
+
+class GpuControlListEntryTest : public testing::Test {
+ public:
+  GpuControlListEntryTest() { }
+  virtual ~GpuControlListEntryTest() { }
+
+  const GPUInfo& gpu_info() const {
+    return gpu_info_;
+  }
+
+  typedef GpuControlList::ScopedGpuControlListEntry ScopedEntry;
+
+  static ScopedEntry GetEntryFromString(
+      const std::string& json, bool supports_feature_type_all) {
+    scoped_ptr<base::Value> root;
+    root.reset(base::JSONReader::Read(json));
+    DictionaryValue* value = NULL;
+    if (root.get() == NULL || !root->GetAsDictionary(&value))
+      return NULL;
+
+    GpuControlList::FeatureMap feature_map;
+    feature_map["test_feature_0"] = TEST_FEATURE_0;
+    feature_map["test_feature_1"] = TEST_FEATURE_1;
+    feature_map["test_feature_2"] = TEST_FEATURE_2;
+
+    return GpuControlList::GpuControlListEntry::GetEntryFromValue(
+        value, true, feature_map, supports_feature_type_all);
+  }
+
+  static ScopedEntry GetEntryFromString(const std::string& json) {
+    return GetEntryFromString(json, false);
+  }
+
+  virtual void SetUp() {
+    gpu_info_.gpu.vendor_id = 0x10de;
+    gpu_info_.gpu.device_id = 0x0640;
+    gpu_info_.driver_vendor = "NVIDIA";
+    gpu_info_.driver_version = "1.6.18";
+    gpu_info_.driver_date = "7-14-2009";
+    gpu_info_.machine_model = "MacBookPro 7.1";
+    gpu_info_.gl_vendor = "NVIDIA Corporation";
+    gpu_info_.gl_renderer = "NVIDIA GeForce GT 120 OpenGL Engine";
+    gpu_info_.performance_stats.graphics = 5.0;
+    gpu_info_.performance_stats.gaming = 5.0;
+    gpu_info_.performance_stats.overall = 5.0;
+  }
+
+ private:
+  GPUInfo gpu_info_;
+};
+
+TEST_F(GpuControlListEntryTest, DetailedEntry) {
+  const std::string json = LONG_STRING_CONST(
+      {
+        "id": 5,
+        "description": "test entry",
+        "cr_bugs": [1024, 678],
+        "webkit_bugs": [1950],
+        "os": {
+          "type": "macosx",
+          "version": {
+            "op": "=",
+            "number": "10.6.4"
+          }
+        },
+        "vendor_id": "0x10de",
+        "device_id": ["0x0640"],
+        "driver_version": {
+          "op": "=",
+          "number": "1.6.18"
+        },
+        "features": [
+          "test_feature_0"
+        ]
+      }
+  );
+
+  ScopedEntry entry(GetEntryFromString(json));
+  EXPECT_TRUE(entry != NULL);
+  EXPECT_EQ(GpuControlList::kOsMacosx, entry->GetOsType());
+  EXPECT_FALSE(entry->disabled());
+  EXPECT_EQ(5u, entry->id());
+  EXPECT_STREQ("test entry", entry->description().c_str());
+  EXPECT_EQ(2u, entry->cr_bugs().size());
+  EXPECT_EQ(1024, entry->cr_bugs()[0]);
+  EXPECT_EQ(678, entry->cr_bugs()[1]);
+  EXPECT_EQ(1u, entry->webkit_bugs().size());
+  EXPECT_EQ(1950, entry->webkit_bugs()[0]);
+  EXPECT_EQ(1u, entry->features().size());
+  EXPECT_EQ(1u, entry->features().count(TEST_FEATURE_0));
+  EXPECT_FALSE(entry->contains_unknown_fields());
+  EXPECT_FALSE(entry->contains_unknown_features());
+  EXPECT_FALSE(entry->NeedsMoreInfo(gpu_info()));
+  EXPECT_TRUE(entry->Contains(
+      GpuControlList::kOsMacosx, "10.6.4", gpu_info()));
+}
+
+TEST_F(GpuControlListEntryTest, VendorOnAllOsEntry) {
+  const std::string json = LONG_STRING_CONST(
+      {
+        "id": 1,
+        "vendor_id": "0x10de",
+        "features": [
+          "test_feature_0"
+        ]
+      }
+  );
+  ScopedEntry entry(GetEntryFromString(json));
+  EXPECT_TRUE(entry != NULL);
+  EXPECT_EQ(GpuControlList::kOsAny, entry->GetOsType());
+
+  const GpuControlList::OsType os_type[] = {
+    GpuControlList::kOsMacosx,
+    GpuControlList::kOsWin,
+    GpuControlList::kOsLinux,
+    GpuControlList::kOsChromeOS,
+    GpuControlList::kOsAndroid
+  };
+  for (size_t i = 0; i < arraysize(os_type); ++i)
+    EXPECT_TRUE(entry->Contains(os_type[i], "10.6", gpu_info()));
+}
+
+TEST_F(GpuControlListEntryTest, VendorOnLinuxEntry) {
+  const std::string json = LONG_STRING_CONST(
+      {
+        "id": 1,
+        "os": {
+          "type": "linux"
+        },
+        "vendor_id": "0x10de",
+        "features": [
+          "test_feature_0"
+        ]
+      }
+  );
+  ScopedEntry entry(GetEntryFromString(json));
+  EXPECT_TRUE(entry != NULL);
+  EXPECT_EQ(GpuControlList::kOsLinux, entry->GetOsType());
+
+  const GpuControlList::OsType os_type[] = {
+    GpuControlList::kOsMacosx,
+    GpuControlList::kOsWin,
+    GpuControlList::kOsChromeOS,
+    GpuControlList::kOsAndroid
+  };
+  for (size_t i = 0; i < arraysize(os_type); ++i)
+    EXPECT_FALSE(entry->Contains(os_type[i], "10.6", gpu_info()));
+  EXPECT_TRUE(entry->Contains(
+      GpuControlList::kOsLinux, "10.6", gpu_info()));
+}
+
+TEST_F(GpuControlListEntryTest, AllExceptNVidiaOnLinuxEntry) {
+  const std::string json = LONG_STRING_CONST(
+      {
+        "id": 1,
+        "os": {
+          "type": "linux"
+        },
+        "exceptions": [
+          {
+            "vendor_id": "0x10de"
+          }
+        ],
+        "features": [
+          "test_feature_0"
+        ]
+      }
+  );
+  ScopedEntry entry(GetEntryFromString(json));
+  EXPECT_TRUE(entry != NULL);
+  EXPECT_EQ(GpuControlList::kOsLinux, entry->GetOsType());
+
+  const GpuControlList::OsType os_type[] = {
+    GpuControlList::kOsMacosx,
+    GpuControlList::kOsWin,
+    GpuControlList::kOsLinux,
+    GpuControlList::kOsChromeOS,
+    GpuControlList::kOsAndroid
+  };
+  for (size_t i = 0; i < arraysize(os_type); ++i)
+    EXPECT_FALSE(entry->Contains(os_type[i], "10.6", gpu_info()));
+}
+
+TEST_F(GpuControlListEntryTest, AllExceptIntelOnLinuxEntry) {
+  const std::string json = LONG_STRING_CONST(
+      {
+        "id": 1,
+        "os": {
+          "type": "linux"
+        },
+        "exceptions": [
+          {
+            "vendor_id": "0x8086"
+          }
+        ],
+        "features": [
+          "test_feature_0"
+        ]
+      }
+  );
+  ScopedEntry entry(GetEntryFromString(json));
+  EXPECT_TRUE(entry != NULL);
+  EXPECT_EQ(GpuControlList::kOsLinux, entry->GetOsType());
+
+  const GpuControlList::OsType os_type[] = {
+    GpuControlList::kOsMacosx,
+    GpuControlList::kOsWin,
+    GpuControlList::kOsChromeOS,
+    GpuControlList::kOsAndroid
+  };
+  for (size_t i = 0; i < arraysize(os_type); ++i)
+    EXPECT_FALSE(entry->Contains(os_type[i], "10.6", gpu_info()));
+  EXPECT_TRUE(entry->Contains(
+      GpuControlList::kOsLinux, "10.6", gpu_info()));
+}
+
+TEST_F(GpuControlListEntryTest, DateOnWindowsEntry) {
+  const std::string json = LONG_STRING_CONST(
+      {
+        "id": 1,
+        "os": {
+          "type": "win"
+        },
+        "driver_date": {
+          "op": "<",
+          "number": "2010.5.8"
+        },
+        "features": [
+          "test_feature_0"
+        ]
+      }
+  );
+  ScopedEntry entry(GetEntryFromString(json));
+  EXPECT_TRUE(entry != NULL);
+  EXPECT_EQ(GpuControlList::kOsWin, entry->GetOsType());
+
+  GPUInfo gpu_info;
+  gpu_info.driver_date = "4-12-2010";
+  EXPECT_TRUE(entry->Contains(
+      GpuControlList::kOsWin, "10.6", gpu_info));
+  gpu_info.driver_date = "5-8-2010";
+  EXPECT_FALSE(entry->Contains(
+      GpuControlList::kOsWin, "10.6", gpu_info));
+  gpu_info.driver_date = "5-9-2010";
+  EXPECT_FALSE(entry->Contains(
+      GpuControlList::kOsWin, "10.6", gpu_info));
+}
+
+TEST_F(GpuControlListEntryTest, MultipleDevicesEntry) {
+  const std::string json = LONG_STRING_CONST(
+      {
+        "id": 1,
+        "vendor_id": "0x10de",
+        "device_id": ["0x1023", "0x0640"],
+        "features": [
+          "test_feature_0"
+        ]
+      }
+  );
+  ScopedEntry entry(GetEntryFromString(json));
+  EXPECT_TRUE(entry != NULL);
+  EXPECT_EQ(GpuControlList::kOsAny, entry->GetOsType());
+
+  const GpuControlList::OsType os_type[] = {
+    GpuControlList::kOsMacosx,
+    GpuControlList::kOsWin,
+    GpuControlList::kOsLinux,
+    GpuControlList::kOsChromeOS,
+    GpuControlList::kOsAndroid
+  };
+  for (size_t i = 0; i < arraysize(os_type); ++i)
+    EXPECT_TRUE(entry->Contains(os_type[i], "10.6", gpu_info()));
+}
+
+TEST_F(GpuControlListEntryTest, ChromeOSEntry) {
+  const std::string json = LONG_STRING_CONST(
+      {
+        "id": 1,
+        "os": {
+          "type": "chromeos"
+        },
+        "features": [
+          "test_feature_0"
+        ]
+      }
+  );
+  ScopedEntry entry(GetEntryFromString(json));
+  EXPECT_TRUE(entry != NULL);
+  EXPECT_EQ(GpuControlList::kOsChromeOS, entry->GetOsType());
+
+  const GpuControlList::OsType os_type[] = {
+    GpuControlList::kOsMacosx,
+    GpuControlList::kOsWin,
+    GpuControlList::kOsLinux,
+    GpuControlList::kOsAndroid
+  };
+  for (size_t i = 0; i < arraysize(os_type); ++i)
+    EXPECT_FALSE(entry->Contains(os_type[i], "10.6", gpu_info()));
+  EXPECT_TRUE(entry->Contains(
+      GpuControlList::kOsChromeOS, "10.6", gpu_info()));
+}
+
+TEST_F(GpuControlListEntryTest, MalformedVendor) {
+  const std::string json = LONG_STRING_CONST(
+      {
+        "id": 1,
+        "vendor_id": "[0x10de]",
+        "features": [
+          "test_feature_0"
+        ]
+      }
+  );
+  ScopedEntry entry(GetEntryFromString(json));
+  EXPECT_TRUE(entry == NULL);
+}
+
+TEST_F(GpuControlListEntryTest, UnknownFieldEntry) {
+  const std::string json = LONG_STRING_CONST(
+      {
+        "id": 1,
+        "unknown_field": 0,
+        "features": [
+          "test_feature_0"
+        ]
+      }
+  );
+  ScopedEntry entry(GetEntryFromString(json));
+  EXPECT_TRUE(entry != NULL);
+  EXPECT_TRUE(entry->contains_unknown_fields());
+  EXPECT_FALSE(entry->contains_unknown_features());
+}
+
+TEST_F(GpuControlListEntryTest, UnknownExceptionFieldEntry) {
+  const std::string json = LONG_STRING_CONST(
+      {
+        "id": 2,
+        "exceptions": [
+          {
+            "unknown_field": 0
+          }
+        ],
+        "features": [
+          "test_feature_0"
+        ]
+      }
+  );
+  ScopedEntry entry(GetEntryFromString(json));
+  EXPECT_TRUE(entry != NULL);
+  EXPECT_TRUE(entry->contains_unknown_fields());
+  EXPECT_FALSE(entry->contains_unknown_features());
+}
+
+TEST_F(GpuControlListEntryTest, UnknownFeatureEntry) {
+  const std::string json = LONG_STRING_CONST(
+      {
+        "id": 1,
+        "features": [
+          "some_unknown_feature",
+          "test_feature_0"
+        ]
+      }
+  );
+  ScopedEntry entry(GetEntryFromString(json));
+  EXPECT_TRUE(entry != NULL);
+  EXPECT_FALSE(entry->contains_unknown_fields());
+  EXPECT_TRUE(entry->contains_unknown_features());
+  EXPECT_EQ(1u, entry->features().size());
+  EXPECT_EQ(1u, entry->features().count(TEST_FEATURE_0));
+
+  const GpuControlList::OsType os_type[] = {
+    GpuControlList::kOsMacosx,
+    GpuControlList::kOsWin,
+    GpuControlList::kOsLinux,
+    GpuControlList::kOsChromeOS,
+    GpuControlList::kOsAndroid
+  };
+  for (size_t i = 0; i < arraysize(os_type); ++i)
+    EXPECT_TRUE(entry->Contains(os_type[i], "10.6", gpu_info()));
+}
+
+TEST_F(GpuControlListEntryTest, GlVendorEntry) {
+  const std::string json = LONG_STRING_CONST(
+      {
+        "id": 1,
+        "gl_vendor": {
+          "op": "beginwith",
+          "value": "NVIDIA"
+        },
+        "features": [
+          "test_feature_0"
+        ]
+      }
+  );
+  ScopedEntry entry(GetEntryFromString(json));
+  EXPECT_TRUE(entry != NULL);
+
+  const GpuControlList::OsType os_type[] = {
+    GpuControlList::kOsMacosx,
+    GpuControlList::kOsWin,
+    GpuControlList::kOsLinux,
+    GpuControlList::kOsChromeOS,
+    GpuControlList::kOsAndroid
+  };
+  for (size_t i = 0; i < arraysize(os_type); ++i)
+    EXPECT_TRUE(entry->Contains(os_type[i], "10.6", gpu_info()));
+}
+
+TEST_F(GpuControlListEntryTest, GlRendererEntry) {
+  const std::string json = LONG_STRING_CONST(
+      {
+        "id": 1,
+        "gl_renderer": {
+          "op": "contains",
+          "value": "GeForce"
+        },
+        "features": [
+          "test_feature_0"
+        ]
+      }
+  );
+  ScopedEntry entry(GetEntryFromString(json));
+  EXPECT_TRUE(entry != NULL);
+
+  const GpuControlList::OsType os_type[] = {
+    GpuControlList::kOsMacosx,
+    GpuControlList::kOsWin,
+    GpuControlList::kOsLinux,
+    GpuControlList::kOsChromeOS,
+    GpuControlList::kOsAndroid
+  };
+  for (size_t i = 0; i < arraysize(os_type); ++i)
+    EXPECT_TRUE(entry->Contains(os_type[i], "10.6", gpu_info()));
+}
+
+TEST_F(GpuControlListEntryTest, PerfGraphicsEntry) {
+  const std::string json = LONG_STRING_CONST(
+      {
+        "id": 1,
+        "perf_graphics": {
+          "op": "<",
+          "value": "6.0"
+        },
+        "features": [
+          "test_feature_0"
+        ]
+      }
+  );
+  ScopedEntry entry(GetEntryFromString(json));
+  EXPECT_TRUE(entry != NULL);
+  EXPECT_TRUE(entry->Contains(
+      GpuControlList::kOsWin, "10.6", gpu_info()));
+}
+
+TEST_F(GpuControlListEntryTest, PerfGamingEntry) {
+  const std::string json = LONG_STRING_CONST(
+      {
+        "id": 1,
+        "perf_graphics": {
+          "op": "<=",
+          "value": "4.0"
+        },
+        "features": [
+          "test_feature_0"
+        ]
+      }
+  );
+  ScopedEntry entry(GetEntryFromString(json));
+  EXPECT_TRUE(entry != NULL);
+  EXPECT_FALSE(entry->Contains(
+      GpuControlList::kOsWin, "10.6", gpu_info()));
+}
+
+TEST_F(GpuControlListEntryTest, PerfOverallEntry) {
+  const std::string json = LONG_STRING_CONST(
+      {
+        "id": 1,
+        "perf_overall": {
+          "op": "between",
+          "value": "1.0",
+          "value2": "9.0"
+        },
+        "features": [
+          "test_feature_0"
+        ]
+      }
+  );
+  ScopedEntry entry(GetEntryFromString(json));
+  EXPECT_TRUE(entry != NULL);
+  EXPECT_TRUE(entry->Contains(
+      GpuControlList::kOsWin, "10.6", gpu_info()));
+}
+
+TEST_F(GpuControlListEntryTest, DisabledEntry) {
+  const std::string json = LONG_STRING_CONST(
+      {
+        "id": 1,
+        "disabled": true,
+        "features": [
+          "test_feature_0"
+        ]
+      }
+  );
+  ScopedEntry entry(GetEntryFromString(json));
+  EXPECT_TRUE(entry != NULL);
+  EXPECT_TRUE(entry->disabled());
+}
+
+TEST_F(GpuControlListEntryTest, OptimusEntry) {
+  const std::string json = LONG_STRING_CONST(
+      {
+        "id": 1,
+        "os": {
+          "type": "linux"
+        },
+        "multi_gpu_style": "optimus",
+        "features": [
+          "test_feature_0"
+        ]
+      }
+  );
+  GPUInfo gpu_info;
+  gpu_info.optimus = true;
+
+  ScopedEntry entry(GetEntryFromString(json));
+  EXPECT_TRUE(entry != NULL);
+  EXPECT_EQ(GpuControlList::kOsLinux, entry->GetOsType());
+  EXPECT_TRUE(entry->Contains(
+      GpuControlList::kOsLinux, "10.6", gpu_info));
+}
+
+TEST_F(GpuControlListEntryTest, AMDSwitchableEntry) {
+  const std::string json = LONG_STRING_CONST(
+      {
+        "id": 1,
+        "os": {
+          "type": "macosx"
+        },
+        "multi_gpu_style": "amd_switchable",
+        "features": [
+          "test_feature_0"
+        ]
+      }
+  );
+  GPUInfo gpu_info;
+  gpu_info.amd_switchable = true;
+
+  ScopedEntry entry(GetEntryFromString(json));
+  EXPECT_TRUE(entry != NULL);
+  EXPECT_EQ(GpuControlList::kOsMacosx, entry->GetOsType());
+  EXPECT_TRUE(entry->Contains(
+      GpuControlList::kOsMacosx, "10.6", gpu_info));
+}
+
+TEST_F(GpuControlListEntryTest, LexicalDriverVersionEntry) {
+  const std::string json = LONG_STRING_CONST(
+      {
+        "id": 1,
+        "os": {
+          "type": "linux"
+        },
+        "vendor_id": "0x1002",
+        "driver_version": {
+          "op": "=",
+          "style": "lexical",
+          "number": "8.76"
+        },
+        "features": [
+          "test_feature_0"
+        ]
+      }
+  );
+  GPUInfo gpu_info;
+  gpu_info.gpu.vendor_id = 0x1002;
+
+  ScopedEntry entry(GetEntryFromString(json));
+  EXPECT_TRUE(entry != NULL);
+  EXPECT_EQ(GpuControlList::kOsLinux, entry->GetOsType());
+
+  gpu_info.driver_version = "8.76";
+  EXPECT_TRUE(entry->Contains(
+      GpuControlList::kOsLinux, "10.6", gpu_info));
+
+  gpu_info.driver_version = "8.768";
+  EXPECT_TRUE(entry->Contains(
+      GpuControlList::kOsLinux, "10.6", gpu_info));
+
+  gpu_info.driver_version = "8.76.8";
+  EXPECT_TRUE(entry->Contains(
+      GpuControlList::kOsLinux, "10.6", gpu_info));
+}
+
+TEST_F(GpuControlListEntryTest, MultipleGPUsAnyEntry) {
+  const std::string json = LONG_STRING_CONST(
+      {
+        "id": 1,
+        "os": {
+          "type": "macosx"
+        },
+        "vendor_id": "0x8086",
+        "device_id": ["0x0166"],
+        "multi_gpu_category": "any",
+        "features": [
+          "test_feature_0"
+        ]
+      }
+  );
+  ScopedEntry entry(GetEntryFromString(json));
+  EXPECT_TRUE(entry != NULL);
+  EXPECT_EQ(GpuControlList::kOsMacosx, entry->GetOsType());
+
+  GPUInfo gpu_info;
+  gpu_info.gpu.vendor_id = 0x10de;
+  gpu_info.gpu.device_id = 0x1976;
+  EXPECT_FALSE(entry->Contains(
+      GpuControlList::kOsMacosx, "10.6", gpu_info));
+
+  GPUInfo::GPUDevice gpu_device;
+  gpu_device.vendor_id = 0x8086;
+  gpu_device.device_id = 0x0166;
+  gpu_info.secondary_gpus.push_back(gpu_device);
+  EXPECT_TRUE(entry->Contains(
+      GpuControlList::kOsMacosx, "10.6", gpu_info));
+}
+
+TEST_F(GpuControlListEntryTest, MultipleGPUsSecondaryEntry) {
+  const std::string json = LONG_STRING_CONST(
+      {
+        "id": 1,
+        "os": {
+          "type": "macosx"
+        },
+        "vendor_id": "0x8086",
+        "device_id": ["0x0166"],
+        "multi_gpu_category": "secondary",
+        "features": [
+          "test_feature_0"
+        ]
+      }
+  );
+  ScopedEntry entry(GetEntryFromString(json));
+  EXPECT_TRUE(entry != NULL);
+  EXPECT_EQ(GpuControlList::kOsMacosx, entry->GetOsType());
+
+  GPUInfo gpu_info;
+  gpu_info.gpu.vendor_id = 0x10de;
+  gpu_info.gpu.device_id = 0x1976;
+  EXPECT_FALSE(entry->Contains(
+      GpuControlList::kOsMacosx, "10.6", gpu_info));
+
+  GPUInfo::GPUDevice gpu_device;
+  gpu_device.vendor_id = 0x8086;
+  gpu_device.device_id = 0x0166;
+  gpu_info.secondary_gpus.push_back(gpu_device);
+  EXPECT_TRUE(entry->Contains(
+      GpuControlList::kOsMacosx, "10.6", gpu_info));
+}
+
+TEST_F(GpuControlListEntryTest, NeedsMoreInfoEntry) {
+  const std::string json = LONG_STRING_CONST(
+      {
+        "id": 1,
+        "vendor_id": "0x8086",
+        "driver_version": {
+          "op": "<",
+          "number": "10.7"
+        },
+        "features": [
+          "test_feature_1"
+        ]
+      }
+  );
+  ScopedEntry entry(GetEntryFromString(json));
+  EXPECT_TRUE(entry != NULL);
+
+  GPUInfo gpu_info;
+  gpu_info.gpu.vendor_id = 0x8086;
+  EXPECT_TRUE(entry->NeedsMoreInfo(gpu_info));
+
+  gpu_info.driver_version = "10.6";
+  EXPECT_FALSE(entry->NeedsMoreInfo(gpu_info));
+}
+
+TEST_F(GpuControlListEntryTest, NeedsMoreInfoForExceptionsEntry) {
+  const std::string json = LONG_STRING_CONST(
+      {
+        "id": 1,
+        "vendor_id": "0x8086",
+        "exceptions": [
+          {
+            "gl_renderer": {
+              "op": "contains",
+              "value": "mesa"
+            }
+          }
+        ],
+        "features": [
+          "test_feature_1"
+        ]
+      }
+  );
+  ScopedEntry entry(GetEntryFromString(json));
+  EXPECT_TRUE(entry != NULL);
+
+  GPUInfo gpu_info;
+  gpu_info.gpu.vendor_id = 0x8086;
+  EXPECT_TRUE(entry->NeedsMoreInfo(gpu_info));
+
+  gpu_info.gl_renderer = "mesa";
+  EXPECT_FALSE(entry->NeedsMoreInfo(gpu_info));
+}
+
+TEST_F(GpuControlListEntryTest, FeatureTypeAllEntry) {
+  const std::string json = LONG_STRING_CONST(
+      {
+        "id": 1,
+        "features": [
+          "all"
+        ]
+      }
+  );
+  ScopedEntry entry(GetEntryFromString(json, true));
+  EXPECT_TRUE(entry != NULL);
+  EXPECT_EQ(3u, entry->features().size());
+  EXPECT_EQ(1u, entry->features().count(TEST_FEATURE_0));
+  EXPECT_EQ(1u, entry->features().count(TEST_FEATURE_1));
+  EXPECT_EQ(1u, entry->features().count(TEST_FEATURE_2));
+}
+
+}  // namespace content
+
diff --git a/content/browser/gpu/gpu_control_list_machine_model_info_unittest.cc b/content/browser/gpu/gpu_control_list_machine_model_info_unittest.cc
new file mode 100644
index 0000000..8d00a33
--- /dev/null
+++ b/content/browser/gpu/gpu_control_list_machine_model_info_unittest.cc
@@ -0,0 +1,57 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/gpu/gpu_control_list.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+class MachineModelInfoTest : public testing::Test {
+ public:
+  MachineModelInfoTest() { }
+  virtual ~MachineModelInfoTest() { }
+
+  typedef GpuControlList::MachineModelInfo MachineModelInfo;
+};
+
+TEST_F(MachineModelInfoTest, ValidModelInfo) {
+  const std::string name_op[] = {
+    "contains",
+    "beginwith",
+    "endwith",
+    "="
+  };
+  const std::string version_op[] = {
+    "=",
+    "<",
+    "<=",
+    ">",
+    ">=",
+    "any",
+    "between"
+  };
+  for (size_t i = 0; i < arraysize(name_op); ++i) {
+    for (size_t j = 0; j < arraysize(version_op); ++j) {
+      std::string version1;
+      std::string version2;
+      if (version_op[j] != "any")
+        version1 = "3.14";
+      if (version_op[j] == "between")
+        version2 = "5.4";
+      MachineModelInfo info(name_op[i], "model",
+                            version_op[j], version1, version2);
+      EXPECT_TRUE(info.IsValid());
+    }
+  }
+}
+
+TEST_F(MachineModelInfoTest, ModelComparison) {
+  MachineModelInfo info("=", "model_a", ">", "3.4", std::string());
+  EXPECT_TRUE(info.Contains("model_a", "4"));
+  EXPECT_FALSE(info.Contains("model_b", "4"));
+  EXPECT_FALSE(info.Contains("model_a", "3.2"));
+}
+
+}  // namespace content
+
diff --git a/content/browser/gpu/gpu_control_list_number_info_unittest.cc b/content/browser/gpu/gpu_control_list_number_info_unittest.cc
new file mode 100644
index 0000000..0cb72a7
--- /dev/null
+++ b/content/browser/gpu/gpu_control_list_number_info_unittest.cc
@@ -0,0 +1,210 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/gpu/gpu_control_list.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+class NumberInfoTest : public testing::Test {
+ public:
+  NumberInfoTest() { }
+  virtual ~NumberInfoTest() { }
+
+  typedef GpuControlList::FloatInfo FloatInfo;
+  typedef GpuControlList::IntInfo IntInfo;
+};
+
+TEST_F(NumberInfoTest, ValidFloatInfo) {
+  const std::string op[] = {
+    "=",
+    "<",
+    "<=",
+    ">",
+    ">=",
+    "any",
+    "between"
+  };
+  for (size_t i = 0; i < arraysize(op); ++i) {
+    std::string value1;
+    std::string value2;
+    if (op[i] != "any")
+      value1 = "3.14";
+    if (op[i] == "between")
+      value2 = "4.21";
+    FloatInfo info(op[i], value1, value2);
+    EXPECT_TRUE(info.IsValid());
+  }
+
+  const std::string value[] = {
+    "1.0E12",
+    "1.0e12",
+    "2013",
+    "1.0e-12",
+    "2.1400",
+    "-2.14",
+  };
+  for (size_t i = 0; i < arraysize(value); ++i) {
+    FloatInfo info("=", value[i], std::string());
+    EXPECT_TRUE(info.IsValid());
+  }
+}
+
+TEST_F(NumberInfoTest, InvalidFloatInfo) {
+  const std::string op[] = {
+    "=",
+    "<",
+    "<=",
+    ">",
+    ">=",
+  };
+  for (size_t i = 0; i < arraysize(op); ++i) {
+    FloatInfo info(op[i], std::string(), std::string());
+    EXPECT_FALSE(info.IsValid());
+  }
+  {
+    FloatInfo info("between", "3.14", std::string());
+    EXPECT_FALSE(info.IsValid());
+  }
+  const std::string value[] = {
+    "1.0 E12",
+    "1.0e 12",
+    " 2013",
+    "2013 ",
+    "- 2.14",
+  };
+  for (size_t i = 0; i < arraysize(value); ++i) {
+    FloatInfo info("=", value[i], std::string());
+    EXPECT_FALSE(info.IsValid());
+  }
+}
+
+TEST_F(NumberInfoTest, FloatComparison) {
+  {
+    FloatInfo info("=", "3.14", std::string());
+    EXPECT_TRUE(info.Contains(3.14f));
+    EXPECT_TRUE(info.Contains(3.1400f));
+    EXPECT_FALSE(info.Contains(3.1f));
+    EXPECT_FALSE(info.Contains(3));
+  }
+  {
+    FloatInfo info(">", "3.14", std::string());
+    EXPECT_FALSE(info.Contains(3.14f));
+    EXPECT_TRUE(info.Contains(3.141f));
+    EXPECT_FALSE(info.Contains(3.1f));
+  }
+  {
+    FloatInfo info("<=", "3.14", std::string());
+    EXPECT_TRUE(info.Contains(3.14f));
+    EXPECT_FALSE(info.Contains(3.141f));
+    EXPECT_TRUE(info.Contains(3.1f));
+  }
+  {
+    FloatInfo info("any", std::string(), std::string());
+    EXPECT_TRUE(info.Contains(3.14f));
+  }
+  {
+    FloatInfo info("between", "3.14", "5.4");
+    EXPECT_TRUE(info.Contains(3.14f));
+    EXPECT_TRUE(info.Contains(5.4f));
+    EXPECT_TRUE(info.Contains(4));
+    EXPECT_FALSE(info.Contains(5.6f));
+    EXPECT_FALSE(info.Contains(3.12f));
+  }
+}
+
+TEST_F(NumberInfoTest, ValidIntInfo) {
+  const std::string op[] = {
+    "=",
+    "<",
+    "<=",
+    ">",
+    ">=",
+    "any",
+    "between"
+  };
+  for (size_t i = 0; i < arraysize(op); ++i) {
+    std::string value1;
+    std::string value2;
+    if (op[i] != "any")
+      value1 = "3";
+    if (op[i] == "between")
+      value2 = "9";
+    IntInfo info(op[i], value1, value2);
+    EXPECT_TRUE(info.IsValid());
+  }
+
+  const std::string value[] = {
+    "12",
+    "-12",
+  };
+  for (size_t i = 0; i < arraysize(value); ++i) {
+    IntInfo info("=", value[i], std::string());
+    EXPECT_TRUE(info.IsValid());
+  }
+}
+
+TEST_F(NumberInfoTest, InvalidIntInfo) {
+  const std::string op[] = {
+    "=",
+    "<",
+    "<=",
+    ">",
+    ">=",
+  };
+  for (size_t i = 0; i < arraysize(op); ++i) {
+    IntInfo info(op[i], std::string(), std::string());
+    EXPECT_FALSE(info.IsValid());
+  }
+  {
+    IntInfo info("between", "3", std::string());
+    EXPECT_FALSE(info.IsValid());
+  }
+  const std::string value[] = {
+    " 12",
+    "12 ",
+    "- 12",
+    " -12",
+    "3.14"
+  };
+  for (size_t i = 0; i < arraysize(value); ++i) {
+    IntInfo info("=", value[i], std::string());
+    EXPECT_FALSE(info.IsValid());
+  }
+}
+
+TEST_F(NumberInfoTest, IntComparison) {
+  {
+    IntInfo info("=", "3", std::string());
+    EXPECT_TRUE(info.Contains(3));
+    EXPECT_FALSE(info.Contains(4));
+  }
+  {
+    IntInfo info(">", "3", std::string());
+    EXPECT_FALSE(info.Contains(2));
+    EXPECT_FALSE(info.Contains(3));
+    EXPECT_TRUE(info.Contains(4));
+  }
+  {
+    IntInfo info("<=", "3", std::string());
+    EXPECT_TRUE(info.Contains(2));
+    EXPECT_TRUE(info.Contains(3));
+    EXPECT_FALSE(info.Contains(4));
+  }
+  {
+    IntInfo info("any", std::string(), std::string());
+    EXPECT_TRUE(info.Contains(3));
+  }
+  {
+    IntInfo info("between", "3", "5");
+    EXPECT_TRUE(info.Contains(3));
+    EXPECT_TRUE(info.Contains(5));
+    EXPECT_TRUE(info.Contains(4));
+    EXPECT_FALSE(info.Contains(6));
+    EXPECT_FALSE(info.Contains(2));
+  }
+}
+
+}  // namespace content
+
diff --git a/content/browser/gpu/gpu_control_list_os_info_unittest.cc b/content/browser/gpu/gpu_control_list_os_info_unittest.cc
new file mode 100644
index 0000000..5ea03b2
--- /dev/null
+++ b/content/browser/gpu/gpu_control_list_os_info_unittest.cc
@@ -0,0 +1,111 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/gpu/gpu_control_list.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+class OsInfoTest : public testing::Test {
+ public:
+  OsInfoTest() { }
+  virtual ~OsInfoTest() { }
+
+  typedef GpuControlList::OsInfo OsInfo;
+};
+
+TEST_F(OsInfoTest, ValidOsInfo) {
+  const std::string os[] = {
+    "win",
+    "linux",
+    "macosx",
+    "chromeos",
+    "android",
+    "any"
+  };
+  const GpuControlList::OsType os_type[] = {
+    GpuControlList::kOsWin,
+    GpuControlList::kOsLinux,
+    GpuControlList::kOsMacosx,
+    GpuControlList::kOsChromeOS,
+    GpuControlList::kOsAndroid,
+    GpuControlList::kOsAny
+  };
+  for (size_t i = 0; i < arraysize(os); ++i) {
+    OsInfo info(os[i], "=", "10.6", std::string());
+    EXPECT_TRUE(info.IsValid());
+    EXPECT_EQ(os_type[i], info.type());
+  }
+  {
+    OsInfo info("any", "any", std::string(), std::string());
+    EXPECT_TRUE(info.IsValid());
+  }
+}
+
+TEST_F(OsInfoTest, InvalidOsInfo) {
+  const std::string os[] = {
+    "win",
+    "linux",
+    "macosx",
+    "chromeos",
+    "android",
+    "any"
+  };
+  for (size_t i = 0; i < arraysize(os); ++i) {
+    {
+      OsInfo info(os[i], std::string(), std::string(), std::string());
+      EXPECT_FALSE(info.IsValid());
+    }
+    {
+      OsInfo info(os[i], "=", std::string(), std::string());
+      EXPECT_FALSE(info.IsValid());
+    }
+    {
+      OsInfo info(os[i], std::string(), "10.6", std::string());
+      EXPECT_FALSE(info.IsValid());
+    }
+  }
+  const std::string os_cap[] = {
+    "Win",
+    "Linux",
+    "MacOSX",
+    "ChromeOS",
+    "Android",
+  };
+  for (size_t i = 0; i < arraysize(os_cap); ++i) {
+    OsInfo info(os_cap[i], "=", "10.6", std::string());
+    EXPECT_FALSE(info.IsValid());
+  }
+}
+
+TEST_F(OsInfoTest, OsComparison) {
+  {
+    OsInfo info("any", "any", std::string(), std::string());
+    const GpuControlList::OsType os_type[] = {
+      GpuControlList::kOsWin, GpuControlList::kOsLinux,
+      GpuControlList::kOsMacosx, GpuControlList::kOsChromeOS,
+      GpuControlList::kOsAndroid,
+    };
+    for (size_t i = 0; i < arraysize(os_type); ++i) {
+      EXPECT_TRUE(info.Contains(os_type[i], std::string()));
+      EXPECT_TRUE(info.Contains(os_type[i], "7.8"));
+    }
+  }
+  {
+    OsInfo info("win", ">=", "6", std::string());
+    EXPECT_FALSE(info.Contains(GpuControlList::kOsMacosx, "10.8.3"));
+    EXPECT_FALSE(info.Contains(GpuControlList::kOsLinux, "10"));
+    EXPECT_FALSE(info.Contains(GpuControlList::kOsChromeOS, "13"));
+    EXPECT_FALSE(info.Contains(GpuControlList::kOsAndroid, "7"));
+    EXPECT_FALSE(info.Contains(GpuControlList::kOsAny, "7"));
+    EXPECT_FALSE(info.Contains(GpuControlList::kOsWin, std::string()));
+    EXPECT_TRUE(info.Contains(GpuControlList::kOsWin, "6"));
+    EXPECT_TRUE(info.Contains(GpuControlList::kOsWin, "6.1"));
+    EXPECT_TRUE(info.Contains(GpuControlList::kOsWin, "7"));
+    EXPECT_FALSE(info.Contains(GpuControlList::kOsWin, "5"));
+  }
+}
+
+}  // namespace content
+
diff --git a/content/browser/gpu/gpu_control_list_string_info_unittest.cc b/content/browser/gpu/gpu_control_list_string_info_unittest.cc
new file mode 100644
index 0000000..c2c8009
--- /dev/null
+++ b/content/browser/gpu/gpu_control_list_string_info_unittest.cc
@@ -0,0 +1,98 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/gpu/gpu_control_list.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+class StringInfoTest : public testing::Test {
+ public:
+  StringInfoTest() { }
+  virtual ~StringInfoTest() { }
+
+  typedef GpuControlList::StringInfo StringInfo;
+};
+
+TEST_F(StringInfoTest, ValidStringInfo) {
+  const std::string op[] = {
+    "contains",
+    "beginwith",
+    "endwith",
+    "="
+  };
+  for (size_t i = 0; i < arraysize(op); ++i) {
+    {
+      StringInfo info(op[i], std::string());
+      EXPECT_TRUE(info.IsValid());
+    }
+    {
+      StringInfo info(op[i], "hello");
+      EXPECT_TRUE(info.IsValid());
+    }
+  }
+}
+
+TEST_F(StringInfoTest, InvalidStringInfo) {
+  const std::string op[] = {
+    "Contains",
+    "BeginWith",
+    "EndWith",
+    " =",
+    "= "
+  };
+  for (size_t i = 0; i < arraysize(op); ++i) {
+    StringInfo info(op[i], "hello");
+    EXPECT_FALSE(info.IsValid());
+  }
+}
+
+TEST_F(StringInfoTest, StringComparison) {
+  {
+    StringInfo info("contains", "happy");
+    EXPECT_TRUE(info.Contains("unhappy"));
+    EXPECT_TRUE(info.Contains("happy1"));
+    EXPECT_TRUE(info.Contains("happy"));
+    EXPECT_TRUE(info.Contains("a happy dog"));
+    EXPECT_TRUE(info.Contains("Happy"));
+    EXPECT_TRUE(info.Contains("HAPPY"));
+    EXPECT_FALSE(info.Contains("ha-ppy"));
+  }
+  {
+    StringInfo info("beginwith", "happy");
+    EXPECT_FALSE(info.Contains("unhappy"));
+    EXPECT_TRUE(info.Contains("happy1"));
+    EXPECT_TRUE(info.Contains("happy"));
+    EXPECT_FALSE(info.Contains("a happy dog"));
+    EXPECT_TRUE(info.Contains("Happy"));
+    EXPECT_TRUE(info.Contains("HAPPY"));
+    EXPECT_FALSE(info.Contains("ha-ppy"));
+  }
+  {
+    StringInfo info("endwith", "happy");
+    EXPECT_TRUE(info.Contains("unhappy"));
+    EXPECT_FALSE(info.Contains("happy1"));
+    EXPECT_TRUE(info.Contains("happy"));
+    EXPECT_FALSE(info.Contains("a happy dog"));
+    EXPECT_TRUE(info.Contains("Happy"));
+    EXPECT_TRUE(info.Contains("HAPPY"));
+    EXPECT_FALSE(info.Contains("ha-ppy"));
+  }
+  {
+    StringInfo info("=", "happy");
+    EXPECT_FALSE(info.Contains("unhappy"));
+    EXPECT_FALSE(info.Contains("happy1"));
+    EXPECT_TRUE(info.Contains("happy"));
+    EXPECT_FALSE(info.Contains("a happy dog"));
+    EXPECT_TRUE(info.Contains("Happy"));
+    EXPECT_TRUE(info.Contains("HAPPY"));
+    EXPECT_FALSE(info.Contains("ha-ppy"));
+    EXPECT_FALSE(info.Contains("ha ppy"));
+    EXPECT_FALSE(info.Contains(" happy"));
+    EXPECT_FALSE(info.Contains("happy "));
+  }
+}
+
+}  // namespace content
+
diff --git a/content/browser/gpu/gpu_control_list_unittest.cc b/content/browser/gpu/gpu_control_list_unittest.cc
index 8793986..0991d27 100644
--- a/content/browser/gpu/gpu_control_list_unittest.cc
+++ b/content/browser/gpu/gpu_control_list_unittest.cc
@@ -17,6 +17,10 @@
 
 #define LONG_STRING_CONST(...) #__VA_ARGS__
 
+#define EXPECT_EMPTY_SET(feature_set) EXPECT_EQ(0u, feature_set.size())
+#define EXPECT_SINGLE_FEATURE(feature_set, feature) \
+    EXPECT_TRUE(feature_set.size() == 1 && feature_set.count(feature) == 1)
+
 namespace content {
 
 enum TestFeatureType {
@@ -37,9 +41,9 @@
 
   GpuControlList* Create() {
     GpuControlList* rt = new GpuControlList();
-    rt->AddFeature("test_feature_0", TEST_FEATURE_0);
-    rt->AddFeature("test_feature_1", TEST_FEATURE_1);
-    rt->AddFeature("test_feature_2", TEST_FEATURE_2);
+    rt->AddSupportedFeature("test_feature_0", TEST_FEATURE_0);
+    rt->AddSupportedFeature("test_feature_1", TEST_FEATURE_1);
+    rt->AddSupportedFeature("test_feature_2", TEST_FEATURE_2);
     return rt;
   }
 
@@ -68,9 +72,9 @@
 TEST_F(GpuControlListTest, DefaultControlListSettings) {
   scoped_ptr<GpuControlList> control_list(Create());
   // Default control list settings: all feature are allowed.
-  int features = control_list->MakeDecision(
+  std::set<int> features = control_list->MakeDecision(
       GpuControlList::kOsMacosx, kOsVersion, gpu_info());
-  EXPECT_EQ(0, features);
+  EXPECT_EMPTY_SET(features);
 }
 
 TEST_F(GpuControlListTest, EmptyControlList) {
@@ -87,10 +91,10 @@
 
   EXPECT_TRUE(control_list->LoadList(empty_list_json,
                                      GpuControlList::kAllOs));
-  EXPECT_EQ("2.5", control_list->GetVersion());
-  int features = control_list->MakeDecision(
+  EXPECT_EQ("2.5", control_list->version());
+  std::set<int> features = control_list->MakeDecision(
       GpuControlList::kOsMacosx, kOsVersion, gpu_info());
-  EXPECT_EQ(0, features);
+  EXPECT_EMPTY_SET(features);
 }
 
 TEST_F(GpuControlListTest, DetailedEntryAndInvalidJson) {
@@ -125,9 +129,9 @@
   scoped_ptr<GpuControlList> control_list(Create());
 
   EXPECT_TRUE(control_list->LoadList(exact_list_json, GpuControlList::kAllOs));
-  int features = control_list->MakeDecision(
+  std::set<int> features = control_list->MakeDecision(
       GpuControlList::kOsMacosx, kOsVersion, gpu_info());
-  EXPECT_EQ(TEST_FEATURE_0, features);
+  EXPECT_SINGLE_FEATURE(features, TEST_FEATURE_0);
 
   // Invalid json input should not change the current control_list settings.
   const std::string invalid_json = "invalid";
@@ -135,7 +139,7 @@
   EXPECT_FALSE(control_list->LoadList(invalid_json, GpuControlList::kAllOs));
   features = control_list->MakeDecision(
       GpuControlList::kOsMacosx, kOsVersion, gpu_info());
-  EXPECT_EQ(TEST_FEATURE_0, features);
+  EXPECT_SINGLE_FEATURE(features, TEST_FEATURE_0);
   std::vector<uint32> entries;
   control_list->GetDecisionEntries(&entries, false);
   ASSERT_EQ(1u, entries.size());
@@ -164,15 +168,15 @@
 
   // ControlList entries won't be filtered to the current OS only upon loading.
   EXPECT_TRUE(control_list->LoadList(vendor_json, GpuControlList::kAllOs));
-  int features = control_list->MakeDecision(
+  std::set<int> features = control_list->MakeDecision(
       GpuControlList::kOsMacosx, kOsVersion, gpu_info());
-  EXPECT_EQ(TEST_FEATURE_0, features);
+  EXPECT_SINGLE_FEATURE(features, TEST_FEATURE_0);
   features = control_list->MakeDecision(
       GpuControlList::kOsWin, kOsVersion, gpu_info());
-  EXPECT_EQ(TEST_FEATURE_0, features);
+  EXPECT_SINGLE_FEATURE(features, TEST_FEATURE_0);
   features = control_list->MakeDecision(
       GpuControlList::kOsLinux, kOsVersion, gpu_info());
-  EXPECT_EQ(TEST_FEATURE_0, features);
+  EXPECT_SINGLE_FEATURE(features, TEST_FEATURE_0);
 #if defined(OS_WIN) || defined(OS_LINUX) || defined(OS_MACOSX) || \
     defined(OS_OPENBSD)
   // ControlList entries will be filtered to the current OS only upon loading.
@@ -180,260 +184,16 @@
       vendor_json, GpuControlList::kCurrentOsOnly));
   features = control_list->MakeDecision(
       GpuControlList::kOsMacosx, kOsVersion, gpu_info());
-  EXPECT_EQ(TEST_FEATURE_0, features);
+  EXPECT_SINGLE_FEATURE(features, TEST_FEATURE_0);
   features = control_list->MakeDecision(
       GpuControlList::kOsWin, kOsVersion, gpu_info());
-  EXPECT_EQ(TEST_FEATURE_0, features);
+  EXPECT_SINGLE_FEATURE(features, TEST_FEATURE_0);
   features = control_list->MakeDecision(
       GpuControlList::kOsLinux, kOsVersion, gpu_info());
-  EXPECT_EQ(TEST_FEATURE_0, features);
+  EXPECT_SINGLE_FEATURE(features, TEST_FEATURE_0);
 #endif
 }
 
-TEST_F(GpuControlListTest, VendorOnLinuxEntry) {
-  // ControlList a vendor on Linux only.
-  const std::string vendor_linux_json = LONG_STRING_CONST(
-      {
-        "name": "gpu control list",
-        "version": "0.1",
-        "entries": [
-          {
-            "id": 1,
-            "os": {
-              "type": "linux"
-            },
-            "vendor_id": "0x10de",
-            "features": [
-              "test_feature_0"
-            ]
-          }
-        ]
-      }
-  );
-  scoped_ptr<GpuControlList> control_list(Create());
-
-  EXPECT_TRUE(control_list->LoadList(
-      vendor_linux_json, GpuControlList::kAllOs));
-  int features = control_list->MakeDecision(
-      GpuControlList::kOsMacosx, kOsVersion, gpu_info());
-  EXPECT_EQ(0, features);
-  features = control_list->MakeDecision(
-      GpuControlList::kOsWin, kOsVersion, gpu_info());
-  EXPECT_EQ(0, features);
-  features = control_list->MakeDecision(
-      GpuControlList::kOsLinux, kOsVersion, gpu_info());
-  EXPECT_EQ(TEST_FEATURE_0, features);
-}
-
-TEST_F(GpuControlListTest, AllExceptNVidiaOnLinuxEntry) {
-  // ControlList all cards in Linux except NVIDIA.
-  const std::string linux_except_nvidia_json = LONG_STRING_CONST(
-      {
-        "name": "gpu control list",
-        "version": "0.1",
-        "entries": [
-          {
-            "id": 1,
-            "os": {
-              "type": "linux"
-            },
-            "exceptions": [
-              {
-                "vendor_id": "0x10de"
-              }
-            ],
-            "features": [
-              "test_feature_0"
-            ]
-          }
-        ]
-      }
-  );
-  scoped_ptr<GpuControlList> control_list(Create());
-
-  EXPECT_TRUE(control_list->LoadList(
-      linux_except_nvidia_json, GpuControlList::kAllOs));
-  int features = control_list->MakeDecision(
-      GpuControlList::kOsMacosx, kOsVersion, gpu_info());
-  EXPECT_EQ(0, features);
-  features = control_list->MakeDecision(
-      GpuControlList::kOsWin, kOsVersion, gpu_info());
-  EXPECT_EQ(0, features);
-  features = control_list->MakeDecision(
-      GpuControlList::kOsLinux, kOsVersion, gpu_info());
-  EXPECT_EQ(0, features);
-}
-
-TEST_F(GpuControlListTest, AllExceptIntelOnLinuxEntry) {
-  // ControlList all cards in Linux except Intel.
-  const std::string linux_except_intel_json = LONG_STRING_CONST(
-      {
-        "name": "gpu control list",
-        "version": "0.1",
-        "entries": [
-          {
-            "id": 1,
-            "os": {
-              "type": "linux"
-            },
-            "exceptions": [
-              {
-                "vendor_id": "0x8086"
-              }
-            ],
-            "features": [
-              "test_feature_0"
-            ]
-          }
-        ]
-      }
-  );
-  scoped_ptr<GpuControlList> control_list(Create());
-
-  EXPECT_TRUE(control_list->LoadList(
-      linux_except_intel_json, GpuControlList::kAllOs));
-  int features = control_list->MakeDecision(
-      GpuControlList::kOsMacosx, kOsVersion, gpu_info());
-  EXPECT_EQ(0, features);
-  features = control_list->MakeDecision(
-      GpuControlList::kOsWin, kOsVersion, gpu_info());
-  EXPECT_EQ(0, features);
-  features = control_list->MakeDecision(
-      GpuControlList::kOsLinux, kOsVersion, gpu_info());
-  EXPECT_EQ(TEST_FEATURE_0, features);
-}
-
-TEST_F(GpuControlListTest, DateOnWindowsEntry) {
-  // ControlList all drivers earlier than 2010-5-8 in Windows.
-  const std::string date_windows_json = LONG_STRING_CONST(
-      {
-        "name": "gpu control list",
-        "version": "0.1",
-        "entries": [
-          {
-            "id": 1,
-            "os": {
-              "type": "win"
-            },
-            "driver_date": {
-              "op": "<",
-              "number": "2010.5.8"
-            },
-            "features": [
-              "test_feature_0"
-            ]
-          }
-        ]
-      }
-  );
-  scoped_ptr<GpuControlList> control_list(Create());
-
-  GPUInfo gpu_info;
-  gpu_info.driver_date = "7-14-2009";
-
-  EXPECT_TRUE(control_list->LoadList(
-      date_windows_json, GpuControlList::kAllOs));
-  int features = control_list->MakeDecision(
-      GpuControlList::kOsMacosx, kOsVersion, gpu_info);
-  EXPECT_EQ(0, features);
-  features = control_list->MakeDecision(
-      GpuControlList::kOsLinux, kOsVersion, gpu_info);
-  EXPECT_EQ(0, features);
-  features = control_list->MakeDecision(
-      GpuControlList::kOsWin, kOsVersion, gpu_info);
-  EXPECT_EQ(TEST_FEATURE_0, features);
-
-  gpu_info.driver_date = "07-14-2009";
-  features = control_list->MakeDecision(
-      GpuControlList::kOsWin, kOsVersion, gpu_info);
-  EXPECT_EQ(TEST_FEATURE_0, features);
-
-  gpu_info.driver_date = "1-1-2010";
-  features = control_list->MakeDecision(
-      GpuControlList::kOsWin, kOsVersion, gpu_info);
-  EXPECT_EQ(TEST_FEATURE_0, features);
-
-  gpu_info.driver_date = "05-07-2010";
-  features = control_list->MakeDecision(
-      GpuControlList::kOsWin, kOsVersion, gpu_info);
-  EXPECT_EQ(TEST_FEATURE_0, features);
-
-  gpu_info.driver_date = "5-8-2010";
-  features = control_list->MakeDecision(
-      GpuControlList::kOsWin, kOsVersion, gpu_info);
-  EXPECT_EQ(0, features);
-
-  gpu_info.driver_date = "5-9-2010";
-  features = control_list->MakeDecision(
-      GpuControlList::kOsWin, kOsVersion, gpu_info);
-  EXPECT_EQ(0, features);
-
-  gpu_info.driver_date = "6-2-2010";
-  features = control_list->MakeDecision(
-      GpuControlList::kOsWin, kOsVersion, gpu_info);
-  EXPECT_EQ(0, features);
-}
-
-TEST_F(GpuControlListTest, MultipleDevicesEntry) {
-  const std::string devices_json = LONG_STRING_CONST(
-      {
-        "name": "gpu control list",
-        "version": "0.1",
-        "entries": [
-          {
-            "id": 1,
-            "vendor_id": "0x10de",
-            "device_id": ["0x1023", "0x0640"],
-            "features": [
-              "test_feature_0"
-            ]
-          }
-        ]
-      }
-  );
-  scoped_ptr<GpuControlList> control_list(Create());
-
-  EXPECT_TRUE(control_list->LoadList(devices_json, GpuControlList::kAllOs));
-  int features = control_list->MakeDecision(
-      GpuControlList::kOsMacosx, kOsVersion, gpu_info());
-  EXPECT_EQ(TEST_FEATURE_0, features);
-  features = control_list->MakeDecision(
-      GpuControlList::kOsWin, kOsVersion, gpu_info());
-  EXPECT_EQ(TEST_FEATURE_0, features);
-  features = control_list->MakeDecision(
-      GpuControlList::kOsLinux, kOsVersion, gpu_info());
-  EXPECT_EQ(TEST_FEATURE_0, features);
-}
-
-TEST_F(GpuControlListTest, ChromeOSEntry) {
-  const std::string devices_json = LONG_STRING_CONST(
-      {
-        "name": "gpu control list",
-        "version": "0.1",
-        "entries": [
-          {
-            "id": 1,
-            "os": {
-              "type": "chromeos"
-            },
-            "features": [
-              "test_feature_0"
-            ]
-          }
-        ]
-      }
-  );
-  scoped_ptr<GpuControlList> control_list(Create());
-
-  EXPECT_TRUE(control_list->LoadList(devices_json, GpuControlList::kAllOs));
-  int features = control_list->MakeDecision(
-      GpuControlList::kOsChromeOS, kOsVersion, gpu_info());
-  EXPECT_EQ(TEST_FEATURE_0, features);
-  features = control_list->MakeDecision(
-      GpuControlList::kOsLinux, kOsVersion, gpu_info());
-  EXPECT_EQ(0, features);
-}
-
 TEST_F(GpuControlListTest, ChromeVersionEntry) {
   const std::string browser_version_json = LONG_STRING_CONST(
       {
@@ -456,39 +216,16 @@
   scoped_ptr<GpuControlList> control_list9(Create());
   EXPECT_TRUE(control_list9->LoadList(
       "9.0", browser_version_json, GpuControlList::kAllOs));
-  int features = control_list9->MakeDecision(
+  std::set<int> features = control_list9->MakeDecision(
       GpuControlList::kOsWin, kOsVersion, gpu_info());
-  EXPECT_EQ(0, features);
+  EXPECT_EMPTY_SET(features);
 
   scoped_ptr<GpuControlList> control_list10(Create());
   EXPECT_TRUE(control_list10->LoadList(
       "10.0", browser_version_json, GpuControlList::kAllOs));
   features = control_list10->MakeDecision(
       GpuControlList::kOsWin, kOsVersion, gpu_info());
-  EXPECT_EQ(TEST_FEATURE_0, features);
-}
-
-TEST_F(GpuControlListTest, MalformedVendor) {
-  // vendor_id is defined as list instead of string.
-  const std::string malformed_vendor_json = LONG_STRING_CONST(
-      {
-        "name": "gpu control list",
-        "version": "0.1",
-        "entries": [
-          {
-            "id": 1,
-            "vendor_id": "[0x10de]",
-            "features": [
-              "test_feature_0"
-            ]
-          }
-        ]
-      }
-  );
-  scoped_ptr<GpuControlList> control_list(Create());
-
-  EXPECT_FALSE(control_list->LoadList(
-      malformed_vendor_json, GpuControlList::kAllOs));
+  EXPECT_SINGLE_FEATURE(features, TEST_FEATURE_0);
 }
 
 TEST_F(GpuControlListTest, UnknownField) {
@@ -519,9 +256,9 @@
       unknown_field_json, GpuControlList::kAllOs));
   EXPECT_EQ(1u, control_list->num_entries());
   EXPECT_TRUE(control_list->contains_unknown_fields());
-  int features = control_list->MakeDecision(
+  std::set<int> features = control_list->MakeDecision(
       GpuControlList::kOsWin, kOsVersion, gpu_info());
-  EXPECT_EQ(TEST_FEATURE_0, features);
+  EXPECT_SINGLE_FEATURE(features, TEST_FEATURE_0);
 }
 
 TEST_F(GpuControlListTest, UnknownExceptionField) {
@@ -563,168 +300,9 @@
       unknown_exception_field_json, GpuControlList::kAllOs));
   EXPECT_EQ(1u, control_list->num_entries());
   EXPECT_TRUE(control_list->contains_unknown_fields());
-  int features = control_list->MakeDecision(
+  std::set<int> features = control_list->MakeDecision(
       GpuControlList::kOsWin, kOsVersion, gpu_info());
-  EXPECT_EQ(TEST_FEATURE_0, features);
-}
-
-TEST_F(GpuControlListTest, UnknownFeature) {
-  const std::string unknown_feature_json = LONG_STRING_CONST(
-      {
-        "name": "gpu control list",
-        "version": "0.1",
-        "entries": [
-          {
-            "id": 1,
-            "features": [
-              "some_unknown_feature",
-              "test_feature_0"
-            ]
-          }
-        ]
-      }
-  );
-  scoped_ptr<GpuControlList> control_list(Create());
-
-  EXPECT_TRUE(control_list->LoadList(
-      unknown_feature_json, GpuControlList::kAllOs));
-  EXPECT_EQ(1u, control_list->num_entries());
-  EXPECT_TRUE(control_list->contains_unknown_fields());
-  int features = control_list->MakeDecision(
-      GpuControlList::kOsWin, kOsVersion, gpu_info());
-  EXPECT_EQ(TEST_FEATURE_0, features);
-}
-
-TEST_F(GpuControlListTest, GlVendor) {
-  const std::string gl_vendor_json = LONG_STRING_CONST(
-      {
-        "name": "gpu control list",
-        "version": "0.1",
-        "entries": [
-          {
-            "id": 1,
-            "gl_vendor": {
-              "op": "beginwith",
-              "value": "NVIDIA"
-            },
-            "features": [
-              "test_feature_0"
-            ]
-          }
-        ]
-      }
-  );
-  scoped_ptr<GpuControlList> control_list(Create());
-  EXPECT_TRUE(control_list->LoadList(gl_vendor_json, GpuControlList::kAllOs));
-  int features = control_list->MakeDecision(
-      GpuControlList::kOsWin, kOsVersion, gpu_info());
-  EXPECT_EQ(TEST_FEATURE_0, features);
-}
-
-TEST_F(GpuControlListTest, GlRenderer) {
-  const std::string gl_renderer_json = LONG_STRING_CONST(
-      {
-        "name": "gpu control list",
-        "version": "0.1",
-        "entries": [
-          {
-            "id": 1,
-            "gl_renderer": {
-              "op": "contains",
-              "value": "GeForce"
-            },
-            "features": [
-              "test_feature_0"
-            ]
-          }
-        ]
-      }
-  );
-
-  scoped_ptr<GpuControlList> control_list(Create());
-  EXPECT_TRUE(control_list->LoadList(gl_renderer_json, GpuControlList::kAllOs));
-  int features = control_list->MakeDecision(
-      GpuControlList::kOsWin, kOsVersion, gpu_info());
-  EXPECT_EQ(TEST_FEATURE_0, features);
-}
-
-TEST_F(GpuControlListTest, PerfGraphics) {
-  const std::string json = LONG_STRING_CONST(
-      {
-        "name": "gpu control list",
-        "version": "0.1",
-        "entries": [
-          {
-            "id": 1,
-            "perf_graphics": {
-              "op": "<",
-              "value": "6.0"
-            },
-            "features": [
-              "test_feature_0"
-            ]
-          }
-        ]
-      }
-  );
-  scoped_ptr<GpuControlList> control_list(Create());
-  EXPECT_TRUE(control_list->LoadList(json, GpuControlList::kAllOs));
-  int features = control_list->MakeDecision(
-      GpuControlList::kOsWin, kOsVersion, gpu_info());
-  EXPECT_EQ(TEST_FEATURE_0, features);
-}
-
-TEST_F(GpuControlListTest, PerfGaming) {
-  const std::string json = LONG_STRING_CONST(
-      {
-        "name": "gpu control list",
-        "version": "0.1",
-        "entries": [
-          {
-            "id": 1,
-            "perf_gaming": {
-              "op": "<=",
-              "value": "4.0"
-            },
-            "features": [
-              "test_feature_0"
-            ]
-          }
-        ]
-      }
-  );
-  scoped_ptr<GpuControlList> control_list(Create());
-  EXPECT_TRUE(control_list->LoadList(json, GpuControlList::kAllOs));
-  int features = control_list->MakeDecision(
-      GpuControlList::kOsWin, kOsVersion, gpu_info());
-  EXPECT_EQ(0, features);
-}
-
-TEST_F(GpuControlListTest, PerfOverall) {
-  const std::string json = LONG_STRING_CONST(
-      {
-        "name": "gpu control list",
-        "version": "0.1",
-        "entries": [
-          {
-            "id": 1,
-            "perf_overall": {
-              "op": "between",
-              "value": "1.0",
-              "value2": "9.0"
-            },
-            "features": [
-              "test_feature_0"
-            ]
-          }
-        ]
-      }
-  );
-  scoped_ptr<GpuControlList> control_list(Create());
-  EXPECT_TRUE(control_list->LoadList(json, GpuControlList::kAllOs));
-  int features = control_list->MakeDecision(
-      GpuControlList::kOsWin, kOsVersion, gpu_info());
-  EXPECT_EQ(TEST_FEATURE_0, features);
+  EXPECT_SINGLE_FEATURE(features, TEST_FEATURE_0);
 }
 
 TEST_F(GpuControlListTest, DisabledEntry) {
@@ -745,9 +323,9 @@
   );
   scoped_ptr<GpuControlList> control_list(Create());
   EXPECT_TRUE(control_list->LoadList(disabled_json, GpuControlList::kAllOs));
-  int features = control_list->MakeDecision(
+  std::set<int> features = control_list->MakeDecision(
       GpuControlList::kOsWin, kOsVersion, gpu_info());
-  EXPECT_EQ(features, 0);
+  EXPECT_EMPTY_SET(features);
   std::vector<uint32> flag_entries;
   control_list->GetDecisionEntries(&flag_entries, false);
   EXPECT_EQ(0u, flag_entries.size());
@@ -755,471 +333,6 @@
   EXPECT_EQ(1u, flag_entries.size());
 }
 
-TEST_F(GpuControlListTest, Optimus) {
-  const std::string optimus_json = LONG_STRING_CONST(
-      {
-        "name": "gpu control list",
-        "version": "0.1",
-        "entries": [
-          {
-            "id": 1,
-            "os": {
-              "type": "linux"
-            },
-            "multi_gpu_style": "optimus",
-            "features": [
-              "test_feature_0"
-            ]
-          }
-        ]
-      }
-  );
-  GPUInfo gpu_info;
-  gpu_info.optimus = true;
-
-  scoped_ptr<GpuControlList> control_list(Create());
-  EXPECT_TRUE(control_list->LoadList(optimus_json, GpuControlList::kAllOs));
-  int features = control_list->MakeDecision(
-      GpuControlList::kOsLinux, kOsVersion, gpu_info);
-  EXPECT_EQ(TEST_FEATURE_0, features);
-}
-
-TEST_F(GpuControlListTest, AMDSwitchable) {
-  const std::string amd_switchable_json = LONG_STRING_CONST(
-      {
-        "name": "gpu control list",
-        "version": "0.1",
-        "entries": [
-          {
-            "id": 1,
-            "os": {
-              "type": "macosx"
-            },
-            "multi_gpu_style": "amd_switchable",
-            "features": [
-              "test_feature_0"
-            ]
-          }
-        ]
-      }
-  );
-  GPUInfo gpu_info;
-  gpu_info.amd_switchable = true;
-
-  scoped_ptr<GpuControlList> control_list(Create());
-  EXPECT_TRUE(control_list->LoadList(amd_switchable_json,
-                                          GpuControlList::kAllOs));
-  int features = control_list->MakeDecision(
-      GpuControlList::kOsMacosx, kOsVersion, gpu_info);
-  EXPECT_EQ(TEST_FEATURE_0, features);
-}
-
-TEST_F(GpuControlListTest, LexicalDriverVersion) {
-  const std::string lexical_json = LONG_STRING_CONST(
-      {
-        "name": "gpu control list",
-        "version": "0.1",
-        "entries": [
-          {
-            "id": 1,
-            "os": {
-              "type": "linux"
-            },
-            "vendor_id": "0x1002",
-            "driver_version": {
-              "op": "<",
-              "style": "lexical",
-              "number": "8.201"
-            },
-            "features": [
-              "test_feature_0"
-            ]
-          }
-        ]
-      }
-  );
-  GPUInfo gpu_info;
-  gpu_info.gpu.vendor_id = 0x1002;
-
-  scoped_ptr<GpuControlList> control_list(Create());
-  EXPECT_TRUE(control_list->LoadList(lexical_json, GpuControlList::kAllOs));
-
-  gpu_info.driver_version = "8.001.100";
-  int features = control_list->MakeDecision(
-      GpuControlList::kOsLinux, kOsVersion, gpu_info);
-  EXPECT_EQ(TEST_FEATURE_0, features);
-
-  gpu_info.driver_version = "8.109";
-  features = control_list->MakeDecision(
-      GpuControlList::kOsLinux, kOsVersion, gpu_info);
-  EXPECT_EQ(TEST_FEATURE_0, features);
-
-  gpu_info.driver_version = "8.10900";
-  features = control_list->MakeDecision(
-      GpuControlList::kOsLinux, kOsVersion, gpu_info);
-  EXPECT_EQ(TEST_FEATURE_0, features);
-
-  gpu_info.driver_version = "8.109.100";
-  features = control_list->MakeDecision(
-      GpuControlList::kOsLinux, kOsVersion, gpu_info);
-  EXPECT_EQ(TEST_FEATURE_0, features);
-
-  gpu_info.driver_version = "8.2";
-  features = control_list->MakeDecision(
-      GpuControlList::kOsLinux, kOsVersion, gpu_info);
-  EXPECT_EQ(TEST_FEATURE_0, features);
-
-  gpu_info.driver_version = "8.20";
-  features = control_list->MakeDecision(
-      GpuControlList::kOsLinux, kOsVersion, gpu_info);
-  EXPECT_EQ(TEST_FEATURE_0, features);
-
-  gpu_info.driver_version = "8.200";
-  features = control_list->MakeDecision(
-      GpuControlList::kOsLinux, kOsVersion, gpu_info);
-  EXPECT_EQ(TEST_FEATURE_0, features);
-
-  gpu_info.driver_version = "8.20.100";
-  features = control_list->MakeDecision(
-      GpuControlList::kOsLinux, kOsVersion, gpu_info);
-  EXPECT_EQ(TEST_FEATURE_0, features);
-
-  gpu_info.driver_version = "8.201";
-  features = control_list->MakeDecision(
-      GpuControlList::kOsLinux, kOsVersion, gpu_info);
-  EXPECT_EQ(0, features);
-
-  gpu_info.driver_version = "8.2010";
-  features = control_list->MakeDecision(
-      GpuControlList::kOsLinux, kOsVersion, gpu_info);
-  EXPECT_EQ(0, features);
-
-  gpu_info.driver_version = "8.21";
-  features = control_list->MakeDecision(
-      GpuControlList::kOsLinux, kOsVersion, gpu_info);
-  EXPECT_EQ(0, features);
-
-  gpu_info.driver_version = "8.21.100";
-  features = control_list->MakeDecision(
-      GpuControlList::kOsLinux, kOsVersion, gpu_info);
-  EXPECT_EQ(0, features);
-
-  gpu_info.driver_version = "9.002";
-  features = control_list->MakeDecision(
-      GpuControlList::kOsLinux, kOsVersion, gpu_info);
-  EXPECT_EQ(0, features);
-
-  gpu_info.driver_version = "9.201";
-  features = control_list->MakeDecision(
-      GpuControlList::kOsLinux, kOsVersion, gpu_info);
-  EXPECT_EQ(0, features);
-
-  gpu_info.driver_version = "12";
-  features = control_list->MakeDecision(
-      GpuControlList::kOsLinux, kOsVersion, gpu_info);
-  EXPECT_EQ(0, features);
-
-  gpu_info.driver_version = "12.201";
-  features = control_list->MakeDecision(
-      GpuControlList::kOsLinux, kOsVersion, gpu_info);
-  EXPECT_EQ(0, features);
-}
-
-TEST_F(GpuControlListTest, LexicalDriverVersion2) {
-  const std::string lexical_json = LONG_STRING_CONST(
-      {
-        "name": "gpu control list",
-        "version": "0.1",
-        "entries": [
-          {
-            "id": 1,
-            "os": {
-              "type": "linux"
-            },
-            "vendor_id": "0x1002",
-            "driver_version": {
-              "op": "<",
-              "style": "lexical",
-              "number": "9.002"
-            },
-            "features": [
-              "test_feature_0"
-            ]
-          }
-        ]
-      }
-  );
-  GPUInfo gpu_info;
-  gpu_info.gpu.vendor_id = 0x1002;
-
-  scoped_ptr<GpuControlList> control_list(Create());
-  EXPECT_TRUE(control_list->LoadList(lexical_json, GpuControlList::kAllOs));
-
-  gpu_info.driver_version = "8.001.100";
-  int features = control_list->MakeDecision(
-      GpuControlList::kOsLinux, kOsVersion, gpu_info);
-  EXPECT_EQ(TEST_FEATURE_0, features);
-
-  gpu_info.driver_version = "8.109";
-  features = control_list->MakeDecision(
-      GpuControlList::kOsLinux, kOsVersion, gpu_info);
-  EXPECT_EQ(TEST_FEATURE_0, features);
-
-  gpu_info.driver_version = "8.10900";
-  features = control_list->MakeDecision(
-      GpuControlList::kOsLinux, kOsVersion, gpu_info);
-  EXPECT_EQ(TEST_FEATURE_0, features);
-
-  gpu_info.driver_version = "8.109.100";
-  features = control_list->MakeDecision(
-      GpuControlList::kOsLinux, kOsVersion, gpu_info);
-  EXPECT_EQ(TEST_FEATURE_0, features);
-
-  gpu_info.driver_version = "8.2";
-  features = control_list->MakeDecision(
-      GpuControlList::kOsLinux, kOsVersion, gpu_info);
-  EXPECT_EQ(TEST_FEATURE_0, features);
-
-  gpu_info.driver_version = "8.20";
-  features = control_list->MakeDecision(
-      GpuControlList::kOsLinux, kOsVersion, gpu_info);
-  EXPECT_EQ(TEST_FEATURE_0, features);
-
-  gpu_info.driver_version = "8.200";
-  features = control_list->MakeDecision(
-      GpuControlList::kOsLinux, kOsVersion, gpu_info);
-  EXPECT_EQ(TEST_FEATURE_0, features);
-
-  gpu_info.driver_version = "8.20.100";
-  features = control_list->MakeDecision(
-      GpuControlList::kOsLinux, kOsVersion, gpu_info);
-  EXPECT_EQ(TEST_FEATURE_0, features);
-
-  gpu_info.driver_version = "8.201";
-  features = control_list->MakeDecision(
-      GpuControlList::kOsLinux, kOsVersion, gpu_info);
-  EXPECT_EQ(TEST_FEATURE_0, features);
-
-  gpu_info.driver_version = "8.2010";
-  features = control_list->MakeDecision(
-      GpuControlList::kOsLinux, kOsVersion, gpu_info);
-  EXPECT_EQ(TEST_FEATURE_0, features);
-
-  gpu_info.driver_version = "8.21";
-  features = control_list->MakeDecision(
-      GpuControlList::kOsLinux, kOsVersion, gpu_info);
-  EXPECT_EQ(TEST_FEATURE_0, features);
-
-  gpu_info.driver_version = "8.21.100";
-  features = control_list->MakeDecision(
-      GpuControlList::kOsLinux, kOsVersion, gpu_info);
-  EXPECT_EQ(TEST_FEATURE_0, features);
-
-  gpu_info.driver_version = "9.002";
-  features = control_list->MakeDecision(
-      GpuControlList::kOsLinux, kOsVersion, gpu_info);
-  EXPECT_EQ(0, features);
-
-  gpu_info.driver_version = "9.201";
-  features = control_list->MakeDecision(
-      GpuControlList::kOsLinux, kOsVersion, gpu_info);
-  EXPECT_EQ(0, features);
-
-  gpu_info.driver_version = "12";
-  features = control_list->MakeDecision(
-      GpuControlList::kOsLinux, kOsVersion, gpu_info);
-  EXPECT_EQ(0, features);
-
-  gpu_info.driver_version = "12.201";
-  features = control_list->MakeDecision(
-      GpuControlList::kOsLinux, kOsVersion, gpu_info);
-  EXPECT_EQ(0, features);
-}
-
-TEST_F(GpuControlListTest, LexicalDriverVersion3) {
-  const std::string lexical_json = LONG_STRING_CONST(
-      {
-        "name": "gpu control list",
-        "version": "0.1",
-        "entries": [
-          {
-            "id": 1,
-            "os": {
-              "type": "linux"
-            },
-            "vendor_id": "0x1002",
-            "driver_version": {
-              "op": "=",
-              "style": "lexical",
-              "number": "8.76"
-            },
-            "features": [
-              "test_feature_0"
-            ]
-          }
-        ]
-      }
-  );
-  GPUInfo gpu_info;
-  gpu_info.gpu.vendor_id = 0x1002;
-
-  scoped_ptr<GpuControlList> control_list(Create());
-  EXPECT_TRUE(control_list->LoadList(lexical_json, GpuControlList::kAllOs));
-
-  gpu_info.driver_version = "8.76";
-  int features = control_list->MakeDecision(
-      GpuControlList::kOsLinux, kOsVersion, gpu_info);
-  EXPECT_EQ(TEST_FEATURE_0, features);
-
-  gpu_info.driver_version = "8.768";
-  features = control_list->MakeDecision(
-      GpuControlList::kOsLinux, kOsVersion, gpu_info);
-  EXPECT_EQ(TEST_FEATURE_0, features);
-
-  gpu_info.driver_version = "8.76.8";
-  features = control_list->MakeDecision(
-      GpuControlList::kOsLinux, kOsVersion, gpu_info);
-  EXPECT_EQ(TEST_FEATURE_0, features);
-}
-
-TEST_F(GpuControlListTest, MultipleGPUsAny) {
-  const std::string multi_gpu_json = LONG_STRING_CONST(
-      {
-        "name": "gpu control list",
-        "version": "0.1",
-        "entries": [
-          {
-            "id": 1,
-            "os": {
-              "type": "macosx"
-            },
-            "vendor_id": "0x8086",
-            "device_id": ["0x0166"],
-            "multi_gpu_category": "any",
-            "features": [
-              "test_feature_0"
-            ]
-          }
-        ]
-      }
-  );
-  GPUInfo gpu_info;
-  gpu_info.gpu.vendor_id = kNvidiaVendorId;
-  gpu_info.gpu.device_id = kNvidiaDeviceId;
-
-  scoped_ptr<GpuControlList> control_list(Create());
-  EXPECT_TRUE(control_list->LoadList(multi_gpu_json,
-                                          GpuControlList::kAllOs));
-  int features = control_list->MakeDecision(
-      GpuControlList::kOsMacosx, kOsVersion, gpu_info);
-  EXPECT_EQ(0, features);
-
-  GPUInfo::GPUDevice gpu_device;
-  gpu_device.vendor_id = kIntelVendorId;
-  gpu_device.device_id = kIntelDeviceId;
-  gpu_info.secondary_gpus.push_back(gpu_device);
-  features = control_list->MakeDecision(
-      GpuControlList::kOsMacosx, kOsVersion, gpu_info);
-  EXPECT_EQ(TEST_FEATURE_0, features);
-}
-
-TEST_F(GpuControlListTest, MultipleGPUsSecondary) {
-  const std::string multi_gpu_json = LONG_STRING_CONST(
-      {
-        "name": "gpu control list",
-        "version": "0.1",
-        "entries": [
-          {
-            "id": 1,
-            "os": {
-              "type": "macosx"
-            },
-            "vendor_id": "0x8086",
-            "device_id": ["0x0166"],
-            "multi_gpu_category": "secondary",
-            "features": [
-              "test_feature_0"
-            ]
-          }
-        ]
-      }
-  );
-  GPUInfo gpu_info;
-  gpu_info.gpu.vendor_id = kNvidiaVendorId;
-  gpu_info.gpu.device_id = kNvidiaDeviceId;
-
-  scoped_ptr<GpuControlList> control_list(Create());
-  EXPECT_TRUE(control_list->LoadList(multi_gpu_json,
-                                          GpuControlList::kAllOs));
-  int features = control_list->MakeDecision(
-      GpuControlList::kOsMacosx, kOsVersion, gpu_info);
-  EXPECT_EQ(0, features);
-
-  GPUInfo::GPUDevice gpu_device;
-  gpu_device.vendor_id = kIntelVendorId;
-  gpu_device.device_id = kIntelDeviceId;
-  gpu_info.secondary_gpus.push_back(gpu_device);
-  features = control_list->MakeDecision(
-      GpuControlList::kOsMacosx, kOsVersion, gpu_info);
-  EXPECT_EQ(TEST_FEATURE_0, features);
-}
-
-TEST_F(GpuControlListTest, NeedsMoreInfo) {
-  const std::string json = LONG_STRING_CONST(
-      {
-        "name": "gpu control list",
-        "version": "0.1",
-        "entries": [
-          {
-            "id": 1,
-            "os": {
-              "type": "linux"
-            },
-            "vendor_id": "0x8086",
-            "driver_version": {
-              "op": "<",
-              "number": "10.7"
-            },
-            "features": [
-              "test_feature_0"
-            ]
-          }
-        ]
-      }
-  );
-  GPUInfo gpu_info;
-  gpu_info.gpu.vendor_id = kIntelVendorId;
-
-  scoped_ptr<GpuControlList> control_list(Create());
-  EXPECT_TRUE(control_list->LoadList(json, GpuControlList::kAllOs));
-
-  // The case this entry does not apply.
-  int features = control_list->MakeDecision(
-      GpuControlList::kOsMacosx, kOsVersion, gpu_info);
-  EXPECT_EQ(0, features);
-  EXPECT_FALSE(control_list->needs_more_info());
-
-  // The case this entry might apply, but need more info.
-  features = control_list->MakeDecision(
-      GpuControlList::kOsLinux, kOsVersion, gpu_info);
-  EXPECT_EQ(0, features);
-  EXPECT_TRUE(control_list->needs_more_info());
-
-  // The case we have full info, and this entry applies.
-  gpu_info.driver_version = "10.6";
-  features = control_list->MakeDecision(
-      GpuControlList::kOsLinux, kOsVersion, gpu_info);
-  EXPECT_EQ(TEST_FEATURE_0, features);
-  EXPECT_FALSE(control_list->needs_more_info());
-
-  // The case we have full info, and this entry does not apply.
-  gpu_info.driver_version = "10.8";
-  features = control_list->MakeDecision(
-      GpuControlList::kOsLinux, kOsVersion, gpu_info);
-  EXPECT_EQ(0, features);
-  EXPECT_FALSE(control_list->needs_more_info());
-}
-
 TEST_F(GpuControlListTest, NeedsMoreInfoForExceptions) {
   const std::string json = LONG_STRING_CONST(
       {
@@ -1254,15 +367,15 @@
   EXPECT_TRUE(control_list->LoadList(json, GpuControlList::kAllOs));
 
   // The case this entry does not apply.
-  int features = control_list->MakeDecision(
+  std::set<int> features = control_list->MakeDecision(
       GpuControlList::kOsMacosx, kOsVersion, gpu_info);
-  EXPECT_EQ(0, features);
+  EXPECT_EMPTY_SET(features);
   EXPECT_FALSE(control_list->needs_more_info());
 
   // The case this entry might apply, but need more info.
   features = control_list->MakeDecision(
       GpuControlList::kOsLinux, kOsVersion, gpu_info);
-  EXPECT_EQ(0, features);
+  EXPECT_EMPTY_SET(features);
   EXPECT_TRUE(control_list->needs_more_info());
 
   // The case we have full info, and the exception applies (so the entry
@@ -1270,14 +383,14 @@
   gpu_info.gl_renderer = "mesa";
   features = control_list->MakeDecision(
       GpuControlList::kOsLinux, kOsVersion, gpu_info);
-  EXPECT_EQ(0, features);
+  EXPECT_EMPTY_SET(features);
   EXPECT_FALSE(control_list->needs_more_info());
 
   // The case we have full info, and this entry applies.
   gpu_info.gl_renderer = "my renderer";
   features = control_list->MakeDecision(GpuControlList::kOsLinux, kOsVersion,
       gpu_info);
-  EXPECT_EQ(TEST_FEATURE_0, features);
+  EXPECT_SINGLE_FEATURE(features, TEST_FEATURE_0);
   EXPECT_FALSE(control_list->needs_more_info());
 }
 
@@ -1321,9 +434,9 @@
 
   scoped_ptr<GpuControlList> control_list(Create());
   EXPECT_TRUE(control_list->LoadList(json, GpuControlList::kAllOs));
-  int features = control_list->MakeDecision(
+  std::set<int> features = control_list->MakeDecision(
       GpuControlList::kOsLinux, kOsVersion, gpu_info);
-  EXPECT_EQ(TEST_FEATURE_0, features);
+  EXPECT_SINGLE_FEATURE(features, TEST_FEATURE_0);
   EXPECT_FALSE(control_list->needs_more_info());
 }
 
diff --git a/content/browser/gpu/gpu_control_list_version_info_unittest.cc b/content/browser/gpu/gpu_control_list_version_info_unittest.cc
new file mode 100644
index 0000000..eb18648
--- /dev/null
+++ b/content/browser/gpu/gpu_control_list_version_info_unittest.cc
@@ -0,0 +1,258 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/gpu/gpu_control_list.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+class VersionInfoTest : public testing::Test {
+ public:
+  VersionInfoTest() { }
+  virtual ~VersionInfoTest() { }
+
+  typedef GpuControlList::VersionInfo VersionInfo;
+};
+
+TEST_F(VersionInfoTest, ValidVersionInfo) {
+  const std::string op[] = {
+    "=",
+    "<",
+    "<=",
+    ">",
+    ">=",
+    "any",
+    "between"
+  };
+  for (size_t i = 0; i < arraysize(op); ++i) {
+    std::string string1;
+    std::string string2;
+    if (op[i] != "any")
+      string1 = "8.9";
+    if (op[i] == "between")
+      string2 = "9.0";
+    VersionInfo info(op[i], std::string(), string1, string2);
+    EXPECT_TRUE(info.IsValid());
+  }
+
+  const std::string style[] = {
+    "lexical",
+    "numerical",
+    ""  // Default, same as "numerical"
+  };
+  for (size_t i =0; i < arraysize(style); ++i) {
+    VersionInfo info("=", style[i], "8.9", std::string());
+    EXPECT_TRUE(info.IsValid());
+    if (style[i] == "lexical")
+      EXPECT_TRUE(info.IsLexical());
+    else
+      EXPECT_FALSE(info.IsLexical());
+  }
+
+  const std::string number[] = {
+    "10",
+    "10.9",
+    "10.0",
+    "10.0.9",
+    "0.8",
+    // Leading 0s are valid.
+    "10.09",
+    // Whitespaces are ignored.
+    " 10.9",
+    "10.9 ",
+    "10 .9",
+    "10. 9",
+  };
+  for (size_t i =0; i < arraysize(number); ++i) {
+    VersionInfo info("=", std::string(), number[i], std::string());
+    EXPECT_TRUE(info.IsValid());
+  }
+}
+
+TEST_F(VersionInfoTest, InvalidVersionInfo) {
+  const std::string op[] = {
+    "=",
+    "<",
+    "<=",
+    ">",
+    ">=",
+    "any",
+    "between"
+  };
+  for (size_t i = 0; i < arraysize(op); ++i) {
+    {
+      VersionInfo info(op[i], std::string(), "8.9", std::string());
+      if (op[i] == "between")
+        EXPECT_FALSE(info.IsValid());
+      else
+        EXPECT_TRUE(info.IsValid());
+    }
+    {
+      VersionInfo info(op[i], std::string(), std::string(), std::string());
+      if (op[i] == "any")
+        EXPECT_TRUE(info.IsValid());
+      else
+        EXPECT_FALSE(info.IsValid());
+    }
+    {
+      VersionInfo info(op[i], std::string(), "8.9", "9.0");
+      EXPECT_TRUE(info.IsValid());
+    }
+  }
+
+  const std::string number[] = {
+    "8.E",
+    "8-9",
+  };
+  for (size_t i = 0; i < arraysize(number); ++i) {
+    VersionInfo info("=", std::string(), number[i], std::string());
+    EXPECT_FALSE(info.IsValid());
+  }
+}
+
+TEST_F(VersionInfoTest, VersionComparison) {
+  {
+    VersionInfo info("any", std::string(), std::string(), std::string());
+    EXPECT_TRUE(info.Contains("0"));
+    EXPECT_TRUE(info.Contains("8.9"));
+    EXPECT_TRUE(info.Contains("100"));
+  }
+  {
+    VersionInfo info(">", std::string(), "8.9", std::string());
+    EXPECT_FALSE(info.Contains("7"));
+    EXPECT_FALSE(info.Contains("8.9"));
+    EXPECT_FALSE(info.Contains("8.9.1"));
+    EXPECT_TRUE(info.Contains("9"));
+  }
+  {
+    VersionInfo info(">=", std::string(), "8.9", std::string());
+    EXPECT_FALSE(info.Contains("7"));
+    EXPECT_TRUE(info.Contains("8.9"));
+    EXPECT_TRUE(info.Contains("8.9.1"));
+    EXPECT_TRUE(info.Contains("9"));
+  }
+  {
+    VersionInfo info("=", std::string(), "8.9", std::string());
+    EXPECT_FALSE(info.Contains("7"));
+    EXPECT_TRUE(info.Contains("8"));
+    EXPECT_TRUE(info.Contains("8.9"));
+    EXPECT_TRUE(info.Contains("8.9.1"));
+    EXPECT_FALSE(info.Contains("9"));
+  }
+  {
+    VersionInfo info("<", std::string(), "8.9", std::string());
+    EXPECT_TRUE(info.Contains("7"));
+    EXPECT_TRUE(info.Contains("8.8"));
+    EXPECT_FALSE(info.Contains("8"));
+    EXPECT_FALSE(info.Contains("8.9"));
+    EXPECT_FALSE(info.Contains("8.9.1"));
+    EXPECT_FALSE(info.Contains("9"));
+  }
+  {
+    VersionInfo info("<=", std::string(), "8.9", std::string());
+    EXPECT_TRUE(info.Contains("7"));
+    EXPECT_TRUE(info.Contains("8.8"));
+    EXPECT_TRUE(info.Contains("8"));
+    EXPECT_TRUE(info.Contains("8.9"));
+    EXPECT_TRUE(info.Contains("8.9.1"));
+    EXPECT_FALSE(info.Contains("9"));
+  }
+  {
+    VersionInfo info("between", std::string(), "8.9", "9.1");
+    EXPECT_FALSE(info.Contains("7"));
+    EXPECT_FALSE(info.Contains("8.8"));
+    EXPECT_TRUE(info.Contains("8"));
+    EXPECT_TRUE(info.Contains("8.9"));
+    EXPECT_TRUE(info.Contains("8.9.1"));
+    EXPECT_TRUE(info.Contains("9"));
+    EXPECT_TRUE(info.Contains("9.1"));
+    EXPECT_TRUE(info.Contains("9.1.9"));
+    EXPECT_FALSE(info.Contains("9.2"));
+    EXPECT_FALSE(info.Contains("10"));
+  }
+}
+
+TEST_F(VersionInfoTest, DateComparison) {
+  // When we use '-' as splitter, we assume a format of mm-dd-yyyy
+  // or mm-yyyy, i.e., a date.
+  {
+    VersionInfo info("=", std::string(), "1976.3.21", std::string());
+    EXPECT_TRUE(info.Contains("3-21-1976", '-'));
+    EXPECT_TRUE(info.Contains("3-1976", '-'));
+    EXPECT_TRUE(info.Contains("03-1976", '-'));
+    EXPECT_FALSE(info.Contains("21-3-1976", '-'));
+  }
+  {
+    VersionInfo info(">", std::string(), "1976.3.21", std::string());
+    EXPECT_TRUE(info.Contains("3-22-1976", '-'));
+    EXPECT_TRUE(info.Contains("4-1976", '-'));
+    EXPECT_TRUE(info.Contains("04-1976", '-'));
+    EXPECT_FALSE(info.Contains("3-1976", '-'));
+    EXPECT_FALSE(info.Contains("2-1976", '-'));
+  }
+  {
+    VersionInfo info("between", std::string(), "1976.3.21", "2012.12.25");
+    EXPECT_FALSE(info.Contains("3-20-1976", '-'));
+    EXPECT_TRUE(info.Contains("3-21-1976", '-'));
+    EXPECT_TRUE(info.Contains("3-22-1976", '-'));
+    EXPECT_TRUE(info.Contains("3-1976", '-'));
+    EXPECT_TRUE(info.Contains("4-1976", '-'));
+    EXPECT_TRUE(info.Contains("1-1-2000", '-'));
+    EXPECT_TRUE(info.Contains("1-2000", '-'));
+    EXPECT_TRUE(info.Contains("2000", '-'));
+    EXPECT_TRUE(info.Contains("11-2012", '-'));
+    EXPECT_TRUE(info.Contains("12-2012", '-'));
+    EXPECT_TRUE(info.Contains("12-24-2012", '-'));
+    EXPECT_TRUE(info.Contains("12-25-2012", '-'));
+    EXPECT_FALSE(info.Contains("12-26-2012", '-'));
+    EXPECT_FALSE(info.Contains("1-2013", '-'));
+    EXPECT_FALSE(info.Contains("2013", '-'));
+  }
+}
+
+TEST_F(VersionInfoTest, LexicalComparison) {
+  // When we use lexical style, we assume a format major.minor.*.
+  // We apply numerical comparison to major, lexical comparison to others.
+  {
+    VersionInfo info("<", "lexical", "8.201", std::string());
+    EXPECT_TRUE(info.Contains("8.001.100"));
+    EXPECT_TRUE(info.Contains("8.109"));
+    EXPECT_TRUE(info.Contains("8.10900"));
+    EXPECT_TRUE(info.Contains("8.109.100"));
+    EXPECT_TRUE(info.Contains("8.2"));
+    EXPECT_TRUE(info.Contains("8.20"));
+    EXPECT_TRUE(info.Contains("8.200"));
+    EXPECT_TRUE(info.Contains("8.20.100"));
+    EXPECT_FALSE(info.Contains("8.201"));
+    EXPECT_FALSE(info.Contains("8.2010"));
+    EXPECT_FALSE(info.Contains("8.21"));
+    EXPECT_FALSE(info.Contains("8.21.100"));
+    EXPECT_FALSE(info.Contains("9.002"));
+    EXPECT_FALSE(info.Contains("9.201"));
+    EXPECT_FALSE(info.Contains("12"));
+    EXPECT_FALSE(info.Contains("12.201"));
+  }
+  {
+    VersionInfo info("<", "lexical", "9.002", std::string());
+    EXPECT_TRUE(info.Contains("8.001.100"));
+    EXPECT_TRUE(info.Contains("8.109"));
+    EXPECT_TRUE(info.Contains("8.10900"));
+    EXPECT_TRUE(info.Contains("8.109.100"));
+    EXPECT_TRUE(info.Contains("8.2"));
+    EXPECT_TRUE(info.Contains("8.20"));
+    EXPECT_TRUE(info.Contains("8.200"));
+    EXPECT_TRUE(info.Contains("8.20.100"));
+    EXPECT_TRUE(info.Contains("8.201"));
+    EXPECT_TRUE(info.Contains("8.2010"));
+    EXPECT_TRUE(info.Contains("8.21"));
+    EXPECT_TRUE(info.Contains("8.21.100"));
+    EXPECT_FALSE(info.Contains("9.002"));
+    EXPECT_FALSE(info.Contains("9.201"));
+    EXPECT_FALSE(info.Contains("12"));
+    EXPECT_FALSE(info.Contains("12.201"));
+  }
+}
+
+}  // namespace content
+
diff --git a/content/browser/gpu/gpu_data_manager_impl.cc b/content/browser/gpu/gpu_data_manager_impl.cc
index cdc65ee..5f17f0a 100644
--- a/content/browser/gpu/gpu_data_manager_impl.cc
+++ b/content/browser/gpu/gpu_data_manager_impl.cc
@@ -11,11 +11,13 @@
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/command_line.h"
+#include "base/debug/trace_event.h"
 #include "base/file_util.h"
 #include "base/metrics/field_trial.h"
 #include "base/metrics/histogram.h"
-#include "base/string_piece.h"
 #include "base/stringprintf.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_piece.h"
 #include "base/sys_info.h"
 #include "base/values.h"
 #include "base/version.h"
@@ -28,12 +30,14 @@
 #include "content/public/common/content_client.h"
 #include "content/public/common/content_constants.h"
 #include "content/public/common/content_switches.h"
+#include "content/public/common/gpu_feature_type.h"
 #include "gpu/command_buffer/service/gpu_switches.h"
 #include "grit/content_resources.h"
 #include "ui/base/ui_base_switches.h"
 #include "ui/gl/gl_implementation.h"
 #include "ui/gl/gl_switches.h"
 #include "ui/gl/gpu_switching_manager.h"
+#include "webkit/glue/webpreferences.h"
 #include "webkit/plugins/plugin_switches.h"
 
 #if defined(OS_WIN)
@@ -58,6 +62,18 @@
   return version_string;
 }
 
+// Combine the integers into a string, seperated by ','.
+std::string IntSetToString(const std::set<int>& list) {
+  std::string rt;
+  for (std::set<int>::const_iterator it = list.begin();
+       it != list.end(); ++it) {
+    if (!rt.empty())
+      rt += ",";
+    rt += base::IntToString(*it);
+  }
+  return rt;
+}
+
 #if defined(OS_MACOSX)
 void DisplayReconfigCallback(CGDirectDisplayID display,
                              CGDisplayChangeSummaryFlags flags,
@@ -102,22 +118,41 @@
   // This function is for testing only, so disable histograms.
   update_histograms_ = false;
 
-  InitializeImpl(gpu_blacklist_json, "", "", gpu_info);
+  InitializeImpl(gpu_blacklist_json, std::string(), std::string(), gpu_info);
 }
 
-GpuFeatureType GpuDataManagerImpl::GetBlacklistedFeatures() const {
-  if (software_rendering_) {
-    GpuFeatureType flags;
-
+bool GpuDataManagerImpl::IsFeatureBlacklisted(int feature) const {
+  if (use_swiftshader_) {
     // Skia's software rendering is probably more efficient than going through
     // software emulation of the GPU, so use that.
-    flags = GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS;
-    return flags;
+    if (feature == GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS)
+      return true;
+    return false;
   }
 
-  return blacklisted_features_;
+  return (blacklisted_features_.count(feature) == 1);
 }
 
+size_t GpuDataManagerImpl::GetBlacklistedFeatureCount() const {
+  if (use_swiftshader_)
+    return 1;
+  return blacklisted_features_.size();
+}
+
+void GpuDataManagerImpl::AddGpuSwitchCallback(
+    const GpuSwitchCallback& callback) {
+  gpu_switch_callbacks_.push_back(callback);
+}
+
+void GpuDataManagerImpl::RemoveGpuSwitchCallback(
+    const GpuSwitchCallback& callback) {
+  for (size_t i = 0; i < gpu_switch_callbacks_.size(); i++) {
+    if (gpu_switch_callbacks_[i].Equals(callback)) {
+      gpu_switch_callbacks_.erase(gpu_switch_callbacks_.begin() + i);
+      return;
+    }
+  }
+}
 
 GPUInfo GpuDataManagerImpl::GetGPUInfo() const {
   GPUInfo gpu_info;
@@ -133,30 +168,51 @@
   GpuProcessHost::GetProcessHandles(callback);
 }
 
-bool GpuDataManagerImpl::GpuAccessAllowed() const {
-  if (software_rendering_)
+bool GpuDataManagerImpl::GpuAccessAllowed(std::string* reason) const {
+  if (use_swiftshader_)
     return true;
 
-  if (!gpu_info_.gpu_accessible)
+  if (!gpu_info_.gpu_accessible) {
+    if (reason) {
+      *reason = "GPU process launch failed.";
+    }
     return false;
+  }
 
-  if (card_blacklisted_)
+  if (card_blacklisted_) {
+    if (reason) {
+      *reason = "GPU access is disabled ";
+      CommandLine* command_line = CommandLine::ForCurrentProcess();
+      if (command_line->HasSwitch(switches::kDisableGpu))
+        *reason += "through commandline switch --disable-gpu.";
+      else
+        *reason += "in chrome://settings.";
+    }
     return false;
+  }
 
   // We only need to block GPU process if more features are disallowed other
   // than those in the preliminary gpu feature flags because the latter work
   // through renderer commandline switches.
-  uint32 mask = ~(preliminary_blacklisted_features_);
-  if ((blacklisted_features_ & mask) != 0)
+  std::set<int> features = preliminary_blacklisted_features_;
+  MergeFeatureSets(&features, blacklisted_features_);
+  if (features.size() > preliminary_blacklisted_features_.size()) {
+    if (reason) {
+      *reason = "Features are disabled upon full but not preliminary GPU info.";
+    }
     return false;
+  }
 
-  if (blacklisted_features_ == GPU_FEATURE_TYPE_ALL) {
+  if (blacklisted_features_.size() == NUMBER_OF_GPU_FEATURE_TYPES) {
     // On Linux, we use cached GL strings to make blacklist decsions at browser
     // startup time. We need to launch the GPU process to validate these
     // strings even if all features are blacklisted. If all GPU features are
     // disabled, the GPU process will only initialize GL bindings, create a GL
     // context, and collect full GPU info.
 #if !defined(OS_LINUX)
+    if (reason) {
+      *reason = "All GPU features are blacklisted.";
+    }
     return false;
 #endif
   }
@@ -190,13 +246,13 @@
       new GpuMsg_GetVideoMemoryUsageStats());
 }
 
-bool GpuDataManagerImpl::ShouldUseSoftwareRendering() const {
-  return software_rendering_;
+bool GpuDataManagerImpl::ShouldUseSwiftShader() const {
+  return use_swiftshader_;
 }
 
 void GpuDataManagerImpl::RegisterSwiftShaderPath(const base::FilePath& path) {
   swiftshader_path_ = path;
-  EnableSoftwareRenderingIfNecessary();
+  EnableSwiftShaderIfNecessary();
 }
 
 void GpuDataManagerImpl::AddObserver(GpuDataManagerObserver* observer) {
@@ -276,12 +332,17 @@
 
 
 void GpuDataManagerImpl::Initialize() {
+  TRACE_EVENT0("startup", "GpuDataManagerImpl::Initialize");
   CommandLine* command_line = CommandLine::ForCurrentProcess();
   if (command_line->HasSwitch(switches::kSkipGpuDataLoading))
     return;
 
   GPUInfo gpu_info;
-  gpu_info_collector::CollectBasicGraphicsInfo(&gpu_info);
+  {
+    TRACE_EVENT0("startup",
+      "GpuDataManagerImpl::Initialize:CollectBasicGraphicsInfo");
+    gpu_info_collector::CollectBasicGraphicsInfo(&gpu_info);
+  }
 #if defined(ARCH_CPU_X86_FAMILY)
   if (!gpu_info.gpu.vendor_id || !gpu_info.gpu.device_id)
     gpu_info.finalized = true;
@@ -313,8 +374,8 @@
 }
 
 void GpuDataManagerImpl::UpdateGpuInfo(const GPUInfo& gpu_info) {
-  // No further update of gpu_info if falling back to software renderer.
-  if (software_rendering_)
+  // No further update of gpu_info if falling back to SwiftShader.
+  if (use_swiftshader_)
     return;
 
   GPUInfo my_gpu_info;
@@ -328,27 +389,27 @@
 
   GetContentClient()->SetGpuInfo(my_gpu_info);
 
-  if (gpu_blacklist_.get()) {
-    int features = gpu_blacklist_->MakeDecision(
-        GpuControlList::kOsAny, "", my_gpu_info);
+  if (gpu_blacklist_) {
+    std::set<int> features = gpu_blacklist_->MakeDecision(
+        GpuControlList::kOsAny, std::string(), my_gpu_info);
     if (update_histograms_)
       UpdateStats(gpu_blacklist_.get(), features);
 
-    UpdateBlacklistedFeatures(static_cast<GpuFeatureType>(features));
+    UpdateBlacklistedFeatures(features);
   }
-  if (gpu_switching_list_.get()) {
-    int option = gpu_switching_list_->MakeDecision(
-        GpuControlList::kOsAny, "", my_gpu_info);
-    if (option != GPU_SWITCHING_OPTION_UNKNOWN) {
+  if (gpu_switching_list_) {
+    std::set<int> option = gpu_switching_list_->MakeDecision(
+        GpuControlList::kOsAny, std::string(), my_gpu_info);
+    if (option.size() == 1) {
       // Blacklist decision should not overwrite commandline switch from users.
       CommandLine* command_line = CommandLine::ForCurrentProcess();
       if (!command_line->HasSwitch(switches::kGpuSwitching))
-        gpu_switching_ = static_cast<GpuSwitchingOption>(option);
+        gpu_switching_ = static_cast<GpuSwitchingOption>(*(option.begin()));
     }
   }
-  if (gpu_driver_bug_list_.get())
+  if (gpu_driver_bug_list_)
     gpu_driver_bugs_ = gpu_driver_bug_list_->MakeDecision(
-        GpuControlList::kOsAny, "", my_gpu_info);
+        GpuControlList::kOsAny, std::string(), my_gpu_info);
 
   // We have to update GpuFeatureType before notify all the observers.
   NotifyGpuInfoUpdate();
@@ -364,8 +425,7 @@
     CommandLine* command_line) const {
   DCHECK(command_line);
 
-  uint32 flags = GetBlacklistedFeatures();
-  if ((flags & GPU_FEATURE_TYPE_WEBGL)) {
+  if (IsFeatureBlacklisted(GPU_FEATURE_TYPE_WEBGL)) {
 #if !defined(OS_ANDROID)
     if (!command_line->HasSwitch(switches::kDisableExperimentalWebGL))
       command_line->AppendSwitch(switches::kDisableExperimentalWebGL);
@@ -373,19 +433,19 @@
     if (!command_line->HasSwitch(switches::kDisablePepper3d))
       command_line->AppendSwitch(switches::kDisablePepper3d);
   }
-  if ((flags & GPU_FEATURE_TYPE_MULTISAMPLING) &&
+  if (IsFeatureBlacklisted(GPU_FEATURE_TYPE_MULTISAMPLING) &&
       !command_line->HasSwitch(switches::kDisableGLMultisampling))
     command_line->AppendSwitch(switches::kDisableGLMultisampling);
-  if ((flags & GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING) &&
+  if (IsFeatureBlacklisted(GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING) &&
       !command_line->HasSwitch(switches::kDisableAcceleratedCompositing))
     command_line->AppendSwitch(switches::kDisableAcceleratedCompositing);
-  if ((flags & GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS) &&
+  if (IsFeatureBlacklisted(GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS) &&
       !command_line->HasSwitch(switches::kDisableAccelerated2dCanvas))
     command_line->AppendSwitch(switches::kDisableAccelerated2dCanvas);
-  if ((flags & GPU_FEATURE_TYPE_ACCELERATED_VIDEO_DECODE) &&
+  if (IsFeatureBlacklisted(GPU_FEATURE_TYPE_ACCELERATED_VIDEO_DECODE) &&
       !command_line->HasSwitch(switches::kDisableAcceleratedVideoDecode))
     command_line->AppendSwitch(switches::kDisableAcceleratedVideoDecode);
-  if (ShouldUseSoftwareRendering())
+  if (ShouldUseSwiftShader())
     command_line->AppendSwitch(switches::kDisableFlashFullscreen3d);
 }
 
@@ -398,20 +458,19 @@
   base::FilePath swiftshader_path =
       CommandLine::ForCurrentProcess()->GetSwitchValuePath(
           switches::kSwiftShaderPath);
-  uint32 flags = GetBlacklistedFeatures();
-  if ((flags & GPU_FEATURE_TYPE_MULTISAMPLING) &&
+  if (IsFeatureBlacklisted(GPU_FEATURE_TYPE_MULTISAMPLING) &&
       !command_line->HasSwitch(switches::kDisableGLMultisampling))
     command_line->AppendSwitch(switches::kDisableGLMultisampling);
-  if (flags & GPU_FEATURE_TYPE_TEXTURE_SHARING)
+  if (IsFeatureBlacklisted(GPU_FEATURE_TYPE_TEXTURE_SHARING))
     command_line->AppendSwitch(switches::kDisableImageTransportSurface);
 
-  if (software_rendering_) {
+  if (use_swiftshader_) {
     command_line->AppendSwitchASCII(switches::kUseGL, "swiftshader");
     if (swiftshader_path.empty())
       swiftshader_path = swiftshader_path_;
-  } else if ((flags & (GPU_FEATURE_TYPE_WEBGL |
-                GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING |
-                GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS)) &&
+  } else if ((IsFeatureBlacklisted(GPU_FEATURE_TYPE_WEBGL) ||
+              IsFeatureBlacklisted(GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING) ||
+              IsFeatureBlacklisted(GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS)) &&
       (use_gl == "any")) {
     command_line->AppendSwitchASCII(
         switches::kUseGL, gfx::kGLImplementationOSMesaName);
@@ -441,6 +500,11 @@
     command_line->AppendSwitchPath(switches::kSwiftShaderPath,
                                    swiftshader_path);
 
+  if (!gpu_driver_bugs_.empty()) {
+    command_line->AppendSwitchASCII(switches::kGpuDriverBugWorkarounds,
+                                    IntSetToString(gpu_driver_bugs_));
+  }
+
 #if defined(OS_WIN)
   // DisplayLink 7.1 and earlier can cause the GPU process to crash on startup.
   // http://crbug.com/177611
@@ -483,11 +547,10 @@
   DCHECK(command_line);
 
 #if defined(OS_MACOSX)
-  uint32 flags = GetBlacklistedFeatures();
   // TODO(jbauman): Add proper blacklist support for core animation plugins so
   // special-casing this video card won't be necessary. See
   // http://crbug.com/134015
-  if ((flags & GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING) ||
+  if (IsFeatureBlacklisted(GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING) ||
       CommandLine::ForCurrentProcess()->HasSwitch(
           switches::kDisableAcceleratedCompositing)) {
     if (!command_line->HasSwitch(
@@ -498,6 +561,42 @@
 #endif
 }
 
+void GpuDataManagerImpl::UpdateRendererWebPrefs(WebPreferences* prefs) const {
+  DCHECK(prefs);
+
+  if (IsFeatureBlacklisted(GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING))
+    prefs->accelerated_compositing_enabled = false;
+  if (IsFeatureBlacklisted(GPU_FEATURE_TYPE_WEBGL))
+    prefs->experimental_webgl_enabled = false;
+  if (IsFeatureBlacklisted(GPU_FEATURE_TYPE_FLASH3D))
+    prefs->flash_3d_enabled = false;
+  if (IsFeatureBlacklisted(GPU_FEATURE_TYPE_FLASH_STAGE3D)) {
+    prefs->flash_stage3d_enabled = false;
+    prefs->flash_stage3d_baseline_enabled = false;
+  }
+  if (IsFeatureBlacklisted(GPU_FEATURE_TYPE_FLASH_STAGE3D_BASELINE))
+    prefs->flash_stage3d_baseline_enabled = false;
+  if (IsFeatureBlacklisted(GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS))
+    prefs->accelerated_2d_canvas_enabled = false;
+  if (IsFeatureBlacklisted(GPU_FEATURE_TYPE_MULTISAMPLING))
+    prefs->gl_multisampling_enabled = false;
+  if (IsFeatureBlacklisted(GPU_FEATURE_TYPE_3D_CSS)) {
+    prefs->accelerated_compositing_for_3d_transforms_enabled = false;
+    prefs->accelerated_compositing_for_animation_enabled = false;
+  }
+  if (IsFeatureBlacklisted(GPU_FEATURE_TYPE_ACCELERATED_VIDEO))
+    prefs->accelerated_compositing_for_video_enabled = false;
+
+  // Accelerated video and animation are slower than regular when using
+  // SwiftShader. 3D CSS may also be too slow to be worthwhile.
+  if (ShouldUseSwiftShader()) {
+    prefs->accelerated_compositing_for_video_enabled = false;
+    prefs->accelerated_compositing_for_animation_enabled = false;
+    prefs->accelerated_compositing_for_3d_transforms_enabled = false;
+    prefs->accelerated_compositing_for_plugins_enabled = false;
+  }
+}
+
 GpuSwitchingOption GpuDataManagerImpl::GetGpuSwitchingOption() const {
   if (!ui::GpuSwitchingManager::GetInstance()->SupportsDualGpus())
     return GPU_SWITCHING_OPTION_UNKNOWN;
@@ -507,21 +606,22 @@
 void GpuDataManagerImpl::DisableHardwareAcceleration() {
   card_blacklisted_ = true;
 
-  blacklisted_features_ = GPU_FEATURE_TYPE_ALL;
+  for (int i = 0; i < NUMBER_OF_GPU_FEATURE_TYPES; ++i)
+    blacklisted_features_.insert(i);
 
-  EnableSoftwareRenderingIfNecessary();
+  EnableSwiftShaderIfNecessary();
   NotifyGpuInfoUpdate();
 }
 
 std::string GpuDataManagerImpl::GetBlacklistVersion() const {
-  if (gpu_blacklist_.get())
-    return gpu_blacklist_->GetVersion();
+  if (gpu_blacklist_)
+    return gpu_blacklist_->version();
   return "0";
 }
 
 base::ListValue* GpuDataManagerImpl::GetBlacklistReasons() const {
   ListValue* reasons = new ListValue();
-  if (gpu_blacklist_.get())
+  if (gpu_blacklist_)
     gpu_blacklist_->GetReasons(reasons);
   return reasons;
 }
@@ -559,11 +659,10 @@
 }
 
 void GpuDataManagerImpl::HandleGpuSwitch() {
-  if (complete_gpu_info_already_requested_) {
-    complete_gpu_info_already_requested_ = false;
-    gpu_info_.finalized = false;
-    RequestCompleteGpuInfoIfNeeded();
-  }
+  complete_gpu_info_already_requested_ = false;
+  gpu_info_.finalized = false;
+  for (size_t i = 0; i < gpu_switch_callbacks_.size(); ++i)
+    gpu_switch_callbacks_[i].Run();
 }
 
 #if defined(OS_WIN)
@@ -573,16 +672,12 @@
 
   if (gpu_info_.amd_switchable)
     return false;
-  if (software_rendering_)
+  if (use_swiftshader_)
     return false;
   CommandLine* command_line = CommandLine::ForCurrentProcess();
   if (command_line->HasSwitch(switches::kDisableImageTransportSurface))
     return false;
-  uint32 flags = GetBlacklistedFeatures();
-  if (flags & GPU_FEATURE_TYPE_TEXTURE_SHARING)
-    return false;
-
-  return true;
+  return !IsFeatureBlacklisted(GPU_FEATURE_TYPE_TEXTURE_SHARING);
 }
 #endif
 
@@ -614,11 +709,9 @@
 
 GpuDataManagerImpl::GpuDataManagerImpl()
     : complete_gpu_info_already_requested_(false),
-      blacklisted_features_(GPU_FEATURE_TYPE_UNKNOWN),
-      preliminary_blacklisted_features_(GPU_FEATURE_TYPE_UNKNOWN),
       gpu_switching_(GPU_SWITCHING_OPTION_AUTOMATIC),
       observer_list_(new GpuDataManagerObserverList),
-      software_rendering_(false),
+      use_swiftshader_(false),
       card_blacklisted_(false),
       update_histograms_(true),
       window_count_(0),
@@ -687,23 +780,22 @@
 }
 
 void GpuDataManagerImpl::UpdateBlacklistedFeatures(
-    GpuFeatureType features) {
+    const std::set<int>& features) {
   CommandLine* command_line = CommandLine::ForCurrentProcess();
-  int flags = features;
+  blacklisted_features_ = features;
 
   // Force disable using the GPU for these features, even if they would
   // otherwise be allowed.
   if (card_blacklisted_ ||
       command_line->HasSwitch(switches::kBlacklistAcceleratedCompositing)) {
-    flags |= GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING;
+    blacklisted_features_.insert(GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING);
   }
   if (card_blacklisted_ ||
       command_line->HasSwitch(switches::kBlacklistWebGL)) {
-    flags |= GPU_FEATURE_TYPE_WEBGL;
+    blacklisted_features_.insert(GPU_FEATURE_TYPE_WEBGL);
   }
-  blacklisted_features_ = static_cast<GpuFeatureType>(flags);
 
-  EnableSoftwareRenderingIfNecessary();
+  EnableSwiftShaderIfNecessary();
 }
 
 void GpuDataManagerImpl::UpdatePreliminaryBlacklistedFeatures() {
@@ -733,13 +825,13 @@
   observer_list_->Notify(&GpuDataManagerObserver::OnGpuInfoUpdate);
 }
 
-void GpuDataManagerImpl::EnableSoftwareRenderingIfNecessary() {
-  if (!GpuAccessAllowed() ||
-      (blacklisted_features_ & GPU_FEATURE_TYPE_WEBGL)) {
+void GpuDataManagerImpl::EnableSwiftShaderIfNecessary() {
+  if (!GpuAccessAllowed(NULL) ||
+      blacklisted_features_.count(GPU_FEATURE_TYPE_WEBGL)) {
     if (!swiftshader_path_.empty() &&
         !CommandLine::ForCurrentProcess()->HasSwitch(
              switches::kDisableSoftwareRasterizer))
-      software_rendering_ = true;
+      use_swiftshader_ = true;
   }
 }
 
diff --git a/content/browser/gpu/gpu_data_manager_impl.h b/content/browser/gpu/gpu_data_manager_impl.h
index 93fc6c5..5fa8780 100644
--- a/content/browser/gpu/gpu_data_manager_impl.h
+++ b/content/browser/gpu/gpu_data_manager_impl.h
@@ -7,8 +7,11 @@
 
 #include <list>
 #include <map>
+#include <set>
 #include <string>
+#include <vector>
 
+#include "base/callback.h"
 #include "base/compiler_specific.h"
 #include "base/files/file_path.h"
 #include "base/gtest_prod_util.h"
@@ -25,10 +28,12 @@
 #include "content/public/browser/gpu_data_manager.h"
 #include "content/public/common/gpu_info.h"
 #include "content/public/common/gpu_memory_stats.h"
+#include "content/public/common/gpu_switching_option.h"
 #include "content/public/common/three_d_api_types.h"
 
 class CommandLine;
 class GURL;
+struct WebPreferences;
 
 namespace content {
 
@@ -60,15 +65,15 @@
   virtual void InitializeForTesting(
       const std::string& gpu_blacklist_json,
       const GPUInfo& gpu_info) OVERRIDE;
-  virtual GpuFeatureType GetBlacklistedFeatures() const OVERRIDE;
+  virtual bool IsFeatureBlacklisted(int feature) const OVERRIDE;
   virtual GPUInfo GetGPUInfo() const OVERRIDE;
   virtual void GetGpuProcessHandles(
       const GetGpuProcessHandlesCallback& callback) const OVERRIDE;
-  virtual bool GpuAccessAllowed() const OVERRIDE;
+  virtual bool GpuAccessAllowed(std::string* reason) const OVERRIDE;
   virtual void RequestCompleteGpuInfoIfNeeded() OVERRIDE;
   virtual bool IsCompleteGpuInfoAvailable() const OVERRIDE;
   virtual void RequestVideoMemoryUsageStatsUpdate() const OVERRIDE;
-  virtual bool ShouldUseSoftwareRendering() const OVERRIDE;
+  virtual bool ShouldUseSwiftShader() const OVERRIDE;
   virtual void RegisterSwiftShaderPath(const base::FilePath& path) OVERRIDE;
   virtual void AddObserver(GpuDataManagerObserver* observer) OVERRIDE;
   virtual void RemoveObserver(GpuDataManagerObserver* observer) OVERRIDE;
@@ -106,6 +111,9 @@
   // kDisableCoreAnimationPlugins.
   void AppendPluginCommandLine(CommandLine* command_line) const;
 
+  // Update WebPreferences for renderer based on blacklisting decisions.
+  void UpdateRendererWebPrefs(WebPreferences* prefs) const;
+
   GpuSwitchingOption GetGpuSwitchingOption() const;
 
   std::string GetBlacklistVersion() const;
@@ -155,6 +163,15 @@
   // Disables domain blocking for 3D APIs. For use only in tests.
   void DisableDomainBlockingFor3DAPIsForTesting();
 
+  // Get number of features being blacklisted.
+  size_t GetBlacklistedFeatureCount() const;
+
+  typedef base::Callback<void()> GpuSwitchCallback;
+
+  // Add and remove gpu switch callback.
+  void AddGpuSwitchCallback(const GpuSwitchCallback& callback);
+  void RemoveGpuSwitchCallback(const GpuSwitchCallback& callback);
+
  private:
   struct DomainBlockEntry {
     DomainGuilt last_guilt;
@@ -172,11 +189,11 @@
   FRIEND_TEST_ALL_PREFIXES(GpuDataManagerImplTest, GpuSideExceptions);
   FRIEND_TEST_ALL_PREFIXES(GpuDataManagerImplTest,
                            DisableHardwareAcceleration);
-  FRIEND_TEST_ALL_PREFIXES(GpuDataManagerImplTest, SoftwareRendering);
-  FRIEND_TEST_ALL_PREFIXES(GpuDataManagerImplTest, SoftwareRendering2);
+  FRIEND_TEST_ALL_PREFIXES(GpuDataManagerImplTest, SwiftShaderRendering);
+  FRIEND_TEST_ALL_PREFIXES(GpuDataManagerImplTest, SwiftShaderRendering2);
   FRIEND_TEST_ALL_PREFIXES(GpuDataManagerImplTest, GpuInfoUpdate);
   FRIEND_TEST_ALL_PREFIXES(GpuDataManagerImplTest,
-                           NoGpuInfoUpdateWithSoftwareRendering);
+                           NoGpuInfoUpdateWithSwiftShader);
   FRIEND_TEST_ALL_PREFIXES(GpuDataManagerImplTest,
                            GPUVideoMemoryUsageStatsUpdate);
   FRIEND_TEST_ALL_PREFIXES(GpuDataManagerImplTest,
@@ -189,6 +206,8 @@
                            UnblockOtherDomainFrom3DAPIs);
   FRIEND_TEST_ALL_PREFIXES(GpuDataManagerImplTest,
                            UnblockThisDomainFrom3DAPIs);
+  FRIEND_TEST_ALL_PREFIXES(GpuDataManagerImplTest, GpuDriverBugListSingle);
+  FRIEND_TEST_ALL_PREFIXES(GpuDataManagerImplTest, GpuDriverBugListMultiple);
 
   GpuDataManagerImpl();
   virtual ~GpuDataManagerImpl();
@@ -198,7 +217,7 @@
                       const std::string& gpu_driver_bug_list_json,
                       const GPUInfo& gpu_info);
 
-  void UpdateBlacklistedFeatures(GpuFeatureType features);
+  void UpdateBlacklistedFeatures(const std::set<int>& features);
 
   // This should only be called once at initialization time, when preliminary
   // gpu info is collected.
@@ -211,8 +230,8 @@
   // Notify all observers whenever there is a GPU info update.
   void NotifyGpuInfoUpdate();
 
-  // Try to switch to software rendering, if possible and necessary.
-  void EnableSoftwareRenderingIfNecessary();
+  // Try to switch to SwiftShader rendering, if possible and necessary.
+  void EnableSwiftShaderIfNecessary();
 
   // Helper to extract the domain from a given URL.
   std::string GetDomainFromURL(const GURL& url) const;
@@ -232,12 +251,12 @@
 
   bool complete_gpu_info_already_requested_;
 
-  GpuFeatureType blacklisted_features_;
-  GpuFeatureType preliminary_blacklisted_features_;
+  std::set<int> blacklisted_features_;
+  std::set<int> preliminary_blacklisted_features_;
 
   GpuSwitchingOption gpu_switching_;
 
-  int gpu_driver_bugs_;
+  std::set<int> gpu_driver_bugs_;
 
   GPUInfo gpu_info_;
   mutable base::Lock gpu_info_lock_;
@@ -251,7 +270,7 @@
   ListValue log_messages_;
   mutable base::Lock log_messages_lock_;
 
-  bool software_rendering_;
+  bool use_swiftshader_;
 
   base::FilePath swiftshader_path_;
 
@@ -270,6 +289,8 @@
   mutable std::list<base::Time> timestamps_of_gpu_resets_;
   bool domain_blocking_enabled_;
 
+  std::vector<GpuSwitchCallback> gpu_switch_callbacks_;
+
   DISALLOW_COPY_AND_ASSIGN(GpuDataManagerImpl);
 };
 
diff --git a/content/browser/gpu/gpu_data_manager_impl_unittest.cc b/content/browser/gpu/gpu_data_manager_impl_unittest.cc
index c8c1dc6..efbcdfb 100644
--- a/content/browser/gpu/gpu_data_manager_impl_unittest.cc
+++ b/content/browser/gpu/gpu_data_manager_impl_unittest.cc
@@ -2,13 +2,16 @@
 // 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/message_loop.h"
 #include "base/run_loop.h"
 #include "base/time.h"
 #include "content/browser/gpu/gpu_data_manager_impl.h"
 #include "content/public/browser/gpu_data_manager_observer.h"
+#include "content/public/common/gpu_feature_type.h"
 #include "content/public/common/gpu_info.h"
 #include "googleurl/src/gurl.h"
+#include "gpu/command_buffer/service/gpu_switches.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 #define LONG_STRING_CONST(...) #__VA_ARGS__
@@ -96,7 +99,7 @@
   void TestUnblockingDomainFrom3DAPIs(
       GpuDataManagerImpl::DomainGuilt guilt_level);
 
-  MessageLoop message_loop_;
+  base::MessageLoop message_loop_;
 };
 
 // We use new method instead of GetInstance() method because we want
@@ -109,8 +112,10 @@
   // access, to be on the safe side.
   ScopedGpuDataManagerImpl manager;
   ASSERT_TRUE(manager.get());
-  EXPECT_EQ(0, manager->GetBlacklistedFeatures());
-  EXPECT_TRUE(manager->GpuAccessAllowed());
+  EXPECT_EQ(0u, manager->GetBlacklistedFeatureCount());
+  std::string reason;
+  EXPECT_TRUE(manager->GpuAccessAllowed(&reason));
+  EXPECT_TRUE(reason.empty());
 
   const std::string blacklist_json = LONG_STRING_CONST(
       {
@@ -142,23 +147,27 @@
   gpu_info.gpu.device_id = 0x0640;
   manager->InitializeForTesting(blacklist_json, gpu_info);
 
-  EXPECT_TRUE(manager->GpuAccessAllowed());
-  EXPECT_EQ(GPU_FEATURE_TYPE_WEBGL, manager->GetBlacklistedFeatures());
+  EXPECT_TRUE(manager->GpuAccessAllowed(&reason));
+  EXPECT_TRUE(reason.empty());
+  EXPECT_EQ(1u, manager->GetBlacklistedFeatureCount());
+  EXPECT_TRUE(manager->IsFeatureBlacklisted(GPU_FEATURE_TYPE_WEBGL));
 
   gpu_info.gl_vendor = "NVIDIA";
   gpu_info.gl_renderer = "NVIDIA GeForce GT 120";
   manager->UpdateGpuInfo(gpu_info);
-  EXPECT_FALSE(manager->GpuAccessAllowed());
-  EXPECT_EQ(GPU_FEATURE_TYPE_WEBGL |
-            GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS,
-            manager->GetBlacklistedFeatures());
+  EXPECT_FALSE(manager->GpuAccessAllowed(&reason));
+  EXPECT_FALSE(reason.empty());
+  EXPECT_EQ(2u, manager->GetBlacklistedFeatureCount());
+  EXPECT_TRUE(manager->IsFeatureBlacklisted(GPU_FEATURE_TYPE_WEBGL));
+  EXPECT_TRUE(manager->IsFeatureBlacklisted(
+      GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS));
 }
 
 TEST_F(GpuDataManagerImplTest, GpuSideExceptions) {
   ScopedGpuDataManagerImpl manager;
   ASSERT_TRUE(manager.get());
-  EXPECT_EQ(0, manager->GetBlacklistedFeatures());
-  EXPECT_TRUE(manager->GpuAccessAllowed());
+  EXPECT_EQ(0u, manager->GetBlacklistedFeatureCount());
+  EXPECT_TRUE(manager->GpuAccessAllowed(NULL));
 
   const std::string blacklist_json = LONG_STRING_CONST(
       {
@@ -187,68 +196,74 @@
   gpu_info.gpu.device_id = 0x0640;
   manager->InitializeForTesting(blacklist_json, gpu_info);
 
-  EXPECT_TRUE(manager->GpuAccessAllowed());
-  EXPECT_EQ(0, manager->GetBlacklistedFeatures());
+  EXPECT_TRUE(manager->GpuAccessAllowed(NULL));
+  EXPECT_EQ(0u, manager->GetBlacklistedFeatureCount());
 
   // Now assume gpu process launches and full GPU info is collected.
   gpu_info.gl_renderer = "NVIDIA GeForce GT 120";
   manager->UpdateGpuInfo(gpu_info);
-  EXPECT_TRUE(manager->GpuAccessAllowed());
-  EXPECT_EQ(0, manager->GetBlacklistedFeatures());
+  EXPECT_TRUE(manager->GpuAccessAllowed(NULL));
+  EXPECT_EQ(0u, manager->GetBlacklistedFeatureCount());
 }
 
 TEST_F(GpuDataManagerImplTest, DisableHardwareAcceleration) {
   ScopedGpuDataManagerImpl manager;
   ASSERT_TRUE(manager.get());
-  EXPECT_EQ(0, manager->GetBlacklistedFeatures());
-  EXPECT_TRUE(manager->GpuAccessAllowed());
+  EXPECT_EQ(0u, manager->GetBlacklistedFeatureCount());
+  std::string reason;
+  EXPECT_TRUE(manager->GpuAccessAllowed(&reason));
+  EXPECT_TRUE(reason.empty());
 
   manager->DisableHardwareAcceleration();
-  EXPECT_FALSE(manager->GpuAccessAllowed());
-  EXPECT_EQ(GPU_FEATURE_TYPE_ALL, manager->GetBlacklistedFeatures());
+  EXPECT_FALSE(manager->GpuAccessAllowed(&reason));
+  EXPECT_FALSE(reason.empty());
+  EXPECT_EQ(static_cast<size_t>(NUMBER_OF_GPU_FEATURE_TYPES),
+            manager->GetBlacklistedFeatureCount());
 }
 
-TEST_F(GpuDataManagerImplTest, SoftwareRendering) {
+TEST_F(GpuDataManagerImplTest, SwiftShaderRendering) {
   // Blacklist, then register SwiftShader.
   ScopedGpuDataManagerImpl manager;
   ASSERT_TRUE(manager.get());
-  EXPECT_EQ(0, manager->GetBlacklistedFeatures());
-  EXPECT_TRUE(manager->GpuAccessAllowed());
-  EXPECT_FALSE(manager->ShouldUseSoftwareRendering());
+  EXPECT_EQ(0u, manager->GetBlacklistedFeatureCount());
+  EXPECT_TRUE(manager->GpuAccessAllowed(NULL));
+  EXPECT_FALSE(manager->ShouldUseSwiftShader());
 
   manager->DisableHardwareAcceleration();
-  EXPECT_FALSE(manager->GpuAccessAllowed());
-  EXPECT_FALSE(manager->ShouldUseSoftwareRendering());
+  EXPECT_FALSE(manager->GpuAccessAllowed(NULL));
+  EXPECT_FALSE(manager->ShouldUseSwiftShader());
 
-  // If software rendering is enabled, even if we blacklist GPU,
+  // If SwiftShader is enabled, even if we blacklist GPU,
   // GPU process is still allowed.
   const base::FilePath test_path(FILE_PATH_LITERAL("AnyPath"));
   manager->RegisterSwiftShaderPath(test_path);
-  EXPECT_TRUE(manager->ShouldUseSoftwareRendering());
-  EXPECT_TRUE(manager->GpuAccessAllowed());
-  EXPECT_EQ(GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS,
-            manager->GetBlacklistedFeatures());
+  EXPECT_TRUE(manager->ShouldUseSwiftShader());
+  EXPECT_TRUE(manager->GpuAccessAllowed(NULL));
+  EXPECT_EQ(1u, manager->GetBlacklistedFeatureCount());
+  EXPECT_TRUE(
+      manager->IsFeatureBlacklisted(GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS));
 }
 
-TEST_F(GpuDataManagerImplTest, SoftwareRendering2) {
+TEST_F(GpuDataManagerImplTest, SwiftShaderRendering2) {
   // Register SwiftShader, then blacklist.
   ScopedGpuDataManagerImpl manager;
   ASSERT_TRUE(manager.get());
-  EXPECT_EQ(0, manager->GetBlacklistedFeatures());
-  EXPECT_TRUE(manager->GpuAccessAllowed());
-  EXPECT_FALSE(manager->ShouldUseSoftwareRendering());
+  EXPECT_EQ(0u, manager->GetBlacklistedFeatureCount());
+  EXPECT_TRUE(manager->GpuAccessAllowed(NULL));
+  EXPECT_FALSE(manager->ShouldUseSwiftShader());
 
   const base::FilePath test_path(FILE_PATH_LITERAL("AnyPath"));
   manager->RegisterSwiftShaderPath(test_path);
-  EXPECT_EQ(0, manager->GetBlacklistedFeatures());
-  EXPECT_TRUE(manager->GpuAccessAllowed());
-  EXPECT_FALSE(manager->ShouldUseSoftwareRendering());
+  EXPECT_EQ(0u, manager->GetBlacklistedFeatureCount());
+  EXPECT_TRUE(manager->GpuAccessAllowed(NULL));
+  EXPECT_FALSE(manager->ShouldUseSwiftShader());
 
   manager->DisableHardwareAcceleration();
-  EXPECT_TRUE(manager->GpuAccessAllowed());
-  EXPECT_TRUE(manager->ShouldUseSoftwareRendering());
-  EXPECT_EQ(GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS,
-            manager->GetBlacklistedFeatures());
+  EXPECT_TRUE(manager->GpuAccessAllowed(NULL));
+  EXPECT_TRUE(manager->ShouldUseSwiftShader());
+  EXPECT_EQ(1u, manager->GetBlacklistedFeatureCount());
+  EXPECT_TRUE(
+      manager->IsFeatureBlacklisted(GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS));
 }
 
 TEST_F(GpuDataManagerImplTest, GpuInfoUpdate) {
@@ -273,15 +288,15 @@
   EXPECT_TRUE(observer.gpu_info_updated());
 }
 
-TEST_F(GpuDataManagerImplTest, NoGpuInfoUpdateWithSoftwareRendering) {
+TEST_F(GpuDataManagerImplTest, NoGpuInfoUpdateWithSwiftShader) {
   ScopedGpuDataManagerImpl manager;
   ASSERT_TRUE(manager.get());
 
   manager->DisableHardwareAcceleration();
   const base::FilePath test_path(FILE_PATH_LITERAL("AnyPath"));
   manager->RegisterSwiftShaderPath(test_path);
-  EXPECT_TRUE(manager->ShouldUseSoftwareRendering());
-  EXPECT_TRUE(manager->GpuAccessAllowed());
+  EXPECT_TRUE(manager->ShouldUseSwiftShader());
+  EXPECT_TRUE(manager->GpuAccessAllowed(NULL));
 
   {
     base::RunLoop run_loop;
@@ -462,8 +477,8 @@
 
   ScopedGpuDataManagerImpl manager;
   ASSERT_TRUE(manager.get());
-  EXPECT_EQ(0, manager->GetBlacklistedFeatures());
-  EXPECT_TRUE(manager->GpuAccessAllowed());
+  EXPECT_EQ(0u, manager->GetBlacklistedFeatureCount());
+  EXPECT_TRUE(manager->GpuAccessAllowed(NULL));
 
   const std::string blacklist_json = LONG_STRING_CONST(
       {
@@ -495,16 +510,17 @@
   manager->InitializeForTesting(blacklist_json, gpu_info);
 
   // Not enough GPUInfo.
-  EXPECT_TRUE(manager->GpuAccessAllowed());
-  EXPECT_EQ(0, manager->GetBlacklistedFeatures());
+  EXPECT_TRUE(manager->GpuAccessAllowed(NULL));
+  EXPECT_EQ(0u, manager->GetBlacklistedFeatureCount());
 
   // Now assume browser gets GL strings from local state.
   // The entry applies, blacklist more features than from the preliminary step.
   // However, GPU process is not blocked because this is all browser side and
   // happens before renderer launching.
   manager->SetGLStrings(kGLVendorMesa, kGLRendererMesa, kGLVersionMesa801);
-  EXPECT_TRUE(manager->GpuAccessAllowed());
-  EXPECT_EQ(GPU_FEATURE_TYPE_WEBGL, manager->GetBlacklistedFeatures());
+  EXPECT_TRUE(manager->GpuAccessAllowed(NULL));
+  EXPECT_EQ(1u, manager->GetBlacklistedFeatureCount());
+  EXPECT_TRUE(manager->IsFeatureBlacklisted(GPU_FEATURE_TYPE_WEBGL));
 }
 
 TEST_F(GpuDataManagerImplTest, SetGLStringsNoEffects) {
@@ -515,8 +531,8 @@
 
   ScopedGpuDataManagerImpl manager;
   ASSERT_TRUE(manager.get());
-  EXPECT_EQ(0, manager->GetBlacklistedFeatures());
-  EXPECT_TRUE(manager->GpuAccessAllowed());
+  EXPECT_EQ(0u, manager->GetBlacklistedFeatureCount());
+  EXPECT_TRUE(manager->GpuAccessAllowed(NULL));
 
   const std::string blacklist_json = LONG_STRING_CONST(
       {
@@ -553,16 +569,88 @@
   manager->InitializeForTesting(blacklist_json, gpu_info);
 
   // Full GPUInfo, the entry applies.
-  EXPECT_TRUE(manager->GpuAccessAllowed());
-  EXPECT_EQ(GPU_FEATURE_TYPE_WEBGL, manager->GetBlacklistedFeatures());
+  EXPECT_TRUE(manager->GpuAccessAllowed(NULL));
+  EXPECT_EQ(1u, manager->GetBlacklistedFeatureCount());
+  EXPECT_TRUE(manager->IsFeatureBlacklisted(GPU_FEATURE_TYPE_WEBGL));
 
   // Now assume browser gets GL strings from local state.
   // SetGLStrings() has no effects because GPUInfo already got these strings.
   // (Otherwise the entry should not apply.)
   manager->SetGLStrings(kGLVendorMesa, kGLRendererMesa, kGLVersionMesa802);
-  EXPECT_TRUE(manager->GpuAccessAllowed());
-  EXPECT_EQ(GPU_FEATURE_TYPE_WEBGL, manager->GetBlacklistedFeatures());
+  EXPECT_TRUE(manager->GpuAccessAllowed(NULL));
+  EXPECT_EQ(1u, manager->GetBlacklistedFeatureCount());
+  EXPECT_TRUE(manager->IsFeatureBlacklisted(GPU_FEATURE_TYPE_WEBGL));
 }
 #endif  // OS_LINUX
 
+TEST_F(GpuDataManagerImplTest, GpuDriverBugListSingle) {
+  ScopedGpuDataManagerImpl manager;
+  ASSERT_TRUE(manager.get());
+  manager->gpu_driver_bugs_.insert(5);
+
+  CommandLine command_line(0, NULL);
+  manager->AppendGpuCommandLine(&command_line);
+
+  EXPECT_TRUE(command_line.HasSwitch(switches::kGpuDriverBugWorkarounds));
+  std::string args = command_line.GetSwitchValueASCII(
+      switches::kGpuDriverBugWorkarounds);
+  EXPECT_STREQ("5", args.c_str());
+}
+
+TEST_F(GpuDataManagerImplTest, GpuDriverBugListMultiple) {
+  ScopedGpuDataManagerImpl manager;
+  ASSERT_TRUE(manager.get());
+  manager->gpu_driver_bugs_.insert(5);
+  manager->gpu_driver_bugs_.insert(7);
+
+  CommandLine command_line(0, NULL);
+  manager->AppendGpuCommandLine(&command_line);
+
+  EXPECT_TRUE(command_line.HasSwitch(switches::kGpuDriverBugWorkarounds));
+  std::string args = command_line.GetSwitchValueASCII(
+      switches::kGpuDriverBugWorkarounds);
+  EXPECT_STREQ("5,7", args.c_str());
+}
+
+TEST_F(GpuDataManagerImplTest, BlacklistAllFeatures) {
+  ScopedGpuDataManagerImpl manager;
+  ASSERT_TRUE(manager.get());
+  EXPECT_EQ(0u, manager->GetBlacklistedFeatureCount());
+  std::string reason;
+  EXPECT_TRUE(manager->GpuAccessAllowed(&reason));
+  EXPECT_TRUE(reason.empty());
+
+  const std::string blacklist_json = LONG_STRING_CONST(
+      {
+        "name": "gpu blacklist",
+        "version": "0.1",
+        "entries": [
+          {
+            "id": 1,
+            "features": [
+              "all"
+            ]
+          }
+        ]
+      }
+  );
+
+  GPUInfo gpu_info;
+  gpu_info.gpu.vendor_id = 0x10de;
+  gpu_info.gpu.device_id = 0x0640;
+  manager->InitializeForTesting(blacklist_json, gpu_info);
+
+  EXPECT_EQ(NUMBER_OF_GPU_FEATURE_TYPES,
+            manager->GetBlacklistedFeatureCount());
+  // TODO(zmo): remove the Linux specific behavior once we fix
+  // crbug.com/238466.
+#if defined(OS_LINUX)
+  EXPECT_TRUE(manager->GpuAccessAllowed(&reason));
+  EXPECT_TRUE(reason.empty());
+#else
+  EXPECT_FALSE(manager->GpuAccessAllowed(&reason));
+  EXPECT_FALSE(reason.empty());
+#endif
+}
+
 }  // namespace content
diff --git a/content/browser/gpu/gpu_driver_bug_list.cc b/content/browser/gpu/gpu_driver_bug_list.cc
index 2ffad72..9ab93f2 100644
--- a/content/browser/gpu/gpu_driver_bug_list.cc
+++ b/content/browser/gpu/gpu_driver_bug_list.cc
@@ -4,10 +4,21 @@
 
 #include "content/browser/gpu/gpu_driver_bug_list.h"
 
-#include "content/public/common/gpu_feature_type.h"
+#include "base/basictypes.h"
+#include "base/logging.h"
+#include "gpu/command_buffer/service/gpu_driver_bug_workaround_type.h"
 
 namespace content {
 
+namespace {
+
+struct DriverBugInfo {
+  int feature_type;
+  std::string feature_name;
+};
+
+}  // namespace anonymous
+
 GpuDriverBugList::GpuDriverBugList()
     : GpuControlList() {
 }
@@ -18,6 +29,18 @@
 // static
 GpuDriverBugList* GpuDriverBugList::Create() {
   GpuDriverBugList* list = new GpuDriverBugList();
+
+  const DriverBugInfo kFeatureList[] = {
+#define GPU_OP(type, name) { gpu::type, #name },
+    GPU_DRIVER_BUG_WORKAROUNDS(GPU_OP)
+#undef GPU_OP
+  };
+  DCHECK_EQ(static_cast<int>(arraysize(kFeatureList)),
+            gpu::NUMBER_OF_GPU_DRIVER_BUG_WORKAROUND_TYPES);
+  for (int i = 0; i < gpu::NUMBER_OF_GPU_DRIVER_BUG_WORKAROUND_TYPES; ++i) {
+    list->AddSupportedFeature(kFeatureList[i].feature_name,
+                              kFeatureList[i].feature_type);
+  }
   return list;
 }
 
diff --git a/content/browser/gpu/gpu_driver_bug_list.json b/content/browser/gpu/gpu_driver_bug_list.json
index 9ee21df..c559173 100644
--- a/content/browser/gpu/gpu_driver_bug_list.json
+++ b/content/browser/gpu/gpu_driver_bug_list.json
@@ -38,11 +38,12 @@
 // 16. "gpu_count" is a INT structure (defined below).
 // 17  "cpu_info" is a STRING structure (defined below).
 // 18. "exceptions" is a list of entries.
-// 19. "features" is a list of gpu switching options.
+// 19. "features" is a list of driver bug types. For a list of supported types,
+//     see src/gpu/command_buffer/service/gpu_driver_bug_workaround_type.h
 //     This field is mandatory.
 // 20. "description" has the description of the entry.
 // 21. "webkit_bugs" is an array of associated webkit bug numbers.
-// 22. "cr_bugs" is an array of associated webkit bug numbers.
+// 22. "cr_bugs" is an array of associated chromium bug numbers.
 // 23. "browser_version" is a VERSION structure (defined below).  If this
 //     condition is not satisfied, the entry will be ignored.  If it is not
 //     present, then the entry applies to all versions of the browser.
@@ -71,7 +72,234 @@
 {
   "name": "gpu driver bug list",
   // Please update the version number whenever you change this file.
-  "version": "1.0",
+  "version": "1.3",
   "entries": [
+    {
+      "id": 1,
+      "description": "Imagination driver doesn't like uploading lots of buffer data constantly",
+      "os": {
+        "type": "android"
+      },
+      "gl_vendor": {
+        "op": "beginwith",
+        "value": "Imagination"
+      },
+      "features": [
+        "use_client_side_arrays_for_stream_buffers"
+      ]
+    },
+    {
+      "id": 2,
+      "description": "ARM driver doesn't like uploading lots of buffer data constantly",
+      "os": {
+        "type": "android"
+      },
+      "gl_vendor": {
+        "op": "beginwith",
+        "value": "ARM"
+      },
+      "features": [
+        "use_client_side_arrays_for_stream_buffers"
+      ]
+    },
+    {
+      "id": 3,
+      "features": [
+        "set_texture_filter_before_generating_mipmap"
+      ]
+    },
+    {
+      "id": 4,
+      "description": "Need to set the alpha to 255",
+      "features": [
+        "clear_alpha_in_readpixels"
+      ]
+    },
+    {
+      "id": 5,
+      "vendor_id": "0x10de",
+      "features": [
+        "use_current_program_after_successful_link"
+      ]
+    },
+    {
+      "id": 6,
+      "os": {
+        "type": "android"
+      },
+      "gl_vendor": {
+        "op": "beginwith",
+        "value": "Qualcomm"
+      },
+      "features": [
+        "restore_scissor_on_fbo_change",
+        "flush_on_context_switch",
+        "delete_instead_of_resize_fbo"  // Only need this on the ICS driver.
+      ]
+    },
+    {
+      "id": 7,
+      "cr_bugs": [89557],
+      "os": {
+        "type": "macosx"
+      },
+      "vendor_id": "0x10de",
+      "features": [
+        "needs_offscreen_buffer_workaround"
+      ]
+    },
+    {
+      "id": 8,
+      "os": {
+        "type": "macosx"
+      },
+      "vendor_id": "0x1002",
+      "features": [
+        "needs_glsl_built_in_function_emulation"
+      ]
+    },
+    {
+      "id": 9,
+      "description": "Mac AMD drivers get gl_PointCoord backward, rdar://problem/11883495",
+      "os": {
+        "type": "macosx"
+      },
+      "vendor_id": "0x1002",
+      "features": [
+        "reverse_point_sprite_coord_origin"
+      ]
+    },
+    {
+      "id": 10,
+      "description": "Mac Intel drivers get gl_PointCoord backward, rdar://problem/11883495",
+      "os": {
+        "type": "macosx"
+      },
+      "vendor_id": "0x8086",
+      "features": [
+        "reverse_point_sprite_coord_origin"
+      ]
+    },
+    {
+      "id": 11,
+      "os": {
+        "type": "macosx"
+      },
+      "vendor_id": "0x8086",
+      "features": [
+        "max_texture_size_limit_4096"
+      ]
+    },
+    {
+      "id": 12,
+      "os": {
+        "type": "macosx"
+      },
+      "vendor_id": "0x8086",
+      "features": [
+        "max_cube_map_texture_size_limit_1024"
+      ]
+    },
+    {
+      "id": 13,
+      "os": {
+        "type": "macosx",
+        "version": {
+          "op": "<",
+          "number": "10.7.3"
+        }
+      },
+      "vendor_id": "0x8086",
+      "features": [
+        "max_cube_map_texture_size_limit_512"
+      ]
+    },
+    {
+      "id": 14,
+      "os": {
+        "type": "macosx"
+      },
+      "vendor_id": "0x1002",
+      "features": [
+        "max_texture_size_limit_4096",
+        "max_cube_map_texture_size_limit_4096"
+      ]
+    },
+    {
+      "id": 15,
+      "description": "Some Android Qualcomm drivers falsely report GL_ANGLE_framebuffer_multisample",
+      "cr_bugs": [165736],
+      "os": {
+        "type": "android"
+      },
+      "gl_vendor": {
+        "op": "beginwith",
+        "value": "Qualcomm"
+      },
+      "features": [
+        "disable_angle_framebuffer_multisample"
+      ]
+    },
+    {
+      "id": 16,
+      "description": "Intel drivers on Linux appear to be buggy",
+      "os": {
+        "type": "linux"
+      },
+      "vendor_id": "0x8086",
+      "features": [
+        "disable_ext_occlusion_query"
+      ]
+    },
+    {
+      "id": 17,
+      "description": "Some drivers are unable to reset the D3D device in the GPU process sandbox",
+      "os": {
+        "type": "win"
+      },
+      "features": [
+        "exit_on_context_lost"
+      ]
+    },
+    {
+      "id": 18,
+      "description": "Everything except async + NPOT + multiple-of-8 textures are brutally slow for Imagination drivers",
+      "os": {
+        "type": "android"
+      },
+      "gl_vendor": {
+        "op": "beginwith",
+        "value": "Imagination"
+      },
+      "features": [
+        "enable_chromium_fast_npot_mo8_textures"
+      ]
+    },
+    {
+      "id": 19,
+      "os": {
+        "type": "android"
+      },
+      "gl_vendor": {
+        "op": "beginwith",
+        "value": "Qualcomm"
+      },
+      "features": [
+        "disable_depth_texture"
+      ]
+    },
+    {
+      "id": 20,
+      "description": "Disable EXT_draw_buffers on GeForce GT 650M on Mac OS X due to driver bugs.",
+      "os": {
+        "type": "macosx"
+      },
+      "vendor_id": "0x10de",
+      "device_id": ["0x0fd5"],
+      "multi_gpu_category": "any",
+      "features": [
+        "disable_ext_draw_buffers"
+      ]
+    }
   ]
 }
diff --git a/content/browser/gpu/gpu_driver_bug_list_unittest.cc b/content/browser/gpu/gpu_driver_bug_list_unittest.cc
index 4eb6009..931274c 100644
--- a/content/browser/gpu/gpu_driver_bug_list_unittest.cc
+++ b/content/browser/gpu/gpu_driver_bug_list_unittest.cc
@@ -5,10 +5,12 @@
 #include "base/base_paths.h"
 #include "base/file_util.h"
 #include "base/files/file_path.h"
+#include "base/logging.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/path_service.h"
 #include "content/browser/gpu/gpu_driver_bug_list.h"
 #include "content/public/common/gpu_info.h"
+#include "gpu/command_buffer/service/gpu_driver_bug_workaround_type.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 const char kOsVersion[] = "10.6.4";
@@ -25,6 +27,30 @@
     return gpu_info_;
   }
 
+  bool GetCurrentDriverBugList(std::string* json) {
+    DCHECK(json);
+    base::FilePath data_file;
+    if (!PathService::Get(base::DIR_SOURCE_ROOT, &data_file))
+      return false;
+    data_file =
+        data_file.Append(FILE_PATH_LITERAL("content"))
+                 .Append(FILE_PATH_LITERAL("browser"))
+                 .Append(FILE_PATH_LITERAL("gpu"))
+                 .Append(FILE_PATH_LITERAL("gpu_driver_bug_list.json"));
+    if (!file_util::PathExists(data_file))
+      return false;
+    int64 data_file_size64 = 0;
+    if (!file_util::GetFileSize(data_file, &data_file_size64))
+      return false;
+    int data_file_size = static_cast<int>(data_file_size64);
+    scoped_ptr<char[]> data(new char[data_file_size]);
+    if (file_util::ReadFile(data_file, data.get(), data_file_size) !=
+        data_file_size)
+      return false;
+    *json = std::string(data.get(), data_file_size);
+    return true;
+  }
+
  protected:
   virtual void SetUp() {
     gpu_info_.gpu.vendor_id = 0x10de;
@@ -49,25 +75,40 @@
 
 #if !defined(OS_ANDROID)
 TEST_F(GpuDriverBugListTest, CurrentDriverBugListValidation) {
-  base::FilePath data_file;
-  ASSERT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &data_file));
-  data_file =
-      data_file.Append(FILE_PATH_LITERAL("content"))
-               .Append(FILE_PATH_LITERAL("browser"))
-               .Append(FILE_PATH_LITERAL("gpu"))
-               .Append(FILE_PATH_LITERAL("gpu_driver_bug_list.json"));
-  ASSERT_TRUE(file_util::PathExists(data_file));
-  int64 data_file_size64 = 0;
-  ASSERT_TRUE(file_util::GetFileSize(data_file, &data_file_size64));
-  int data_file_size = static_cast<int>(data_file_size64);
-  scoped_array<char> data(new char[data_file_size]);
-  ASSERT_EQ(data_file_size,
-            file_util::ReadFile(data_file, data.get(), data_file_size));
-  std::string json_string(data.get(), data_file_size);
   scoped_ptr<GpuDriverBugList> list(GpuDriverBugList::Create());
-  EXPECT_TRUE(list->LoadList(json_string, GpuControlList::kAllOs));
+  std::string json;
+  EXPECT_TRUE(GetCurrentDriverBugList(&json));
+  EXPECT_TRUE(list->LoadList(json, GpuControlList::kAllOs));
   EXPECT_FALSE(list->contains_unknown_fields());
 }
+
+TEST_F(GpuDriverBugListTest, CurrentListForARM) {
+  scoped_ptr<GpuDriverBugList> list(GpuDriverBugList::Create());
+  std::string json;
+  EXPECT_TRUE(GetCurrentDriverBugList(&json));
+  EXPECT_TRUE(list->LoadList(json, GpuControlList::kAllOs));
+
+  GPUInfo gpu_info;
+  gpu_info.gl_vendor = "ARM";
+  gpu_info.gl_renderer = "MALi_T604";
+  std::set<int> bugs = list->MakeDecision(
+      GpuControlList::kOsAndroid, "4.1", gpu_info);
+  EXPECT_EQ(1u, bugs.count(gpu::USE_CLIENT_SIDE_ARRAYS_FOR_STREAM_BUFFERS));
+}
+
+TEST_F(GpuDriverBugListTest, CurrentListForImagination) {
+  scoped_ptr<GpuDriverBugList> list(GpuDriverBugList::Create());
+  std::string json;
+  EXPECT_TRUE(GetCurrentDriverBugList(&json));
+  EXPECT_TRUE(list->LoadList(json, GpuControlList::kAllOs));
+
+  GPUInfo gpu_info;
+  gpu_info.gl_vendor = "Imagination Technologies";
+  gpu_info.gl_renderer = "PowerVR SGX 540";
+  std::set<int> bugs = list->MakeDecision(
+      GpuControlList::kOsAndroid, "4.1", gpu_info);
+  EXPECT_EQ(1u, bugs.count(gpu::USE_CLIENT_SIDE_ARRAYS_FOR_STREAM_BUFFERS));
+}
 #endif
 
 }  // namespace content
diff --git a/content/browser/gpu/gpu_functional_browsertest.cc b/content/browser/gpu/gpu_functional_browsertest.cc
new file mode 100644
index 0000000..6d31c2a
--- /dev/null
+++ b/content/browser/gpu/gpu_functional_browsertest.cc
@@ -0,0 +1,130 @@
+// Copyright (c) 2013 The Chromium Authors. 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 "content/browser/gpu/gpu_process_host.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/common/content_paths.h"
+#include "content/public/common/content_switches.h"
+#include "content/public/common/url_constants.h"
+#include "content/public/test/browser_test_utils.h"
+#include "content/shell/shell.h"
+#include "content/test/content_browser_test.h"
+#include "content/test/content_browser_test_utils.h"
+
+namespace content {
+
+namespace {
+  void VerifyGPUProcessLaunch(bool* result) {
+    GpuProcessHost* host =
+        GpuProcessHost::Get(GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED,
+                            content::CAUSE_FOR_GPU_LAUNCH_NO_LAUNCH);
+    *result = !!host;
+  }
+}
+
+class GpuFunctionalTest : public ContentBrowserTest {
+ protected:
+  virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
+    base::FilePath test_dir;
+    ASSERT_TRUE(PathService::Get(DIR_TEST_DATA, &test_dir));
+    gpu_test_dir_ = test_dir.AppendASCII("gpu");
+  }
+
+  virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
+    command_line->AppendSwitch(switches::kDisableGpuProcessPrelaunch);
+  }
+
+  void VerifyHardwareAccelerated(const std::string& feature) {
+    NavigateToURL(shell(),
+                  GURL(std::string(chrome::kChromeUIScheme).
+                       append("://").
+                       append(kChromeUIGpuHost)));
+
+    {
+      // Verify that the given feature is hardware accelerated..
+      std::string javascript =
+          "function VerifyHardwareAccelerated(feature) {"
+          "  var list = document.querySelector(\".feature-status-list\");"
+          "  for (var i=0; i < list.childElementCount; i++) {"
+          "    var span_list = list.children[i].getElementsByTagName('span');"
+          "    var feature_str = span_list[0].textContent;"
+          "    var value_str = span_list[1].textContent;"
+          "    if ((feature_str == feature) &&"
+          "        (value_str == 'Hardware accelerated')) {"
+          "      domAutomationController.send(\"success\");"
+          "    }"
+          "  }"
+          "};";
+      javascript.append("VerifyHardwareAccelerated(\"");
+      javascript.append(feature);
+      javascript.append("\");");
+      std::string result;
+      EXPECT_TRUE(ExecuteScriptAndExtractString(shell()->web_contents(),
+                                                javascript,
+                                                &result));
+      EXPECT_EQ(result, "success");
+    }
+  }
+
+  void VerifyGPUProcessOnPage(std::string filename, bool html) {
+    Shell::Initialize();
+    ASSERT_TRUE(test_server()->Start());
+
+    if (html) {
+      std::string url("files/gpu/");
+      GURL full_url = test_server()->GetURL(url.append(filename));
+      NavigateToURL(shell(), full_url);
+    } else {
+      NavigateToURL(shell(),
+                    GetFileUrlWithQuery(gpu_test_dir_.AppendASCII(filename),
+                                       ""));
+    }
+
+    bool result = false;
+    BrowserThread::PostTaskAndReply(
+        BrowserThread::IO,
+        FROM_HERE,
+        base::Bind(&VerifyGPUProcessLaunch, &result),
+        base::MessageLoop::QuitClosure());
+    base::MessageLoop::current()->Run();
+    EXPECT_TRUE(result);
+  }
+
+  base::FilePath gpu_test_dir_;
+};
+
+IN_PROC_BROWSER_TEST_F(GpuFunctionalTest,
+                       MANUAL_TestFeatureHardwareAccelerated) {
+  VerifyHardwareAccelerated("WebGL: ");
+  VerifyHardwareAccelerated("Canvas: ");
+  VerifyHardwareAccelerated("3D CSS: ");
+}
+
+// Verify that gpu process is spawned in webgl example.
+IN_PROC_BROWSER_TEST_F(GpuFunctionalTest, MANUAL_TestWebGL) {
+  VerifyGPUProcessOnPage("functional_webgl.html", true);
+}
+
+// Verify that gpu process is spawned when viewing a 2D canvas.
+IN_PROC_BROWSER_TEST_F(GpuFunctionalTest, MANUAL_Test2dCanvas) {
+  VerifyGPUProcessOnPage("functional_canvas_demo.html", true);
+}
+
+// Verify that gpu process is spawned when viewing a 3D CSS page.
+IN_PROC_BROWSER_TEST_F(GpuFunctionalTest, MANUAL_Test3dCss) {
+  VerifyGPUProcessOnPage("functional_3d_css.html", true);
+}
+
+// TestGpuWithVideo is failing on all platforms
+// http://crbug.com/237208
+#define MANUAL_TestGpuWithVideo DISABLED_MANUAL_TestGpuWithVideo
+
+// Verify that gpu process is started when viewing video.
+IN_PROC_BROWSER_TEST_F(GpuFunctionalTest, MANUAL_TestGpuWithVideo) {
+  VerifyGPUProcessOnPage("functional_color2.ogv", false);
+}
+
+} // namespace content
diff --git a/content/browser/gpu/gpu_internals_ui.cc b/content/browser/gpu/gpu_internals_ui.cc
index 62b85e3..eb7646c 100644
--- a/content/browser/gpu/gpu_internals_ui.cc
+++ b/content/browser/gpu/gpu_internals_ui.cc
@@ -25,6 +25,7 @@
 #include "content/public/browser/web_ui_message_handler.h"
 #include "content/public/common/content_client.h"
 #include "content/public/common/content_switches.h"
+#include "content/public/common/gpu_feature_type.h"
 #include "content/public/common/gpu_info.h"
 #include "content/public/common/url_constants.h"
 #include "grit/content_resources.h"
@@ -42,7 +43,7 @@
 };
 
 WebUIDataSource* CreateGpuHTMLSource() {
-  WebUIDataSource* source = WebUIDataSource::Create(chrome::kChromeUIGpuHost);
+  WebUIDataSource* source = WebUIDataSource::Create(kChromeUIGpuHost);
 
   source->SetJsonPath("strings.js");
   source->AddResourcePath("gpu_internals.js", IDR_GPU_INTERNALS_JS);
@@ -191,16 +192,17 @@
 
 base::Value* GetFeatureStatus() {
   const CommandLine& command_line = *CommandLine::ForCurrentProcess();
+  GpuDataManagerImpl* manager = GpuDataManagerImpl::GetInstance();
+  std::string gpu_access_blocked_reason;
   bool gpu_access_blocked =
-      !GpuDataManagerImpl::GetInstance()->GpuAccessAllowed();
+      !manager->GpuAccessAllowed(&gpu_access_blocked_reason);
 
-  uint32 flags = GpuDataManagerImpl::GetInstance()->GetBlacklistedFeatures();
   base::DictionaryValue* status = new base::DictionaryValue();
 
   const GpuFeatureInfo kGpuFeatureInfo[] = {
       {
           "2d_canvas",
-          flags & GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS,
+          manager->IsFeatureBlacklisted(GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS),
           command_line.HasSwitch(switches::kDisableAccelerated2dCanvas) ||
           !SupportsAccelerated2dCanvas(),
           "Accelerated 2D canvas is unavailable: either disabled at the command"
@@ -209,7 +211,8 @@
       },
       {
           "compositing",
-          flags & GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING,
+          manager->IsFeatureBlacklisted(
+              GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING),
           command_line.HasSwitch(switches::kDisableAcceleratedCompositing),
           "Accelerated compositing has been disabled, either via about:flags or"
           " command line. This adversely affects performance of all hardware"
@@ -218,16 +221,18 @@
       },
       {
           "3d_css",
-          flags & (GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING |
-                   GPU_FEATURE_TYPE_3D_CSS),
+          manager->IsFeatureBlacklisted(
+              GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING) ||
+          manager->IsFeatureBlacklisted(GPU_FEATURE_TYPE_3D_CSS),
           command_line.HasSwitch(switches::kDisableAcceleratedLayers),
           "Accelerated layers have been disabled at the command line.",
           false
       },
       {
           "css_animation",
-          flags & (GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING |
-                   GPU_FEATURE_TYPE_3D_CSS),
+          manager->IsFeatureBlacklisted(
+              GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING) ||
+          manager->IsFeatureBlacklisted(GPU_FEATURE_TYPE_3D_CSS),
           command_line.HasSwitch(cc::switches::kDisableThreadedAnimation) ||
           command_line.HasSwitch(switches::kDisableAcceleratedCompositing) ||
           command_line.HasSwitch(switches::kDisableAcceleratedLayers),
@@ -236,7 +241,7 @@
       },
       {
           "webgl",
-          flags & GPU_FEATURE_TYPE_WEBGL,
+          manager->IsFeatureBlacklisted(GPU_FEATURE_TYPE_WEBGL),
 #if defined(OS_ANDROID)
           !command_line.HasSwitch(switches::kEnableExperimentalWebGL),
 #else
@@ -247,7 +252,7 @@
       },
       {
           "multisampling",
-          flags & GPU_FEATURE_TYPE_MULTISAMPLING,
+          manager->IsFeatureBlacklisted(GPU_FEATURE_TYPE_MULTISAMPLING),
           command_line.HasSwitch(switches::kDisableGLMultisampling),
           "Multisampling has been disabled, either via about:flags or command"
           " line.",
@@ -255,7 +260,7 @@
       },
       {
           "flash_3d",
-          flags & GPU_FEATURE_TYPE_FLASH3D,
+          manager->IsFeatureBlacklisted(GPU_FEATURE_TYPE_FLASH3D),
           command_line.HasSwitch(switches::kDisableFlash3d),
           "Using 3d in flash has been disabled, either via about:flags or"
           " command line.",
@@ -263,7 +268,7 @@
       },
       {
           "flash_stage3d",
-          flags & GPU_FEATURE_TYPE_FLASH_STAGE3D,
+          manager->IsFeatureBlacklisted(GPU_FEATURE_TYPE_FLASH_STAGE3D),
           command_line.HasSwitch(switches::kDisableFlashStage3d),
           "Using Stage3d in Flash has been disabled, either via about:flags or"
           " command line.",
@@ -271,8 +276,9 @@
       },
       {
           "flash_stage3d_baseline",
-          flags & (content::GPU_FEATURE_TYPE_FLASH_STAGE3D_BASELINE |
-                   content::GPU_FEATURE_TYPE_FLASH_STAGE3D),
+          manager->IsFeatureBlacklisted(
+              GPU_FEATURE_TYPE_FLASH_STAGE3D_BASELINE) ||
+          manager->IsFeatureBlacklisted(GPU_FEATURE_TYPE_FLASH_STAGE3D),
           command_line.HasSwitch(switches::kDisableFlashStage3d),
           "Using Stage3d Baseline profile in Flash has been disabled, either"
           " via about:flags or command line.",
@@ -280,7 +286,7 @@
       },
       {
           "texture_sharing",
-          flags & GPU_FEATURE_TYPE_TEXTURE_SHARING,
+          manager->IsFeatureBlacklisted(GPU_FEATURE_TYPE_TEXTURE_SHARING),
           command_line.HasSwitch(switches::kDisableImageTransportSurface),
           "Sharing textures between processes has been disabled, either via"
           " about:flags or command line.",
@@ -288,7 +294,8 @@
       },
       {
           "video_decode",
-          flags & GPU_FEATURE_TYPE_ACCELERATED_VIDEO_DECODE,
+          manager->IsFeatureBlacklisted(
+              GPU_FEATURE_TYPE_ACCELERATED_VIDEO_DECODE),
           command_line.HasSwitch(switches::kDisableAcceleratedVideoDecode),
           "Accelerated video decode has been disabled, either via about:flags"
           " or command line.",
@@ -296,7 +303,7 @@
       },
       {
           "video",
-          flags & GPU_FEATURE_TYPE_ACCELERATED_VIDEO,
+          manager->IsFeatureBlacklisted(GPU_FEATURE_TYPE_ACCELERATED_VIDEO),
           command_line.HasSwitch(switches::kDisableAcceleratedVideo) ||
           command_line.HasSwitch(switches::kDisableAcceleratedCompositing),
           "Accelerated video presentation has been disabled, either via"
@@ -305,7 +312,7 @@
       },
       {
           "panel_fitting",
-          flags & GPU_FEATURE_TYPE_PANEL_FITTING,
+          manager->IsFeatureBlacklisted(GPU_FEATURE_TYPE_PANEL_FITTING),
 #if defined(OS_CHROMEOS)
           command_line.HasSwitch(switches::kDisablePanelFitting),
 #else
@@ -317,10 +324,12 @@
       },
       {
           "force_compositing_mode",
-          (flags & GPU_FEATURE_TYPE_FORCE_COMPOSITING_MODE) &&
+          manager->IsFeatureBlacklisted(
+              GPU_FEATURE_TYPE_FORCE_COMPOSITING_MODE) &&
           !IsForceCompositingModeEnabled(),
           !IsForceCompositingModeEnabled() &&
-          !(flags & GPU_FEATURE_TYPE_FORCE_COMPOSITING_MODE),
+          !manager->IsFeatureBlacklisted(
+              GPU_FEATURE_TYPE_FORCE_COMPOSITING_MODE),
           "Force compositing mode is off, either disabled at the command"
           " line or not supported by the current system.",
           false
@@ -361,8 +370,7 @@
           else
             status += "_off";
         }
-      } else if (GpuDataManagerImpl::GetInstance()->
-            ShouldUseSoftwareRendering()) {
+      } else if (GpuDataManagerImpl::GetInstance()->ShouldUseSwiftShader()) {
         status = "unavailable_software";
       } else if (kGpuFeatureInfo[i].blocked ||
                  gpu_access_blocked) {
@@ -375,7 +383,8 @@
         status = "enabled";
         if (kGpuFeatureInfo[i].name == "webgl" &&
             (command_line.HasSwitch(switches::kDisableAcceleratedCompositing) ||
-             (flags & GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING)))
+             manager->IsFeatureBlacklisted(
+                 GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING)))
           status += "_readback";
         bool has_thread = IsThreadedCompositingEnabled();
         if (kGpuFeatureInfo[i].name == "compositing") {
@@ -431,10 +440,10 @@
     if (gpu_access_blocked) {
       base::DictionaryValue* problem = new base::DictionaryValue();
       problem->SetString("description",
-          "GPU process was unable to boot. Access to GPU disallowed.");
+          "GPU process was unable to boot: " + gpu_access_blocked_reason);
       problem->Set("crBugs", new base::ListValue());
       problem->Set("webkitBugs", new base::ListValue());
-      problem_list->Append(problem);
+      problem_list->Insert(0, problem);
     }
 
     for (size_t i = 0; i < kNumFeatures; ++i) {
@@ -471,6 +480,9 @@
   // GpuDataManagerObserver implementation.
   virtual void OnGpuInfoUpdate() OVERRIDE;
 
+  // Gpu switch handler.
+  void OnGpuSwitch();
+
   // Messages
   void OnBrowserBridgeInitialized(const base::ListValue* list);
   void OnCallAsync(const base::ListValue* list);
@@ -484,6 +496,8 @@
   // DCHECK).
   bool observing_;
 
+  GpuDataManagerImpl::GpuSwitchCallback gpu_switch_callback_;
+
   DISALLOW_COPY_AND_ASSIGN(GpuMessageHandler);
 };
 
@@ -494,11 +508,15 @@
 ////////////////////////////////////////////////////////////////////////////////
 
 GpuMessageHandler::GpuMessageHandler()
-    : observing_(false) {
+    : observing_(false),
+      gpu_switch_callback_(base::Bind(&GpuMessageHandler::OnGpuSwitch,
+                                      base::Unretained(this))) {
 }
 
 GpuMessageHandler::~GpuMessageHandler() {
   GpuDataManagerImpl::GetInstance()->RemoveObserver(this);
+  GpuDataManagerImpl::GetInstance()->RemoveGpuSwitchCallback(
+      gpu_switch_callback_);
 }
 
 /* BrowserBridge.callAsync prepends a requestID to these messages. */
@@ -565,8 +583,11 @@
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
   // Watch for changes in GPUInfo
-  if (!observing_)
+  if (!observing_) {
     GpuDataManagerImpl::GetInstance()->AddObserver(this);
+    GpuDataManagerImpl::GetInstance()->AddGpuSwitchCallback(
+        gpu_switch_callback_);
+  }
   observing_ = true;
 
   // Tell GpuDataManager it should have full GpuInfo. If the
@@ -618,6 +639,10 @@
       *(gpu_info_val.get()));
 }
 
+void GpuMessageHandler::OnGpuSwitch() {
+  GpuDataManagerImpl::GetInstance()->RequestCompleteGpuInfoIfNeeded();
+}
+
 }  // namespace
 
 
diff --git a/content/browser/gpu/gpu_memory_test.cc b/content/browser/gpu/gpu_memory_test.cc
index 36584c3..832b947 100644
--- a/content/browser/gpu/gpu_memory_test.cc
+++ b/content/browser/gpu/gpu_memory_test.cc
@@ -116,12 +116,8 @@
     js_call << mb_to_use;
     js_call << ");";
     std::string message;
-    ASSERT_TRUE(
-        ExecuteScriptInFrameAndExtractString(
-        tab_to_load->web_contents(),
-        "",
-        js_call.str(),
-        &message));
+    ASSERT_TRUE(ExecuteScriptInFrameAndExtractString(
+        tab_to_load->web_contents(), std::string(), js_call.str(), &message));
     EXPECT_EQ("DONE_USE_GPU_MEMORY", message);
   }
 
@@ -196,12 +192,8 @@
             "  domAutomationController.send(\"DONE_RAF\");"
             "})");
         std::string message;
-        ASSERT_TRUE(
-            ExecuteScriptInFrameAndExtractString(
-            (*it)->web_contents(),
-            "",
-            js_call,
-            &message));
+        ASSERT_TRUE(ExecuteScriptInFrameAndExtractString(
+            (*it)->web_contents(), std::string(), js_call, &message));
         EXPECT_EQ("DONE_RAF", message);
       }
       // TODO(ccameron): send an IPC from Browser -> Renderer (delay it until
diff --git a/content/browser/gpu/gpu_pixel_browsertest.cc b/content/browser/gpu/gpu_pixel_browsertest.cc
index e146a08..fb93076 100644
--- a/content/browser/gpu/gpu_pixel_browsertest.cc
+++ b/content/browser/gpu/gpu_pixel_browsertest.cc
@@ -54,8 +54,8 @@
 // should have been encoded using |gfx::PNGCodec::Encode|.
 bool ReadPNGFile(const base::FilePath& file_path, SkBitmap* bitmap) {
   DCHECK(bitmap);
-  base::FilePath abs_path(file_path);
-  if (!file_util::AbsolutePath(&abs_path))
+  base::FilePath abs_path(base::MakeAbsoluteFilePath(file_path));
+  if (abs_path.empty())
     return false;
 
   std::string png_data;
@@ -147,7 +147,7 @@
         "DISABLED_", "FLAKY_", "FAILS_", "MANUAL_"};
     for (size_t i = 0; i < arraysize(test_status_prefixes); ++i) {
       ReplaceFirstSubstringAfterOffset(
-          &test_name_, 0, test_status_prefixes[i], "");
+          &test_name_, 0, test_status_prefixes[i], std::string());
     }
 
     ui::DisableTestCompositor();
diff --git a/content/browser/gpu/gpu_process_host.cc b/content/browser/gpu/gpu_process_host.cc
index 699ce42..560fed2 100644
--- a/content/browser/gpu/gpu_process_host.cc
+++ b/content/browser/gpu/gpu_process_host.cc
@@ -19,7 +19,6 @@
 #include "content/browser/browser_child_process_host_impl.h"
 #include "content/browser/gpu/gpu_data_manager_impl.h"
 #include "content/browser/gpu/gpu_process_host_ui_shim.h"
-#include "content/browser/gpu/gpu_surface_tracker.h"
 #include "content/browser/gpu/shader_disk_cache.h"
 #include "content/browser/renderer_host/render_widget_helper.h"
 #include "content/browser/renderer_host/render_widget_host_impl.h"
@@ -42,9 +41,6 @@
 #include "ipc/ipc_switches.h"
 #include "ui/gl/gl_switches.h"
 
-#if defined(TOOLKIT_GTK)
-#include "ui/gfx/gtk_native_view_id_manager.h"
-#endif
 
 #if defined(OS_WIN)
 #include "base/win/windows_version.h"
@@ -74,14 +70,6 @@
 // only be accessed from the IO thread.
 GpuProcessHost* g_gpu_process_hosts[GpuProcessHost::GPU_PROCESS_KIND_COUNT];
 
-#if defined(TOOLKIT_GTK)
-
-void ReleasePermanentXIDDispatcher(gfx::PluginWindowHandle surface) {
-  GtkNativeViewManager* manager = GtkNativeViewManager::GetInstance();
-  manager->ReleasePermanentXID(surface);
-}
-
-#endif
 
 void SendGpuProcessMessage(GpuProcessHost::GpuProcessKind kind,
                            CauseForGpuLaunch cause,
@@ -254,6 +242,9 @@
       return;
     }
 
+    // Block this DLL even if it is not loaded by the browser process.
+    policy->AddDllToUnload(L"cmsetac.dll");
+
 #ifdef USE_AURA
     // GPU also needs to add sections to the browser for aura
     // TODO(jschuh): refactor the GPU channel to remove this. crbug.com/128786
@@ -287,33 +278,6 @@
 
 }  // anonymous namespace
 
-#if defined(TOOLKIT_GTK)
-// Used to put a lock on surfaces so that the window to which the GPU
-// process is drawing to doesn't disappear while it is drawing when
-// a WebContents is closed.
-class GpuProcessHost::SurfaceRef {
- public:
-  explicit SurfaceRef(gfx::PluginWindowHandle surface);
-  ~SurfaceRef();
- private:
-  gfx::PluginWindowHandle surface_;
-};
-
-GpuProcessHost::SurfaceRef::SurfaceRef(gfx::PluginWindowHandle surface)
-    : surface_(surface) {
-  GtkNativeViewManager* manager = GtkNativeViewManager::GetInstance();
-  if (!manager->AddRefPermanentXID(surface_)) {
-    LOG(ERROR) << "Surface " << surface << " cannot be referenced.";
-  }
-}
-
-GpuProcessHost::SurfaceRef::~SurfaceRef() {
-  BrowserThread::PostTask(BrowserThread::UI,
-                          FROM_HERE,
-                          base::Bind(&ReleasePermanentXIDDispatcher, surface_));
-}
-#endif  // defined(TOOLKIT_GTK)
-
 // This class creates a GPU thread (instead of a GPU process), when running
 // with --in-process-gpu or --single-process.
 class GpuMainThread : public base::Thread {
@@ -361,13 +325,13 @@
   if (!host)
     return false;
 
-  // The Gpu process is invalid if it's not using software, the card is
+  // The Gpu process is invalid if it's not using SwiftShader, the card is
   // blacklisted, and we can kill it and start over.
   if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess) ||
       CommandLine::ForCurrentProcess()->HasSwitch(switches::kInProcessGPU) ||
       (host->valid_ &&
-       (host->software_rendering() ||
-        !GpuDataManagerImpl::GetInstance()->ShouldUseSoftwareRendering()))) {
+       (host->swiftshader_rendering_ ||
+        !GpuDataManagerImpl::GetInstance()->ShouldUseSwiftShader()))) {
     return true;
   }
 
@@ -383,7 +347,7 @@
   // Don't grant further access to GPU if it is not allowed.
   GpuDataManagerImpl* gpu_data_manager = GpuDataManagerImpl::GetInstance();
   DCHECK(gpu_data_manager);
-  if (!gpu_data_manager->GpuAccessAllowed())
+  if (!gpu_data_manager->GpuAccessAllowed(NULL))
     return NULL;
 
   if (g_gpu_process_hosts[kind] && ValidateHost(g_gpu_process_hosts[kind]))
@@ -459,7 +423,7 @@
     : host_id_(host_id),
       valid_(true),
       in_process_(false),
-      software_rendering_(false),
+      swiftshader_rendering_(false),
       kind_(kind),
       process_launched_(false),
       initialized_(false),
@@ -503,20 +467,19 @@
   static int gpu_recent_crash_count = 0;
   static base::Time last_gpu_crash_time;
   static bool crashed_before = false;
-  static int gpu_software_crash_count = 0;
+  static int swiftshader_crash_count = 0;
 
   // Ending only acts as a failure if the GPU process was actually started and
   // was intended for actual rendering (and not just checking caps or other
   // options).
   if (process_launched_ && kind_ == GPU_PROCESS_KIND_SANDBOXED) {
-    if (software_rendering_) {
-      UMA_HISTOGRAM_ENUMERATION("GPU.SoftwareRendererLifetimeEvents",
-                                DIED_FIRST_TIME + gpu_software_crash_count,
+    if (swiftshader_rendering_) {
+      UMA_HISTOGRAM_ENUMERATION("GPU.SwiftShaderLifetimeEvents",
+                                DIED_FIRST_TIME + swiftshader_crash_count,
                                 GPU_PROCESS_LIFETIME_EVENT_MAX);
 
-      if (++gpu_software_crash_count >= kGpuMaxCrashCount) {
-        // The software renderer is too unstable to use. Disable it for current
-        // session.
+      if (++swiftshader_crash_count >= kGpuMaxCrashCount) {
+        // SwiftShader is too unstable to use. Disable it for current session.
         gpu_enabled_ = false;
       }
     } else {
@@ -632,7 +595,7 @@
 bool GpuProcessHost::Init() {
   init_start_time_ = base::TimeTicks::Now();
 
-  TRACE_EVENT_INSTANT0("gpu", "LaunchGpuProcess");
+  TRACE_EVENT_INSTANT0("gpu", "LaunchGpuProcess", TRACE_EVENT_SCOPE_THREAD);
 
   std::string channel_id = process_->GetHost()->CreateChannel();
   if (channel_id.empty())
@@ -742,7 +705,7 @@
   TRACE_EVENT0("gpu", "GpuProcessHost::EstablishGpuChannel");
 
   // If GPU features are already blacklisted, no need to establish the channel.
-  if (!GpuDataManagerImpl::GetInstance()->GpuAccessAllowed()) {
+  if (!GpuDataManagerImpl::GetInstance()->GpuAccessAllowed(NULL)) {
     callback.Run(IPC::ChannelHandle(), GPUInfo());
     return;
   }
@@ -769,26 +732,12 @@
 
   DCHECK(CalledOnValidThread());
 
-#if defined(TOOLKIT_GTK)
-  // There should only be one such command buffer (for the compositor).  In
-  // practice, if the GPU process lost a context, GraphicsContext3D with
-  // associated command buffer and view surface will not be gone until new
-  // one is in place and all layers are reattached.
-  linked_ptr<SurfaceRef> surface_ref;
-  SurfaceRefMap::iterator it = surface_refs_.find(surface_id);
-  if (it != surface_refs_.end())
-    surface_ref = (*it).second;
-  else
-    surface_ref.reset(new SurfaceRef(compositing_surface.handle));
-#endif  // defined(TOOLKIT_GTK)
-
   if (!compositing_surface.is_null() &&
       Send(new GpuMsg_CreateViewCommandBuffer(
           compositing_surface, surface_id, client_id, init_params))) {
     create_command_buffer_requests_.push(callback);
-#if defined(TOOLKIT_GTK)
-    surface_refs_.insert(std::make_pair(surface_id, surface_ref));
-#endif
+    surface_refs_.insert(std::make_pair(surface_id,
+        GpuSurfaceTracker::GetInstance()->GetSurfaceRefForSurface(surface_id)));
   } else {
     callback.Run(MSG_ROUTING_NONE);
   }
@@ -828,13 +777,21 @@
     const IPC::ChannelHandle& channel_handle) {
   TRACE_EVENT0("gpu", "GpuProcessHost::OnChannelEstablished");
 
+  if (channel_requests_.empty()) {
+    // This happens when GPU process is compromised.
+    RouteOnUIThread(GpuHostMsg_OnLogMessage(
+        logging::LOG_WARNING,
+        "WARNING",
+        "Received a ChannelEstablished message but no requests in queue."));
+    return;
+  }
   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 (!channel_handle.name.empty() &&
-      !GpuDataManagerImpl::GetInstance()->GpuAccessAllowed()) {
+      !GpuDataManagerImpl::GetInstance()->GpuAccessAllowed(NULL)) {
     Send(new GpuMsg_CloseChannel(channel_handle));
     callback.Run(IPC::ChannelHandle(), GPUInfo());
     RouteOnUIThread(GpuHostMsg_OnLogMessage(
@@ -862,12 +819,10 @@
 
 void GpuProcessHost::OnDestroyCommandBuffer(int32 surface_id) {
   TRACE_EVENT0("gpu", "GpuProcessHost::OnDestroyCommandBuffer");
-
-#if defined(TOOLKIT_GTK)
   SurfaceRefMap::iterator it = surface_refs_.find(surface_id);
-  if (it != surface_refs_.end())
+  if (it != surface_refs_.end()) {
     surface_refs_.erase(it);
-#endif  // defined(TOOLKIT_GTK)
+  }
 }
 
 void GpuProcessHost::OnImageCreated(const gfx::Size size) {
@@ -1017,13 +972,6 @@
     return;
   }
 
-  scoped_refptr<media::VideoFrame> target_frame;
-  RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback copy_callback;
-  FrameSubscriberMap::iterator it = frame_subscribers_.find(params.surface_id);
-  bool should_copy = false;
-  if (it != frame_subscribers_.end() && it->second)
-    should_copy = it->second->ShouldCaptureFrame(&target_frame, &copy_callback);
-
   scoped_completion_runner.Release();
   presenter->AsyncPresentAndAcknowledge(
       params.size,
@@ -1034,14 +982,19 @@
                  params.surface_id,
                  params.surface_handle));
 
-  // It is a potential improvement to do the copy in present, but we use a
-  // simpler approach now.
-  if (should_copy) {
-    // The timestamp here is not the acutal presentation time but it is close
-    // enough.
-    presenter->AsyncCopyToVideoFrame(
-        gfx::Rect(params.size), target_frame,
-        base::Bind(copy_callback, base::Time::Now()));
+  FrameSubscriberMap::iterator it = frame_subscribers_.find(params.surface_id);
+  if (it != frame_subscribers_.end() && it->second) {
+    const base::Time present_time = base::Time::Now();
+    scoped_refptr<media::VideoFrame> target_frame;
+    RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback copy_callback;
+    if (it->second->ShouldCaptureFrame(present_time,
+                                       &target_frame, &copy_callback)) {
+      // It is a potential improvement to do the copy in present, but we use a
+      // simpler approach for now.
+      presenter->AsyncCopyToVideoFrame(
+          gfx::Rect(params.size), target_frame,
+          base::Bind(copy_callback, present_time));
+    }
   }
 }
 
@@ -1107,10 +1060,6 @@
       process_->GetTerminationStatus(NULL));
 }
 
-bool GpuProcessHost::software_rendering() {
-  return software_rendering_;
-}
-
 GpuProcessHost::GpuProcessKind GpuProcessHost::kind() {
   return kind_;
 }
@@ -1136,7 +1085,7 @@
 
 bool GpuProcessHost::LaunchGpuProcess(const std::string& channel_id) {
   if (!(gpu_enabled_ &&
-      GpuDataManagerImpl::GetInstance()->ShouldUseSoftwareRendering()) &&
+      GpuDataManagerImpl::GetInstance()->ShouldUseSwiftShader()) &&
       !hardware_gpu_enabled_) {
     SendOutstandingReplies();
     return false;
@@ -1208,11 +1157,12 @@
   GpuDataManagerImpl::GetInstance()->AppendGpuCommandLine(cmd_line);
 
   if (cmd_line->HasSwitch(switches::kUseGL)) {
-    software_rendering_ =
+    swiftshader_rendering_ =
         (cmd_line->GetSwitchValueASCII(switches::kUseGL) == "swiftshader");
   }
 
-  UMA_HISTOGRAM_BOOLEAN("GPU.GPUProcessSoftwareRendering", software_rendering_);
+  UMA_HISTOGRAM_BOOLEAN("GPU.GPU.GPUProcessSoftwareRendering",
+                        swiftshader_rendering_);
 
   // If specified, prepend a launcher program to the command line.
   if (!gpu_launcher.empty())
@@ -1241,6 +1191,13 @@
     channel_requests_.pop();
     callback.Run(IPC::ChannelHandle(), GPUInfo());
   }
+
+  while (!create_command_buffer_requests_.empty()) {
+    CreateCommandBufferCallback callback =
+        create_command_buffer_requests_.front();
+    create_command_buffer_requests_.pop();
+    callback.Run(MSG_ROUTING_NONE);
+  }
 }
 
 void GpuProcessHost::BlockLiveOffscreenContexts() {
diff --git a/content/browser/gpu/gpu_process_host.h b/content/browser/gpu/gpu_process_host.h
index 405918f..6474d56 100644
--- a/content/browser/gpu/gpu_process_host.h
+++ b/content/browser/gpu/gpu_process_host.h
@@ -12,10 +12,10 @@
 
 #include "base/callback.h"
 #include "base/hash_tables.h"
-#include "base/memory/linked_ptr.h"
 #include "base/memory/weak_ptr.h"
 #include "base/threading/non_thread_safe.h"
 #include "base/time.h"
+#include "content/browser/gpu/gpu_surface_tracker.h"
 #include "content/common/content_export.h"
 #include "content/common/gpu/gpu_memory_uma_stats.h"
 #include "content/common/gpu/gpu_process_launch_causes.h"
@@ -68,7 +68,8 @@
   // is not safe to store the pointer once control has returned to the message
   // loop as it can be destroyed. Instead store the associated GPU host ID.
   // This could return NULL if GPU access is not allowed (blacklisted).
-  static GpuProcessHost* Get(GpuProcessKind kind, CauseForGpuLaunch cause);
+  CONTENT_EXPORT static GpuProcessHost* Get(GpuProcessKind kind,
+                                            CauseForGpuLaunch cause);
 
   // Retrieves a list of process handles for all gpu processes.
   static void GetProcessHandles(
@@ -118,9 +119,6 @@
     // Tells the GPU process to delete image.
   void DeleteImage(int client_id, int image_id, int sync_point);
 
-  // Whether this GPU process is set up to use software rendering.
-  bool software_rendering();
-
   // What kind of GPU process, e.g. sandboxed or unsandboxed.
   GpuProcessKind kind();
 
@@ -202,18 +200,6 @@
   // The pending create image requests we need to reply to.
   std::queue<CreateImageCallback> create_image_requests_;
 
-#if defined(TOOLKIT_GTK)
-  // Encapsulates surfaces that we lock when creating view command buffers.
-  // We release this lock once the command buffer (or associated GPU process)
-  // is destroyed. This prevents the browser from destroying the surface
-  // while the GPU process is drawing to it.
-
-  // Multimap is used to simulate reference counting, see comment in
-  // GpuProcessHostUIShim::CreateViewCommandBuffer.
-  class SurfaceRef;
-  typedef std::multimap<int, linked_ptr<SurfaceRef> > SurfaceRefMap;
-  SurfaceRefMap surface_refs_;
-#endif
 
   // Qeueud messages to send when the process launches.
   std::queue<IPC::Message*> queued_messages_;
@@ -225,7 +211,7 @@
   // of a separate GPU process.
   bool in_process_;
 
-  bool software_rendering_;
+  bool swiftshader_rendering_;
   GpuProcessKind kind_;
 
   scoped_ptr<GpuMainThread> in_process_gpu_thread_;
@@ -272,6 +258,13 @@
 
   std::string shader_prefix_key_;
 
+  // Keep an extra reference to the SurfaceRef stored in the GpuSurfaceTracker
+  // in this map so that we don't destroy it whilst the GPU process is
+  // drawing to it.
+  typedef std::multimap<int, scoped_refptr<GpuSurfaceTracker::SurfaceRef> >
+      SurfaceRefMap;
+  SurfaceRefMap surface_refs_;
+
   DISALLOW_COPY_AND_ASSIGN(GpuProcessHost);
 };
 
diff --git a/content/browser/gpu/gpu_process_host_ui_shim.cc b/content/browser/gpu/gpu_process_host_ui_shim.cc
index 4237e49..a243115 100644
--- a/content/browser/gpu/gpu_process_host_ui_shim.cc
+++ b/content/browser/gpu/gpu_process_host_ui_shim.cc
@@ -209,6 +209,7 @@
                         OnVideoMemoryUsageStatsReceived);
     IPC_MESSAGE_HANDLER(GpuHostMsg_UpdateVSyncParameters,
                         OnUpdateVSyncParameters)
+    IPC_MESSAGE_HANDLER(GpuHostMsg_FrameDrawn, OnFrameDrawn)
 
 #if defined(TOOLKIT_GTK) || defined(OS_WIN)
     IPC_MESSAGE_HANDLER(GpuHostMsg_ResizeView, OnResizeView)
@@ -341,6 +342,9 @@
   view->AcceleratedSurfaceBuffersSwapped(params, host_id_);
 }
 
+void GpuProcessHostUIShim::OnFrameDrawn(const cc::LatencyInfo& latency_info) {
+}
+
 void GpuProcessHostUIShim::OnAcceleratedSurfacePostSubBuffer(
     const GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params& params) {
   TRACE_EVENT0("renderer",
diff --git a/content/browser/gpu/gpu_process_host_ui_shim.h b/content/browser/gpu/gpu_process_host_ui_shim.h
index 27f1e9a..243cfd1 100644
--- a/content/browser/gpu/gpu_process_host_ui_shim.h
+++ b/content/browser/gpu/gpu_process_host_ui_shim.h
@@ -28,6 +28,10 @@
 struct GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params;
 struct GpuHostMsg_AcceleratedSurfaceRelease_Params;
 
+namespace cc {
+struct LatencyInfo;
+}
+
 namespace gfx {
 class Size;
 }
@@ -103,6 +107,7 @@
   void OnUpdateVSyncParameters(int surface_id,
                                base::TimeTicks timebase,
                                base::TimeDelta interval);
+  void OnFrameDrawn(const cc::LatencyInfo& latency_info);
 
   // The serial number of the GpuProcessHost / GpuProcessHostUIShim pair.
   int host_id_;
diff --git a/content/browser/gpu/gpu_surface_tracker.cc b/content/browser/gpu/gpu_surface_tracker.cc
index 2c4873a..ce1e956 100644
--- a/content/browser/gpu/gpu_surface_tracker.cc
+++ b/content/browser/gpu/gpu_surface_tracker.cc
@@ -10,8 +10,57 @@
 
 #include "base/logging.h"
 
+#if defined(TOOLKIT_GTK)
+#include "base/bind.h"
+#include "content/public/browser/browser_thread.h"
+#include "ui/gfx/gtk_native_view_id_manager.h"
+#endif  // defined(TOOLKIT_GTK)
+
 namespace content {
 
+namespace {
+#if defined(TOOLKIT_GTK)
+
+void ReleasePermanentXIDDispatcher(
+    const gfx::PluginWindowHandle& surface) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+  GtkNativeViewManager* manager = GtkNativeViewManager::GetInstance();
+  manager->ReleasePermanentXID(surface);
+}
+
+// Implementation of SurfaceRef that allows GTK to ref and unref the
+// surface with the GtkNativeViewManager.
+class SurfaceRefPluginWindow : public GpuSurfaceTracker::SurfaceRef {
+  public:
+   SurfaceRefPluginWindow(const gfx::PluginWindowHandle& surface_ref);
+  private:
+   virtual ~SurfaceRefPluginWindow();
+   gfx::PluginWindowHandle surface_;
+};
+
+SurfaceRefPluginWindow::SurfaceRefPluginWindow(
+    const gfx::PluginWindowHandle& surface)
+    : surface_(surface) {
+  if (surface_ != gfx::kNullPluginWindow) {
+    GtkNativeViewManager* manager = GtkNativeViewManager::GetInstance();
+    if (!manager->AddRefPermanentXID(surface_)) {
+      LOG(ERROR) << "Surface " << surface << " cannot be referenced.";
+    }
+  }
+}
+
+SurfaceRefPluginWindow::~SurfaceRefPluginWindow() {
+  if (surface_ != gfx::kNullPluginWindow) {
+    BrowserThread::PostTask(BrowserThread::UI,
+                            FROM_HERE,
+                            base::Bind(&ReleasePermanentXIDDispatcher,
+                                       surface_));
+  }
+}
+#endif  // defined(TOOLKIT_GTK)
+}  // anonymous
+
 GpuSurfaceTracker::GpuSurfaceTracker()
     : next_surface_id_(1) {
   GpuSurfaceLookup::InitInstance(this);
@@ -28,13 +77,10 @@
 int GpuSurfaceTracker::AddSurfaceForRenderer(int renderer_id,
                                              int render_widget_id) {
   base::AutoLock lock(lock_);
-  SurfaceInfo info = {
-    renderer_id,
-    render_widget_id,
-    gfx::kNullAcceleratedWidget
-  };
   int surface_id = next_surface_id_++;
-  surface_map_[surface_id] = info;
+  surface_map_[surface_id] =
+      SurfaceInfo(renderer_id, render_widget_id, gfx::kNullAcceleratedWidget,
+                  gfx::GLSurfaceHandle(), NULL);
   return surface_id;
 }
 
@@ -55,9 +101,9 @@
 int GpuSurfaceTracker::AddSurfaceForNativeWidget(
     gfx::AcceleratedWidget widget) {
   base::AutoLock lock(lock_);
-  SurfaceInfo info = { 0, 0, widget };
   int surface_id = next_surface_id_++;
-  surface_map_[surface_id] = info;
+  surface_map_[surface_id] =
+      SurfaceInfo(0, 0, widget, gfx::GLSurfaceHandle(), NULL);
   return surface_id;
 }
 
@@ -86,6 +132,9 @@
   DCHECK(surface_map_.find(surface_id) != surface_map_.end());
   SurfaceInfo& info = surface_map_[surface_id];
   info.handle = handle;
+#if defined(TOOLKIT_GTK)
+  info.surface_ref = new SurfaceRefPluginWindow(handle.handle);
+#endif  // defined(TOOLKIT_GTK)
 }
 
 gfx::GLSurfaceHandle GpuSurfaceTracker::GetSurfaceHandle(int surface_id) {
@@ -111,11 +160,14 @@
 }
 
 void GpuSurfaceTracker::SetNativeWidget(
-    int surface_id, gfx::AcceleratedWidget widget) {
+    int surface_id, gfx::AcceleratedWidget widget,
+    SurfaceRef* surface_ref) {
   base::AutoLock lock(lock_);
   SurfaceMap::iterator it = surface_map_.find(surface_id);
   DCHECK(it != surface_map_.end());
-  it->second.native_widget = widget;
+  SurfaceInfo& info = it->second;
+  info.native_widget = widget;
+  info.surface_ref = surface_ref;
 }
 
 std::size_t GpuSurfaceTracker::GetSurfaceCount() {
@@ -123,4 +175,24 @@
   return surface_map_.size();
 }
 
+GpuSurfaceTracker::SurfaceInfo::SurfaceInfo()
+   : renderer_id(0),
+     render_widget_id(0),
+     native_widget(gfx::kNullAcceleratedWidget) { }
+
+GpuSurfaceTracker::SurfaceInfo::SurfaceInfo(
+    int renderer_id,
+    int render_widget_id,
+    const gfx::AcceleratedWidget& native_widget,
+    const gfx::GLSurfaceHandle& handle,
+    const scoped_refptr<SurfaceRef>& surface_ref)
+    : renderer_id(renderer_id),
+      render_widget_id(render_widget_id),
+      native_widget(native_widget),
+      handle(handle),
+      surface_ref(surface_ref) { }
+
+GpuSurfaceTracker::SurfaceInfo::~SurfaceInfo() { }
+
+
 }  // namespace content
diff --git a/content/browser/gpu/gpu_surface_tracker.h b/content/browser/gpu/gpu_surface_tracker.h
index ddf0a66..de9d666 100644
--- a/content/browser/gpu/gpu_surface_tracker.h
+++ b/content/browser/gpu/gpu_surface_tracker.h
@@ -8,6 +8,7 @@
 #include <map>
 
 #include "base/basictypes.h"
+#include "base/memory/ref_counted.h"
 #include "base/memory/singleton.h"
 #include "base/synchronization/lock.h"
 #include "content/common/gpu/gpu_surface_lookup.h"
@@ -27,6 +28,27 @@
 // it is unamibiguously identified.
 class GpuSurfaceTracker : public GpuSurfaceLookup {
  public:
+  // Base class for reference counting surfaces. We store a
+  // reference to an instance of this class in the surface_map_
+  // and GpuProcessHost (if the GPU process is drawing to
+  // the surface with a Command Buffer). The reference count ensures that
+  // we don't destroy the object until it's released from both places.
+  //
+  // This is especially important on Android and GTK where the surface must
+  // not be destroyed when the WebContents is closed if the GPU is still
+  // drawing to it. Those platforms extend this class with the functionality
+  // they need to implement on tear down (see SurfaceRefPluginWindow for GTK and
+  // SurfaceRefAndroid for Android).
+  class SurfaceRef : public base::RefCountedThreadSafe<SurfaceRef> {
+   protected:
+    SurfaceRef() { }
+    virtual ~SurfaceRef() { }
+
+   private:
+    friend class base::RefCountedThreadSafe<SurfaceRef>;
+    DISALLOW_COPY_AND_ASSIGN(SurfaceRef);
+  };
+
   // GpuSurfaceLookup implementation:
   // Returns the native widget associated with a given surface_id.
   virtual gfx::AcceleratedWidget AcquireNativeWidget(int surface_id) OVERRIDE;
@@ -62,7 +84,10 @@
   void SetSurfaceHandle(int surface_id, const gfx::GLSurfaceHandle& handle);
 
   // Sets the native widget associated with the surface_id.
-  void SetNativeWidget(int surface_id, gfx::AcceleratedWidget widget);
+  void SetNativeWidget(
+      int surface_id,
+      gfx::AcceleratedWidget widget,
+      SurfaceRef* surface_ref);
 
   // Gets the native handle for the given surface.
   // Note: This is an O(log N) lookup.
@@ -75,12 +100,24 @@
   // named that way for the implementation of Singleton.
   static GpuSurfaceTracker* GetInstance();
 
+  scoped_refptr<SurfaceRef> GetSurfaceRefForSurface(int surface_id) {
+    return surface_map_[surface_id].surface_ref;
+  }
+
  private:
   struct SurfaceInfo {
+    SurfaceInfo();
+    SurfaceInfo(int renderer_id,
+                int render_widget_id,
+                const gfx::AcceleratedWidget& native_widget,
+                const gfx::GLSurfaceHandle& handle,
+                const scoped_refptr<SurfaceRef>& surface_ref);
+    ~SurfaceInfo();
     int renderer_id;
     int render_widget_id;
     gfx::AcceleratedWidget native_widget;
     gfx::GLSurfaceHandle handle;
+    scoped_refptr<SurfaceRef> surface_ref;
   };
   typedef std::map<int, SurfaceInfo> SurfaceMap;
 
diff --git a/content/browser/gpu/gpu_switching_list.cc b/content/browser/gpu/gpu_switching_list.cc
index da795c1..0097015 100644
--- a/content/browser/gpu/gpu_switching_list.cc
+++ b/content/browser/gpu/gpu_switching_list.cc
@@ -18,10 +18,10 @@
 // static
 GpuSwitchingList* GpuSwitchingList::Create() {
   GpuSwitchingList* list = new GpuSwitchingList();
-  list->AddFeature("force_integrated",
-                   GPU_SWITCHING_OPTION_FORCE_INTEGRATED);
-  list->AddFeature("force_discrete",
-                   GPU_SWITCHING_OPTION_FORCE_DISCRETE);
+  list->AddSupportedFeature("force_integrated",
+                            GPU_SWITCHING_OPTION_FORCE_INTEGRATED);
+  list->AddSupportedFeature("force_discrete",
+                            GPU_SWITCHING_OPTION_FORCE_DISCRETE);
   return list;
 }
 
diff --git a/content/browser/gpu/gpu_switching_list_unittest.cc b/content/browser/gpu/gpu_switching_list_unittest.cc
index da1171f..b6ceb4b 100644
--- a/content/browser/gpu/gpu_switching_list_unittest.cc
+++ b/content/browser/gpu/gpu_switching_list_unittest.cc
@@ -65,7 +65,7 @@
   int64 data_file_size64 = 0;
   ASSERT_TRUE(file_util::GetFileSize(data_file, &data_file_size64));
   int data_file_size = static_cast<int>(data_file_size64);
-  scoped_array<char> data(new char[data_file_size]);
+  scoped_ptr<char[]> data(new char[data_file_size]);
   ASSERT_EQ(data_file_size,
             file_util::ReadFile(data_file, data.get(), data_file_size));
   std::string json_string(data.get(), data_file_size);
@@ -104,10 +104,10 @@
   );
   scoped_ptr<GpuSwitchingList> switching_list(GpuSwitchingList::Create());
   EXPECT_TRUE(switching_list->LoadList(json, GpuControlList::kAllOs));
-  int switching = switching_list->MakeDecision(
+  std::set<int> switching = switching_list->MakeDecision(
       GpuControlList::kOsMacosx, kOsVersion, gpu_info());
-  EXPECT_EQ(GPU_SWITCHING_OPTION_FORCE_DISCRETE,
-            static_cast<GpuSwitchingOption>(switching));
+  EXPECT_EQ(1u, switching.size());
+  EXPECT_EQ(1u, switching.count(GPU_SWITCHING_OPTION_FORCE_DISCRETE));
   std::vector<uint32> entries;
   switching_list->GetDecisionEntries(&entries, false);
   ASSERT_EQ(1u, entries.size());
@@ -117,8 +117,8 @@
   EXPECT_TRUE(switching_list->LoadList(json, GpuControlList::kAllOs));
   switching = switching_list->MakeDecision(
       GpuControlList::kOsWin, kOsVersion, gpu_info());
-  EXPECT_EQ(GPU_SWITCHING_OPTION_FORCE_INTEGRATED,
-            static_cast<GpuSwitchingOption>(switching));
+  EXPECT_EQ(1u, switching.size());
+  EXPECT_EQ(1u, switching.count(GPU_SWITCHING_OPTION_FORCE_INTEGRATED));
   switching_list->GetDecisionEntries(&entries, false);
   ASSERT_EQ(1u, entries.size());
   EXPECT_EQ(2u, entries[0]);
diff --git a/content/browser/gpu/gpu_util.cc b/content/browser/gpu/gpu_util.cc
index 7d7d932..5aa5433 100644
--- a/content/browser/gpu/gpu_util.cc
+++ b/content/browser/gpu/gpu_util.cc
@@ -13,27 +13,12 @@
 #include "base/version.h"
 #include "content/browser/gpu/gpu_blacklist.h"
 #include "content/public/common/content_switches.h"
+#include "content/public/common/gpu_feature_type.h"
 #include "ui/gl/gl_switches.h"
 
 namespace content {
 namespace {
 
-const char kGpuFeatureNameAccelerated2dCanvas[] = "accelerated_2d_canvas";
-const char kGpuFeatureNameAcceleratedCompositing[] = "accelerated_compositing";
-const char kGpuFeatureNameWebgl[] = "webgl";
-const char kGpuFeatureNameMultisampling[] = "multisampling";
-const char kGpuFeatureNameFlash3d[] = "flash_3d";
-const char kGpuFeatureNameFlashStage3d[] = "flash_stage3d";
-const char kGpuFeatureNameFlashStage3dBaseline[] = "flash_stage3d_baseline";
-const char kGpuFeatureNameTextureSharing[] = "texture_sharing";
-const char kGpuFeatureNameAcceleratedVideoDecode[] = "accelerated_video_decode";
-const char kGpuFeatureName3dCss[] = "3d_css";
-const char kGpuFeatureNameAcceleratedVideo[] = "accelerated_video";
-const char kGpuFeatureNamePanelFitting[] = "panel_fitting";
-const char kGpuFeatureNameForceCompositingMode[] = "force_compositing_mode";
-const char kGpuFeatureNameAll[] = "all";
-const char kGpuFeatureNameUnknown[] = "unknown";
-
 enum GpuFeatureStatus {
     kGpuFeatureEnabled = 0,
     kGpuFeatureBlacklisted = 1,
@@ -85,76 +70,7 @@
 }
 #endif  // OS_WIN
 
-}  // namespace
-
-GpuFeatureType StringToGpuFeatureType(const std::string& feature_string) {
-  if (feature_string == kGpuFeatureNameAccelerated2dCanvas)
-    return GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS;
-  if (feature_string == kGpuFeatureNameAcceleratedCompositing)
-    return GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING;
-  if (feature_string == kGpuFeatureNameWebgl)
-    return GPU_FEATURE_TYPE_WEBGL;
-  if (feature_string == kGpuFeatureNameMultisampling)
-    return GPU_FEATURE_TYPE_MULTISAMPLING;
-  if (feature_string == kGpuFeatureNameFlash3d)
-    return GPU_FEATURE_TYPE_FLASH3D;
-  if (feature_string == kGpuFeatureNameFlashStage3d)
-    return GPU_FEATURE_TYPE_FLASH_STAGE3D;
-  if (feature_string == kGpuFeatureNameFlashStage3dBaseline)
-    return GPU_FEATURE_TYPE_FLASH_STAGE3D_BASELINE;
-  if (feature_string == kGpuFeatureNameTextureSharing)
-    return GPU_FEATURE_TYPE_TEXTURE_SHARING;
-  if (feature_string == kGpuFeatureNameAcceleratedVideoDecode)
-    return GPU_FEATURE_TYPE_ACCELERATED_VIDEO_DECODE;
-  if (feature_string == kGpuFeatureName3dCss)
-    return GPU_FEATURE_TYPE_3D_CSS;
-  if (feature_string == kGpuFeatureNameAcceleratedVideo)
-    return GPU_FEATURE_TYPE_ACCELERATED_VIDEO;
-  if (feature_string == kGpuFeatureNamePanelFitting)
-    return GPU_FEATURE_TYPE_PANEL_FITTING;
-  if (feature_string == kGpuFeatureNameForceCompositingMode)
-    return GPU_FEATURE_TYPE_FORCE_COMPOSITING_MODE;
-  if (feature_string == kGpuFeatureNameAll)
-    return GPU_FEATURE_TYPE_ALL;
-  return GPU_FEATURE_TYPE_UNKNOWN;
-}
-
-std::string GpuFeatureTypeToString(GpuFeatureType type) {
-  std::vector<std::string> matches;
-  if (type == GPU_FEATURE_TYPE_ALL) {
-    matches.push_back(kGpuFeatureNameAll);
-  } else {
-    if (type & GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS)
-      matches.push_back(kGpuFeatureNameAccelerated2dCanvas);
-    if (type & GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING)
-      matches.push_back(kGpuFeatureNameAcceleratedCompositing);
-    if (type & GPU_FEATURE_TYPE_WEBGL)
-      matches.push_back(kGpuFeatureNameWebgl);
-    if (type & GPU_FEATURE_TYPE_MULTISAMPLING)
-      matches.push_back(kGpuFeatureNameMultisampling);
-    if (type & GPU_FEATURE_TYPE_FLASH3D)
-      matches.push_back(kGpuFeatureNameFlash3d);
-    if (type & GPU_FEATURE_TYPE_FLASH_STAGE3D)
-      matches.push_back(kGpuFeatureNameFlashStage3d);
-    if (type & GPU_FEATURE_TYPE_FLASH_STAGE3D_BASELINE)
-      matches.push_back(kGpuFeatureNameFlashStage3dBaseline);
-    if (type & GPU_FEATURE_TYPE_TEXTURE_SHARING)
-      matches.push_back(kGpuFeatureNameTextureSharing);
-    if (type & GPU_FEATURE_TYPE_ACCELERATED_VIDEO_DECODE)
-      matches.push_back(kGpuFeatureNameAcceleratedVideoDecode);
-    if (type & GPU_FEATURE_TYPE_3D_CSS)
-      matches.push_back(kGpuFeatureName3dCss);
-    if (type & GPU_FEATURE_TYPE_ACCELERATED_VIDEO)
-      matches.push_back(kGpuFeatureNameAcceleratedVideo);
-    if (type & GPU_FEATURE_TYPE_PANEL_FITTING)
-      matches.push_back(kGpuFeatureNamePanelFitting);
-    if (type & GPU_FEATURE_TYPE_FORCE_COMPOSITING_MODE)
-      matches.push_back(kGpuFeatureNameForceCompositingMode);
-    if (!matches.size())
-      matches.push_back(kGpuFeatureNameUnknown);
-  }
-  return JoinString(matches, ',');
-}
+}  // namespace anonymous
 
 GpuSwitchingOption StringToGpuSwitchingOption(
     const std::string& switching_string) {
@@ -181,7 +97,7 @@
 }
 
 void UpdateStats(const GpuBlacklist* blacklist,
-                 uint32 blacklisted_features) {
+                 const std::set<int>& blacklisted_features) {
   uint32 max_entry_id = blacklist->max_entry_id();
   if (max_entry_id == 0) {
     // GPU Blacklist was not loaded.  No need to go further.
@@ -190,7 +106,7 @@
 
   const CommandLine& command_line = *CommandLine::ForCurrentProcess();
   bool disabled = false;
-  if (blacklisted_features == 0) {
+  if (blacklisted_features.size() == 0) {
     UMA_HISTOGRAM_ENUMERATION("GPU.BlacklistTestResultsPerEntry",
         0, max_entry_id + 1);
   } else {
@@ -245,7 +161,7 @@
     // We can't use UMA_HISTOGRAM_ENUMERATION here because the same name is
     // expected if the macro is used within a loop.
     GpuFeatureStatus value = kGpuFeatureEnabled;
-    if (blacklisted_features & kGpuFeatures[i])
+    if (blacklisted_features.count(kGpuFeatures[i]))
       value = kGpuFeatureBlacklisted;
     else if (kGpuFeatureUserFlags[i])
       value = kGpuFeatureDisabled;
@@ -265,4 +181,11 @@
   }
 }
 
+void MergeFeatureSets(std::set<int>* dst, const std::set<int>& src) {
+  DCHECK(dst);
+  if (src.empty())
+    return;
+  dst->insert(src.begin(), src.end());
+}
+
 }  // namespace content
diff --git a/content/browser/gpu/gpu_util.h b/content/browser/gpu/gpu_util.h
index cac15d8..0a277fc 100644
--- a/content/browser/gpu/gpu_util.h
+++ b/content/browser/gpu/gpu_util.h
@@ -5,27 +5,17 @@
 #ifndef CONTENT_BROWSER_GPU_GPU_UTIL_H_
 #define CONTENT_BROWSER_GPU_GPU_UTIL_H_
 
+#include <set>
 #include <string>
 
 #include "base/basictypes.h"
 #include "build/build_config.h"
 #include "content/common/content_export.h"
-#include "content/public/common/gpu_feature_type.h"
 #include "content/public/common/gpu_switching_option.h"
 
 namespace content {
 class GpuBlacklist;
 
-// Maps string to GpuFeatureType; returns GPU_FEATURE_TYPE_UNKNOWN if an
-// unknown name is input (case-sensitive).
-CONTENT_EXPORT GpuFeatureType StringToGpuFeatureType(
-    const std::string& feature_string);
-
-// Gets a string version of a feature type for use in about:gpu. Will yield
-// strings from StringToGpuFeatureType, e.g.
-// GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS becomes "accelerated_2d_canvas"
-CONTENT_EXPORT std::string GpuFeatureTypeToString(GpuFeatureType feature);
-
 // Maps string to GpuSwitchingOption; returns GPU_SWITCHING_UNKNOWN if an
 // unknown name is input (case-sensitive).
 CONTENT_EXPORT GpuSwitchingOption StringToGpuSwitchingOption(
@@ -37,7 +27,11 @@
 
 // Send UMA histograms about the enabled features.
 CONTENT_EXPORT void UpdateStats(
-    const GpuBlacklist* blacklist, uint32 blacklisted_features);
+    const GpuBlacklist* blacklist, const std::set<int>& blacklisted_features);
+
+// Merge features in src into dst.
+CONTENT_EXPORT void MergeFeatureSets(
+    std::set<int>* dst, const std::set<int>& src);
 
 }  // namespace content
 
diff --git a/content/browser/gpu/gpu_util_unittest.cc b/content/browser/gpu/gpu_util_unittest.cc
index bb1ef2b..5bc7d77 100644
--- a/content/browser/gpu/gpu_util_unittest.cc
+++ b/content/browser/gpu/gpu_util_unittest.cc
@@ -8,87 +8,7 @@
 
 namespace content {
 
-TEST(GpuUtilsTest, GpuFeatureTypFromString) {
-  // Test StringToGpuFeatureType.
-  EXPECT_EQ(StringToGpuFeatureType("accelerated_2d_canvas"),
-            GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS);
-  EXPECT_EQ(StringToGpuFeatureType("accelerated_compositing"),
-            GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING);
-  EXPECT_EQ(StringToGpuFeatureType("webgl"), GPU_FEATURE_TYPE_WEBGL);
-  EXPECT_EQ(StringToGpuFeatureType("multisampling"),
-            GPU_FEATURE_TYPE_MULTISAMPLING);
-  EXPECT_EQ(StringToGpuFeatureType("flash_3d"), GPU_FEATURE_TYPE_FLASH3D);
-  EXPECT_EQ(StringToGpuFeatureType("flash_stage3d"),
-            GPU_FEATURE_TYPE_FLASH_STAGE3D);
-  EXPECT_EQ(StringToGpuFeatureType("texture_sharing"),
-            GPU_FEATURE_TYPE_TEXTURE_SHARING);
-  EXPECT_EQ(StringToGpuFeatureType("accelerated_video_decode"),
-            GPU_FEATURE_TYPE_ACCELERATED_VIDEO_DECODE);
-  EXPECT_EQ(StringToGpuFeatureType("3d_css"), GPU_FEATURE_TYPE_3D_CSS);
-  EXPECT_EQ(StringToGpuFeatureType("accelerated_video"),
-            GPU_FEATURE_TYPE_ACCELERATED_VIDEO);
-  EXPECT_EQ(StringToGpuFeatureType("panel_fitting"),
-            GPU_FEATURE_TYPE_PANEL_FITTING);
-  EXPECT_EQ(StringToGpuFeatureType("force_compositing_mode"),
-            GPU_FEATURE_TYPE_FORCE_COMPOSITING_MODE);
-  EXPECT_EQ(StringToGpuFeatureType("all"), GPU_FEATURE_TYPE_ALL);
-  EXPECT_EQ(StringToGpuFeatureType("xxx"), GPU_FEATURE_TYPE_UNKNOWN);
-}
-
-TEST(GpuUtilsTest, GpuFeatureTypeToString) {
-  // Test GpuFeatureTypeToString for single-bit enums using the all enum
-  EXPECT_STREQ(
-      GpuFeatureTypeToString(GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING).c_str(),
-      "accelerated_compositing");
-  EXPECT_STREQ(
-      GpuFeatureTypeToString(GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS).c_str(),
-      "accelerated_2d_canvas");
-  EXPECT_STREQ(
-      GpuFeatureTypeToString(GPU_FEATURE_TYPE_WEBGL).c_str(), "webgl");
-  EXPECT_STREQ(
-      GpuFeatureTypeToString(GPU_FEATURE_TYPE_MULTISAMPLING).c_str(),
-      "multisampling");
-  EXPECT_STREQ(
-      GpuFeatureTypeToString(GPU_FEATURE_TYPE_FLASH3D).c_str(), "flash_3d");
-  EXPECT_STREQ(
-      GpuFeatureTypeToString(GPU_FEATURE_TYPE_FLASH_STAGE3D).c_str(),
-      "flash_stage3d");
-  EXPECT_STREQ(
-      GpuFeatureTypeToString(GPU_FEATURE_TYPE_TEXTURE_SHARING).c_str(),
-      "texture_sharing");
-  EXPECT_STREQ(
-      GpuFeatureTypeToString(GPU_FEATURE_TYPE_ACCELERATED_VIDEO_DECODE).c_str(),
-      "accelerated_video_decode");
-  EXPECT_STREQ(
-      GpuFeatureTypeToString(GPU_FEATURE_TYPE_3D_CSS).c_str(), "3d_css");
-  EXPECT_STREQ(
-      GpuFeatureTypeToString(GPU_FEATURE_TYPE_ACCELERATED_VIDEO).c_str(),
-      "accelerated_video");
-  EXPECT_STREQ(
-      GpuFeatureTypeToString(GPU_FEATURE_TYPE_PANEL_FITTING).c_str(),
-      "panel_fitting");
-  EXPECT_STREQ(
-      GpuFeatureTypeToString(GPU_FEATURE_TYPE_FORCE_COMPOSITING_MODE).c_str(),
-      "force_compositing_mode");
-  EXPECT_STREQ(
-      GpuFeatureTypeToString(GPU_FEATURE_TYPE_ALL).c_str(), "all");
-  EXPECT_STREQ(GpuFeatureTypeToString(
-      GPU_FEATURE_TYPE_UNKNOWN).c_str(), "unknown");
-  EXPECT_STREQ(
-      GpuFeatureTypeToString(
-          static_cast<GpuFeatureType>(
-              GPU_FEATURE_TYPE_WEBGL |
-              GPU_FEATURE_TYPE_MULTISAMPLING)).c_str(),
-      "webgl,multisampling");
-  EXPECT_STREQ(
-      GpuFeatureTypeToString(
-          static_cast<GpuFeatureType>(
-              GPU_FEATURE_TYPE_WEBGL |
-              GPU_FEATURE_TYPE_ALL)).c_str(),
-      "all");
-}
-
-TEST(GpuUtilsTest, GpuSwitchingOptionFromString) {
+TEST(GpuUtilTest, GpuSwitchingOptionFromString) {
   // Test StringToGpuSwitchingOption.
   EXPECT_EQ(StringToGpuSwitchingOption(
                 switches::kGpuSwitchingOptionNameAutomatic),
@@ -102,7 +22,7 @@
   EXPECT_EQ(StringToGpuSwitchingOption("xxx"), GPU_SWITCHING_OPTION_UNKNOWN);
 }
 
-TEST(GpuUtilsTest, GpuSwitchingOptionToString) {
+TEST(GpuUtilTest, GpuSwitchingOptionToString) {
   // Test GpuSwitchingOptionToString.
   EXPECT_STREQ(
       GpuSwitchingOptionToString(GPU_SWITCHING_OPTION_AUTOMATIC).c_str(),
@@ -115,4 +35,44 @@
       switches::kGpuSwitchingOptionNameForceIntegrated);
 }
 
+TEST(GpuUtilTest, MergeFeatureSets) {
+  {
+    // Merge two empty sets.
+    std::set<int> src;
+    std::set<int> dst;
+    EXPECT_TRUE(dst.empty());
+    MergeFeatureSets(&dst, src);
+    EXPECT_TRUE(dst.empty());
+  }
+  {
+    // Merge an empty set into a set with elements.
+    std::set<int> src;
+    std::set<int> dst;
+    dst.insert(1);
+    EXPECT_EQ(1u, dst.size());
+    MergeFeatureSets(&dst, src);
+    EXPECT_EQ(1u, dst.size());
+  }
+  {
+    // Merge two sets where the source elements are already in the target set.
+    std::set<int> src;
+    std::set<int> dst;
+    src.insert(1);
+    dst.insert(1);
+    EXPECT_EQ(1u, dst.size());
+    MergeFeatureSets(&dst, src);
+    EXPECT_EQ(1u, dst.size());
+  }
+  {
+    // Merge two sets with different elements.
+    std::set<int> src;
+    std::set<int> dst;
+    src.insert(1);
+    dst.insert(2);
+    EXPECT_EQ(1u, dst.size());
+    MergeFeatureSets(&dst, src);
+    EXPECT_EQ(2u, dst.size());
+  }
+}
+
 }  // namespace content
diff --git a/content/browser/gpu/shader_disk_cache.cc b/content/browser/gpu/shader_disk_cache.cc
index ca30937..621d7d53 100644
--- a/content/browser/gpu/shader_disk_cache.cc
+++ b/content/browser/gpu/shader_disk_cache.cc
@@ -101,6 +101,38 @@
   DISALLOW_COPY_AND_ASSIGN(ShaderDiskReadHelper);
 };
 
+class ShaderClearHelper : public base::RefCounted<ShaderClearHelper> {
+ public:
+  ShaderClearHelper(scoped_refptr<ShaderDiskCache> cache,
+                    const base::FilePath& path,
+                    const base::Time& delete_begin,
+                    const base::Time& delete_end,
+                    const base::Closure& callback);
+  void Clear();
+
+ private:
+  friend class base::RefCounted<ShaderClearHelper>;
+
+  enum OpType {
+    TERMINATE,
+    VERIFY_CACHE_SETUP,
+    DELETE_CACHE
+  };
+
+  ~ShaderClearHelper();
+
+  void DoClearShaderCache(int rv);
+
+  scoped_refptr<ShaderDiskCache> cache_;
+  OpType op_type_;
+  base::FilePath path_;
+  base::Time delete_begin_;
+  base::Time delete_end_;
+  base::Closure callback_;
+
+  DISALLOW_COPY_AND_ASSIGN(ShaderClearHelper);
+};
+
 ShaderDiskCacheEntry::ShaderDiskCacheEntry(base::WeakPtr<ShaderDiskCache> cache,
                                            const std::string& key,
                                            const std::string& shader)
@@ -309,6 +341,62 @@
                             base::Bind(&EntryCloser, entry_));
 }
 
+ShaderClearHelper::ShaderClearHelper(scoped_refptr<ShaderDiskCache> cache,
+                    const base::FilePath& path,
+                    const base::Time& delete_begin,
+                    const base::Time& delete_end,
+                    const base::Closure& callback)
+    : cache_(cache),
+      op_type_(VERIFY_CACHE_SETUP),
+      path_(path),
+      delete_begin_(delete_begin),
+      delete_end_(delete_end),
+      callback_(callback) {
+}
+
+ShaderClearHelper::~ShaderClearHelper() {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+}
+
+void ShaderClearHelper::Clear() {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DoClearShaderCache(net::OK);
+}
+
+void ShaderClearHelper::DoClearShaderCache(int rv) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+  // Hold a ref to ourselves so when we do the CacheCleared call we don't get
+  // auto-deleted when our ref count drops to zero.
+  scoped_refptr<ShaderClearHelper> helper = this;
+
+  while (rv != net::ERR_IO_PENDING) {
+    switch (op_type_) {
+      case VERIFY_CACHE_SETUP:
+        rv = cache_->SetAvailableCallback(
+            base::Bind(&ShaderClearHelper::DoClearShaderCache, this));
+        op_type_ = DELETE_CACHE;
+        break;
+      case DELETE_CACHE:
+        rv = cache_->Clear(
+            delete_begin_, delete_end_,
+            base::Bind(&ShaderClearHelper::DoClearShaderCache, this));
+        op_type_ = TERMINATE;
+        break;
+      case TERMINATE:
+        ShaderCacheFactory::GetInstance()->CacheCleared(path_);
+        callback_.Run();
+        rv = net::ERR_IO_PENDING;  // Break the loop.
+        break;
+      default:
+        NOTREACHED();  // Invalid state provided.
+        op_type_ = TERMINATE;
+        break;
+    }
+  }
+}
+
+// static
 ShaderCacheFactory* ShaderCacheFactory::GetInstance() {
   return Singleton<ShaderCacheFactory,
       LeakySingletonTraits<ShaderCacheFactory> >::get();
@@ -322,7 +410,7 @@
 
 void ShaderCacheFactory::SetCacheInfo(int32 client_id,
                                       const base::FilePath& path) {
-  client_id_to_path_map_[client_id] = path.Append(kGpuCachePath);
+  client_id_to_path_map_[client_id] = path;
 }
 
 void ShaderCacheFactory::RemoveCacheInfo(int32 client_id) {
@@ -330,18 +418,21 @@
 }
 
 scoped_refptr<ShaderDiskCache> ShaderCacheFactory::Get(int32 client_id) {
-  ClientIdToPathMap::iterator client_iter =
+  ClientIdToPathMap::iterator iter =
       client_id_to_path_map_.find(client_id);
-  if (client_iter == client_id_to_path_map_.end())
+  if (iter == client_id_to_path_map_.end())
     return NULL;
+  return ShaderCacheFactory::GetByPath(iter->second);
+}
 
-  ShaderCacheMap::iterator iter = shader_cache_map_.find(client_iter->second);
+scoped_refptr<ShaderDiskCache> ShaderCacheFactory::GetByPath(
+    const base::FilePath& path) {
+  ShaderCacheMap::iterator iter = shader_cache_map_.find(path);
   if (iter != shader_cache_map_.end())
     return iter->second;
 
-  ShaderDiskCache* cache = new ShaderDiskCache(client_iter->second);
+  ShaderDiskCache* cache = new ShaderDiskCache(path);
   cache->Init();
-
   return cache;
 }
 
@@ -354,6 +445,54 @@
   shader_cache_map_.erase(key);
 }
 
+void ShaderCacheFactory::ClearByPath(const base::FilePath& path,
+                                     const base::Time& delete_begin,
+                                     const base::Time& delete_end,
+                                     const base::Closure& callback) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK(!callback.is_null());
+
+  scoped_refptr<ShaderClearHelper> helper = new ShaderClearHelper(
+      GetByPath(path), path, delete_begin, delete_end, callback);
+
+  // We could receive requests to clear the same path with different
+  // begin/end times. So, we keep a list of requests. If we haven't seen this
+  // path before we kick off the clear and add it to the list. If we have see it
+  // already, then we already have a clear running. We add this clear to the
+  // list and wait for any previous clears to finish.
+  ShaderClearMap::iterator iter = shader_clear_map_.find(path);
+  if (iter != shader_clear_map_.end()) {
+    iter->second.push(helper);
+    return;
+  }
+
+  shader_clear_map_.insert(
+      std::pair<base::FilePath, ShaderClearQueue>(path, ShaderClearQueue()));
+  shader_clear_map_[path].push(helper);
+  helper->Clear();
+}
+
+void ShaderCacheFactory::CacheCleared(const base::FilePath& path) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+  ShaderClearMap::iterator iter = shader_clear_map_.find(path);
+  if (iter == shader_clear_map_.end()) {
+    LOG(ERROR) << "Completed clear but missing clear helper.";
+    return;
+  }
+
+  iter->second.pop();
+
+  // If there are remaining items in the list we trigger the Clear on the
+  // next one.
+  if (!iter->second.empty()) {
+    iter->second.front()->Clear();
+    return;
+  }
+
+  shader_clear_map_.erase(path);
+}
+
 ShaderDiskCache::ShaderDiskCache(const base::FilePath& cache_path)
     : cache_available_(false),
       max_cache_size_(0),
@@ -366,6 +505,8 @@
 
 ShaderDiskCache::~ShaderDiskCache() {
   ShaderCacheFactory::GetInstance()->RemoveFromCache(cache_path_);
+  if (backend_)
+    delete backend_;
 }
 
 void ShaderDiskCache::Init() {
@@ -377,7 +518,7 @@
 
   int rv = disk_cache::CreateCacheBackend(
       net::SHADER_CACHE,
-      cache_path_,
+      cache_path_.Append(kGpuCachePath),
       max_cache_size_,
       true,
       BrowserThread::GetMessageLoopProxyForThread(BrowserThread::CACHE),
@@ -400,24 +541,69 @@
   entry_map_[shim] = shim;
 }
 
+int ShaderDiskCache::Clear(
+    const base::Time begin_time, const base::Time end_time,
+    const net::CompletionCallback& completion_callback) {
+  int rv;
+  if (begin_time.is_null()) {
+    rv = backend_->DoomAllEntries(completion_callback);
+  } else {
+    rv = backend_->DoomEntriesBetween(begin_time, end_time,
+                                      completion_callback);
+  }
+  return rv;
+}
+
+int32 ShaderDiskCache::Size() {
+  if (!cache_available_)
+    return -1;
+  return backend_->GetEntryCount();
+}
+
+int ShaderDiskCache::SetAvailableCallback(
+    const net::CompletionCallback& callback) {
+  if (cache_available_)
+    return net::OK;
+  available_callback_ = callback;
+  return net::ERR_IO_PENDING;
+}
+
 void ShaderDiskCache::CacheCreatedCallback(int rv) {
   if (rv != net::OK) {
     LOG(ERROR) << "Shader Cache Creation failed: " << rv;
     return;
   }
-
-  cache_available_ = true;
-
   helper_ = new ShaderDiskReadHelper(AsWeakPtr(), host_id_);
   helper_->LoadCache();
 }
 
 void ShaderDiskCache::EntryComplete(void* entry) {
   entry_map_.erase(entry);
+
+  if (entry_map_.empty() && !cache_complete_callback_.is_null())
+    cache_complete_callback_.Run(net::OK);
 }
 
 void ShaderDiskCache::ReadComplete() {
   helper_ = NULL;
+
+  // The cache is considered available after we have finished reading any
+  // of the old cache values off disk. This prevents a potential race where we
+  // are reading from disk and execute a cache clear at the same time.
+  cache_available_ = true;
+  if (!available_callback_.is_null()) {
+    available_callback_.Run(net::OK);
+    available_callback_.Reset();
+  }
+}
+
+int ShaderDiskCache::SetCacheCompleteCallback(
+    const net::CompletionCallback& callback) {
+  if (entry_map_.empty()) {
+    return net::OK;
+  }
+  cache_complete_callback_ = callback;
+  return net::ERR_IO_PENDING;
 }
 
 }  // namespace content
diff --git a/content/browser/gpu/shader_disk_cache.h b/content/browser/gpu/shader_disk_cache.h
index 3ca5420..48438e4 100644
--- a/content/browser/gpu/shader_disk_cache.h
+++ b/content/browser/gpu/shader_disk_cache.h
@@ -6,17 +6,20 @@
 #define CONTENT_BROWSER_GPU_SHADER_DISK_CACHE_H_
 
 #include <map>
+#include <queue>
 #include <string>
 
 #include "base/files/file_path.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/singleton.h"
+#include "content/common/content_export.h"
 #include "net/disk_cache/disk_cache.h"
 
 namespace content {
 
 class ShaderDiskCacheEntry;
 class ShaderDiskReadHelper;
+class ShaderClearHelper;
 
 // ShaderDiskCache is the interface to the on disk cache for
 // GL shaders.
@@ -24,7 +27,7 @@
 // While this class is both RefCounted and SupportsWeakPtr
 // when using this class you should work with the RefCounting.
 // The WeakPtr is needed interally.
-class ShaderDiskCache
+class CONTENT_EXPORT ShaderDiskCache
     : public base::RefCounted<ShaderDiskCache>,
       public base::SupportsWeakPtr<ShaderDiskCache> {
  public:
@@ -35,8 +38,35 @@
     max_cache_size_ = max_cache_size;
   }
 
+  // Store the |shader| into the cache under |key|.
   void Cache(const std::string& key, const std::string& shader);
 
+  // Clear a range of entries. This supports unbounded deletes in either
+  // direction by using null Time values for either |begin_time| or |end_time|.
+  // The return value is a net error code. If this method returns
+  // ERR_IO_PENDING, the |completion_callback| will be invoked when the
+  // operation completes.
+  int Clear(
+      const base::Time begin_time,
+      const base::Time end_time,
+      const net::CompletionCallback& completion_callback);
+
+  // Sets a callback for when the cache is available. If the cache is
+  // already available the callback will not be called and net::OK is returned.
+  // If the callback is set net::ERR_IO_PENDING is returned and the callback
+  // will be executed when the cache is available.
+  int SetAvailableCallback(const net::CompletionCallback& callback);
+
+  // Returns the number of elements currently in the cache.
+  int32 Size();
+
+  // Set a callback notification for when all current entries have been
+  // written to the cache.
+  // The return value is a net error code. If this method returns
+  // ERR_IO_PENDING, the |callback| will be invoked when all entries have
+  // been written to the cache.
+  int SetCacheCompleteCallback(const net::CompletionCallback& callback);
+
  private:
   friend class base::RefCounted<ShaderDiskCache>;
   friend class ShaderDiskCacheEntry;
@@ -58,6 +88,8 @@
   int host_id_;
   base::FilePath cache_path_;
   bool is_initialized_;
+  net::CompletionCallback available_callback_;
+  net::CompletionCallback cache_complete_callback_;
 
   disk_cache::Backend* backend_;
 
@@ -69,30 +101,54 @@
 
 // ShaderCacheFactory maintains a cache of ShaderDiskCache objects
 // so we only create one per profile directory.
-class ShaderCacheFactory {
+class CONTENT_EXPORT ShaderCacheFactory {
  public:
   static ShaderCacheFactory* GetInstance();
 
+  // Clear the shader disk cache for the given |path|. This supports unbounded
+  // deletes in either direction by using null Time values for either
+  // |begin_time| or |end_time|. The |callback| will be executed when the
+  // clear is complete.
+  void ClearByPath(const base::FilePath& path,
+                   const base::Time& begin_time,
+                   const base::Time& end_time,
+                   const base::Closure& callback);
+
+  // Retrieve the shader disk cache for the provided |client_id|.
   scoped_refptr<ShaderDiskCache> Get(int32 client_id);
 
+  // Set the |path| to be used for the disk cache for |client_id|.
   void SetCacheInfo(int32 client_id, const base::FilePath& path);
+
+  // Remove the path mapping for |client_id|.
   void RemoveCacheInfo(int32 client_id);
 
+  // Set the provided |cache| into the cache map for the given |path|.
   void AddToCache(const base::FilePath& path, ShaderDiskCache* cache);
+
+  // Remove the provided |path| from our cache map.
   void RemoveFromCache(const base::FilePath& path);
 
  private:
   friend struct DefaultSingletonTraits<ShaderCacheFactory>;
+  friend class ShaderClearHelper;
 
   ShaderCacheFactory();
   ~ShaderCacheFactory();
 
+  scoped_refptr<ShaderDiskCache> GetByPath(const base::FilePath& path);
+  void CacheCleared(const base::FilePath& path);
+
   typedef std::map<base::FilePath, ShaderDiskCache*> ShaderCacheMap;
   ShaderCacheMap shader_cache_map_;
 
   typedef std::map<int32, base::FilePath> ClientIdToPathMap;
   ClientIdToPathMap client_id_to_path_map_;
 
+  typedef std::queue<scoped_refptr<ShaderClearHelper> > ShaderClearQueue;
+  typedef std::map<base::FilePath, ShaderClearQueue> ShaderClearMap;
+  ShaderClearMap shader_clear_map_;
+
   DISALLOW_COPY_AND_ASSIGN(ShaderCacheFactory);
 };
 
diff --git a/content/browser/gpu/shader_disk_cache_unittest.cc b/content/browser/gpu/shader_disk_cache_unittest.cc
new file mode 100644
index 0000000..93ed979
--- /dev/null
+++ b/content/browser/gpu/shader_disk_cache_unittest.cc
@@ -0,0 +1,78 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/files/scoped_temp_dir.h"
+#include "base/threading/thread.h"
+#include "content/browser/browser_thread_impl.h"
+#include "content/browser/gpu/shader_disk_cache.h"
+#include "content/public/test/test_browser_thread.h"
+#include "net/base/test_completion_callback.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+namespace {
+
+const int kDefaultClientId = 42;
+const char kCacheKey[] = "key";
+const char kCacheValue[] = "cached value";
+
+}  // namespace
+
+class ShaderDiskCacheTest : public testing::Test {
+ public:
+  ShaderDiskCacheTest()
+      : cache_thread_(BrowserThread::CACHE, &message_loop_),
+        io_thread_(BrowserThread::IO, &message_loop_) {
+  }
+
+  virtual ~ShaderDiskCacheTest() {}
+
+  const base::FilePath& cache_path() { return temp_dir_.path(); }
+
+  void InitCache() {
+    ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
+    ShaderCacheFactory::GetInstance()->SetCacheInfo(kDefaultClientId,
+                                                        cache_path());
+  }
+
+ private:
+  virtual void TearDown() OVERRIDE {
+    ShaderCacheFactory::GetInstance()->RemoveCacheInfo(kDefaultClientId);
+  }
+
+  base::ScopedTempDir temp_dir_;
+  base::MessageLoopForIO message_loop_;
+  TestBrowserThread cache_thread_;
+  TestBrowserThread io_thread_;
+
+  DISALLOW_COPY_AND_ASSIGN(ShaderDiskCacheTest);
+};
+
+TEST_F(ShaderDiskCacheTest, ClearsCache) {
+  InitCache();
+
+  scoped_refptr<ShaderDiskCache> cache =
+      ShaderCacheFactory::GetInstance()->Get(kDefaultClientId);
+  ASSERT_TRUE(cache.get() != NULL);
+
+  net::TestCompletionCallback available_cb;
+  int rv = cache->SetAvailableCallback(available_cb.callback());
+  ASSERT_EQ(net::OK, available_cb.GetResult(rv));
+  EXPECT_EQ(0, cache->Size());
+
+  cache->Cache(kCacheKey, kCacheValue);
+
+  net::TestCompletionCallback complete_cb;
+  rv = cache->SetCacheCompleteCallback(complete_cb.callback());
+  ASSERT_EQ(net::OK, complete_cb.GetResult(rv));
+  EXPECT_EQ(1, cache->Size());
+
+  base::Time time;
+  net::TestCompletionCallback clear_cb;
+  rv = cache->Clear(time, time, clear_cb.callback());
+  ASSERT_EQ(net::OK, clear_cb.GetResult(rv));
+  EXPECT_EQ(0, cache->Size());
+};
+
+}  // namespace content
diff --git a/content/browser/gpu/software_rendering_list.json b/content/browser/gpu/software_rendering_list.json
index f8d317f..3621b02 100644
--- a/content/browser/gpu/software_rendering_list.json
+++ b/content/browser/gpu/software_rendering_list.json
@@ -75,7 +75,7 @@
 {
   "name": "software rendering list",
   // Please update the version number whenever you change this file.
-  "version": "5.0",
+  "version": "5.3",
   "entries": [
     {
       "id": 1,
@@ -1015,6 +1015,84 @@
       "features": [
         "all"
       ]
+    },
+    {
+      "id": 69,
+      "description": "NVIDIA driver 8.17.11.9621 is buggy with Stage3D baseline mode.",
+      "cr_bugs": [172771],
+      "os": {
+        "type": "win"
+      },
+      "vendor_id": "0x10de",
+      "driver_version": {
+        "op": "=",
+        "number": "8.17.11.9621"
+      },
+      "features": [
+        "flash_stage3d_baseline"
+      ]
+    },
+    {
+      "id": 70,
+      "description": "NVIDIA driver 8.17.11.8267 is buggy with Stage3D baseline mode.",
+      "cr_bugs": [172771],
+      "os": {
+        "type": "win"
+      },
+      "vendor_id": "0x10de",
+      "driver_version": {
+        "op": "=",
+        "number": "8.17.11.8267"
+      },
+      "features": [
+        "flash_stage3d_baseline"
+      ]
+    },
+    {
+      "id": 71,
+      "description": "All Intel drivers before 8.15.10.2021 are buggy with Stage3D baseline mode.",
+      "cr_bugs": [172771],
+      "os": {
+        "type": "win"
+      },
+      "vendor_id": "0x8086",
+      "driver_version": {
+        "op": "<",
+        "number": "8.15.10.2021"
+      },
+      "features": [
+        "flash_stage3d_baseline"
+      ]
+    },
+    {
+      "id": 72,
+      "description": "NVIDIA GeForce 6200 LE is buggy with WebGL.",
+      "cr_bugs": [232529],
+      "os": {
+        "type": "win"
+      },
+      "vendor_id": "0x10de",
+      "device_id": ["0x0163"],
+      "features": [
+        "webgl"
+      ]
+    },
+    {
+      "id": 73,
+      "description": "WebGL is buggy with the NVIDIA GeForce GT 330M, 9400, and 9400M on MacOSX earlier than 10.8",
+      "cr_bugs": [233523],
+      "os": {
+        "type": "macosx",
+        "version": {
+          "op": "<",
+          "number": "10.8"
+        }
+      },
+      "vendor_id": "0x10de",
+      "device_id": ["0x0a29", "0x0861", "0x0863"],
+      "features": [
+        "webgl"
+      ]
     }
   ]
 }
diff --git a/content/browser/histogram_controller.cc b/content/browser/histogram_controller.cc
index 54f760b..240de25 100644
--- a/content/browser/histogram_controller.cc
+++ b/content/browser/histogram_controller.cc
@@ -73,8 +73,13 @@
   int pending_processes = 0;
   for (BrowserChildProcessHostIterator iter; !iter.Done(); ++iter) {
     int type = iter.GetData().process_type;
-    if (type != PROCESS_TYPE_PLUGIN && type != PROCESS_TYPE_GPU)
+    if (type != PROCESS_TYPE_PLUGIN &&
+        type != PROCESS_TYPE_GPU &&
+        type != PROCESS_TYPE_PPAPI_PLUGIN &&
+        type != PROCESS_TYPE_PPAPI_BROKER) {
       continue;
+    }
+
     ++pending_processes;
     if (!iter.Send(new ChildProcessMsg_GetChildHistogramData(sequence_number)))
       --pending_processes;
diff --git a/content/browser/histogram_synchronizer.cc b/content/browser/histogram_synchronizer.cc
index b2db39b..5a1e6f9 100644
--- a/content/browser/histogram_synchronizer.cc
+++ b/content/browser/histogram_synchronizer.cc
@@ -201,7 +201,7 @@
       base::TimeDelta::FromMinutes(1));
 }
 
-void FetchHistogramsAsynchronously(MessageLoop* callback_thread,
+void FetchHistogramsAsynchronously(base::MessageLoop* callback_thread,
                                    const base::Closure& callback,
                                    base::TimeDelta wait_time) {
   HistogramSynchronizer::FetchHistogramsAsynchronously(
@@ -210,7 +210,7 @@
 
 // static
 void HistogramSynchronizer::FetchHistogramsAsynchronously(
-    MessageLoop* callback_thread,
+    base::MessageLoop* callback_thread,
     const base::Closure& callback,
     base::TimeDelta wait_time) {
   DCHECK(callback_thread != NULL);
@@ -287,10 +287,10 @@
 }
 
 void HistogramSynchronizer::SetCallbackTaskAndThread(
-    MessageLoop* callback_thread,
+    base::MessageLoop* callback_thread,
     const base::Closure& callback) {
   base::Closure old_callback;
-  MessageLoop* old_thread = NULL;
+  base::MessageLoop* old_thread = NULL;
   {
     base::AutoLock auto_lock(lock_);
     old_callback = callback_;
@@ -307,7 +307,7 @@
 void HistogramSynchronizer::ForceHistogramSynchronizationDoneCallback(
     int sequence_number) {
   base::Closure callback;
-  MessageLoop* thread = NULL;
+  base::MessageLoop* thread = NULL;
   {
     base::AutoLock lock(lock_);
     if (sequence_number != async_sequence_number_)
@@ -320,7 +320,7 @@
   InternalPostTask(thread, callback);
 }
 
-void HistogramSynchronizer::InternalPostTask(MessageLoop* thread,
+void HistogramSynchronizer::InternalPostTask(base::MessageLoop* thread,
                                              const base::Closure& callback) {
   if (callback.is_null() || !thread)
     return;
diff --git a/content/browser/histogram_synchronizer.h b/content/browser/histogram_synchronizer.h
index 0968abd..0b279a0 100644
--- a/content/browser/histogram_synchronizer.h
+++ b/content/browser/histogram_synchronizer.h
@@ -15,7 +15,9 @@
 #include "base/time.h"
 #include "content/browser/histogram_subscriber.h"
 
+namespace base {
 class MessageLoop;
+}
 
 namespace content {
 
@@ -68,7 +70,7 @@
   // changes to histograms.  When all changes have been acquired, or when the
   // wait time expires (whichever is sooner), post the callback to the
   // specified message loop. Note the callback is posted exactly once.
-  static void FetchHistogramsAsynchronously(MessageLoop* callback_thread,
+  static void FetchHistogramsAsynchronously(base::MessageLoop* callback_thread,
                                             const base::Closure& callback,
                                             base::TimeDelta wait_time);
 
@@ -109,13 +111,14 @@
   // callaback_thread_.  This side effect should not generally happen, but is in
   // place to assure correctness (that any tasks that were set, are eventually
   // called, and never merely discarded).
-  void SetCallbackTaskAndThread(MessageLoop* callback_thread,
+  void SetCallbackTaskAndThread(base::MessageLoop* callback_thread,
                                 const base::Closure& callback);
 
   void ForceHistogramSynchronizationDoneCallback(int sequence_number);
 
   // Internal helper function, to post task, and record callback stats.
-  void InternalPostTask(MessageLoop* thread, const base::Closure& callback);
+  void InternalPostTask(base::MessageLoop* thread,
+                        const base::Closure& callback);
 
   // Gets a new sequence number to be sent to processes from browser process.
   int GetNextAvailableSequenceNumber(ProcessHistogramRequester requester);
@@ -127,7 +130,7 @@
   // the task and thread we use to post a completion notification in
   // callback_ and callback_thread_.
   base::Closure callback_;
-  MessageLoop* callback_thread_;
+  base::MessageLoop* callback_thread_;
 
   // We don't track the actual processes that are contacted for an update, only
   // the count of the number of processes, and we can sometimes time-out and
diff --git a/content/browser/host_zoom_map_impl.cc b/content/browser/host_zoom_map_impl.cc
index a60a923..ad70977 100644
--- a/content/browser/host_zoom_map_impl.cc
+++ b/content/browser/host_zoom_map_impl.cc
@@ -2,11 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include <cmath>
-
 #include "content/browser/host_zoom_map_impl.h"
 
-#include "base/string_piece.h"
+#include <cmath>
+
+#include "base/strings/string_piece.h"
 #include "base/utf_string_conversions.h"
 #include "base/values.h"
 #include "content/browser/renderer_host/render_process_host_impl.h"
diff --git a/content/browser/host_zoom_map_impl_unittest.cc b/content/browser/host_zoom_map_impl_unittest.cc
index 055e061..ccb04e4 100644
--- a/content/browser/host_zoom_map_impl_unittest.cc
+++ b/content/browser/host_zoom_map_impl_unittest.cc
@@ -18,7 +18,7 @@
   }
 
  protected:
-  MessageLoop message_loop_;
+  base::MessageLoop message_loop_;
   TestBrowserThread ui_thread_;
 };
 
diff --git a/content/browser/hyphenator/hyphenator_message_filter.cc b/content/browser/hyphenator/hyphenator_message_filter.cc
index 1653ea3..e14233a 100644
--- a/content/browser/hyphenator/hyphenator_message_filter.cc
+++ b/content/browser/hyphenator/hyphenator_message_filter.cc
@@ -31,7 +31,7 @@
     RenderProcessHost* render_process_host)
     : render_process_host_(render_process_host),
       dictionary_file_(base::kInvalidPlatformFileValue),
-      weak_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
+      weak_factory_(this) {
 }
 
 HyphenatorMessageFilter::~HyphenatorMessageFilter() {
diff --git a/content/browser/in_process_webkit/indexed_db_browsertest.cc b/content/browser/in_process_webkit/indexed_db_browsertest.cc
index ddbc331..45c0a69 100644
--- a/content/browser/in_process_webkit/indexed_db_browsertest.cc
+++ b/content/browser/in_process_webkit/indexed_db_browsertest.cc
@@ -11,7 +11,7 @@
 #include "base/process_util.h"
 #include "base/test/thread_test_helper.h"
 #include "base/utf_string_conversions.h"
-#include "content/browser/in_process_webkit/indexed_db_context_impl.h"
+#include "content/browser/indexed_db/indexed_db_context_impl.h"
 #include "content/browser/web_contents/web_contents_impl.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/browser_thread.h"
@@ -113,7 +113,7 @@
             BrowserThread::WEBKIT_DEPRECATED)));
     EXPECT_TRUE(helper->Run());
     // Wait for DidGetDiskUsage to be called.
-    MessageLoop::current()->RunUntilIdle();
+    base::MessageLoop::current()->RunUntilIdle();
     return disk_usage_;
   }
  private:
@@ -390,7 +390,7 @@
 IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, PRE_VersionChangeCrashResilience) {
   NavigateAndWaitForTitle(shell(), "version_change_crash.html", "#part2",
                           "pass - part2 - crash me");
-  NavigateToURL(shell(), GURL(chrome::kChromeUIBrowserCrashHost));
+  NavigateToURL(shell(), GURL(kChromeUIBrowserCrashHost));
 }
 
 IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, VersionChangeCrashResilience) {
diff --git a/content/browser/in_process_webkit/indexed_db_callbacks.cc b/content/browser/in_process_webkit/indexed_db_callbacks.cc
index 33f5f61..8884bef 100644
--- a/content/browser/in_process_webkit/indexed_db_callbacks.cc
+++ b/content/browser/in_process_webkit/indexed_db_callbacks.cc
@@ -172,12 +172,12 @@
           ipc_thread_id(), ipc_callbacks_id(), IndexedDBKey(value)));
 }
 
-void IndexedDBCallbacks<WebKit::WebDOMStringList>::onSuccess(
-    const WebKit::WebDOMStringList& value) {
+void IndexedDBCallbacks<WebKit::WebVector<WebKit::WebString> >::onSuccess(
+    const WebKit::WebVector<WebKit::WebString>& value) {
 
   std::vector<string16> list;
-  for (unsigned i = 0; i < value.length(); ++i)
-      list.push_back(value.item(i));
+  for (unsigned i = 0; i < value.size(); ++i)
+      list.push_back(value[i]);
 
   dispatcher_host()->Send(
       new IndexedDBMsg_CallbacksSuccessStringList(
diff --git a/content/browser/in_process_webkit/indexed_db_callbacks.h b/content/browser/in_process_webkit/indexed_db_callbacks.h
index b7d7094..4ab0ab1 100644
--- a/content/browser/in_process_webkit/indexed_db_callbacks.h
+++ b/content/browser/in_process_webkit/indexed_db_callbacks.h
@@ -10,11 +10,11 @@
 #include "content/browser/in_process_webkit/indexed_db_dispatcher_host.h"
 #include "googleurl/src/gurl.h"
 #include "third_party/WebKit/Source/Platform/chromium/public/WebData.h"
+#include "third_party/WebKit/Source/Platform/chromium/public/WebIDBCallbacks.h"
+#include "third_party/WebKit/Source/Platform/chromium/public/WebIDBCursor.h"
+#include "third_party/WebKit/Source/Platform/chromium/public/WebIDBDatabase.h"
+#include "third_party/WebKit/Source/Platform/chromium/public/WebIDBDatabaseError.h"
 #include "third_party/WebKit/Source/Platform/chromium/public/WebString.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/WebIDBDatabase.h"
-#include "third_party/WebKit/Source/WebKit/chromium/public/WebIDBDatabaseError.h"
 
 namespace content {
 
@@ -137,11 +137,11 @@
   DISALLOW_IMPLICIT_CONSTRUCTORS(IndexedDBCallbacks);
 };
 
-// WebDOMStringList is implemented in WebKit as opposed to being an
+// WebVector is implemented in WebKit as opposed to being an
 // interface Chromium implements.  Thus we pass a const ___& version and thus
 // we need this specialization.
 template <>
-class IndexedDBCallbacks<WebKit::WebDOMStringList>
+class IndexedDBCallbacks<WebKit::WebVector<WebKit::WebString> >
     : public IndexedDBCallbacksBase {
  public:
   IndexedDBCallbacks(
@@ -151,7 +151,7 @@
       : IndexedDBCallbacksBase(dispatcher_host, ipc_thread_id,
                                ipc_callbacks_id) { }
 
-  virtual void onSuccess(const WebKit::WebDOMStringList& value);
+    virtual void onSuccess(const WebKit::WebVector<WebKit::WebString>& value);
 
  private:
   DISALLOW_IMPLICIT_CONSTRUCTORS(IndexedDBCallbacks);
diff --git a/content/browser/in_process_webkit/indexed_db_database_callbacks.h b/content/browser/in_process_webkit/indexed_db_database_callbacks.h
index 981b218..43b3fb1 100644
--- a/content/browser/in_process_webkit/indexed_db_database_callbacks.h
+++ b/content/browser/in_process_webkit/indexed_db_database_callbacks.h
@@ -6,7 +6,7 @@
 #define CONTENT_BROWSER_IN_PROCESS_WEBKIT_INDEXED_DB_DATABASE_CALLBACKS_H_
 
 #include "base/memory/ref_counted.h"
-#include "third_party/WebKit/Source/WebKit/chromium/public/WebIDBDatabaseCallbacks.h"
+#include "third_party/WebKit/Source/Platform/chromium/public/WebIDBDatabaseCallbacks.h"
 
 namespace content {
 class IndexedDBDispatcherHost;
diff --git a/content/browser/in_process_webkit/indexed_db_dispatcher_host.cc b/content/browser/in_process_webkit/indexed_db_dispatcher_host.cc
index 71d0ab3..ee0c3ad 100644
--- a/content/browser/in_process_webkit/indexed_db_dispatcher_host.cc
+++ b/content/browser/in_process_webkit/indexed_db_dispatcher_host.cc
@@ -12,8 +12,8 @@
 #include "base/process_util.h"
 #include "base/utf_string_conversions.h"
 #include "content/browser/in_process_webkit/indexed_db_callbacks.h"
-#include "content/browser/in_process_webkit/indexed_db_context_impl.h"
 #include "content/browser/in_process_webkit/indexed_db_database_callbacks.h"
+#include "content/browser/indexed_db/indexed_db_context_impl.h"
 #include "content/browser/renderer_host/render_message_filter.h"
 #include "content/common/indexed_db/indexed_db_messages.h"
 #include "content/public/browser/browser_thread.h"
@@ -22,23 +22,20 @@
 #include "content/public/common/result_codes.h"
 #include "googleurl/src/gurl.h"
 #include "third_party/WebKit/Source/Platform/chromium/public/WebData.h"
+#include "third_party/WebKit/Source/Platform/chromium/public/WebIDBCursor.h"
+#include "third_party/WebKit/Source/Platform/chromium/public/WebIDBDatabase.h"
+#include "third_party/WebKit/Source/Platform/chromium/public/WebIDBDatabaseCallbacks.h"
+#include "third_party/WebKit/Source/Platform/chromium/public/WebIDBDatabaseError.h"
+#include "third_party/WebKit/Source/Platform/chromium/public/WebIDBDatabaseException.h"
+#include "third_party/WebKit/Source/Platform/chromium/public/WebIDBFactory.h"
+#include "third_party/WebKit/Source/Platform/chromium/public/WebIDBMetadata.h"
+#include "third_party/WebKit/Source/Platform/chromium/public/WebString.h"
 #include "third_party/WebKit/Source/Platform/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/WebIDBDatabaseCallbacks.h"
-#include "third_party/WebKit/Source/WebKit/chromium/public/WebIDBDatabaseError.h"
-#include "third_party/WebKit/Source/WebKit/chromium/public/WebIDBDatabaseException.h"
-#include "third_party/WebKit/Source/WebKit/chromium/public/WebIDBFactory.h"
-#include "third_party/WebKit/Source/WebKit/chromium/public/WebIDBMetadata.h"
-#include "third_party/WebKit/Source/WebKit/chromium/public/WebSecurityOrigin.h"
 #include "webkit/base/file_path_string_conversions.h"
 #include "webkit/database/database_util.h"
 
 using webkit_database::DatabaseUtil;
-using WebKit::WebDOMStringList;
 using WebKit::WebData;
-using WebKit::WebExceptionCode;
 using WebKit::WebIDBCallbacks;
 using WebKit::WebIDBCursor;
 using WebKit::WebIDBDatabase;
@@ -47,7 +44,7 @@
 using WebKit::WebIDBKey;
 using WebKit::WebIDBMetadata;
 using WebKit::WebIDBObjectStore;
-using WebKit::WebSecurityOrigin;
+using WebKit::WebString;
 using WebKit::WebVector;
 
 namespace content {
@@ -64,10 +61,8 @@
 IndexedDBDispatcherHost::IndexedDBDispatcherHost(
     int ipc_process_id, IndexedDBContextImpl* indexed_db_context)
     : indexed_db_context_(indexed_db_context),
-      ALLOW_THIS_IN_INITIALIZER_LIST(database_dispatcher_host_(
-          new DatabaseDispatcherHost(this))),
-      ALLOW_THIS_IN_INITIALIZER_LIST(cursor_dispatcher_host_(
-          new CursorDispatcherHost(this))),
+      database_dispatcher_host_(new DatabaseDispatcherHost(this)),
+      cursor_dispatcher_host_(new CursorDispatcherHost(this)),
       ipc_process_id_(ipc_process_id) {
   DCHECK(indexed_db_context_.get());
 }
@@ -135,7 +130,7 @@
 }
 
 int32 IndexedDBDispatcherHost::Add(WebIDBCursor* idb_cursor) {
-  if (!cursor_dispatcher_host_.get()) {
+  if (!cursor_dispatcher_host_) {
     delete idb_cursor;
     return 0;
   }
@@ -145,7 +140,7 @@
 int32 IndexedDBDispatcherHost::Add(WebIDBDatabase* idb_database,
                                    int32 ipc_thread_id,
                                    const GURL& origin_url) {
-  if (!database_dispatcher_host_.get()) {
+  if (!database_dispatcher_host_) {
     delete idb_database;
     return 0;
   }
@@ -230,12 +225,9 @@
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT_DEPRECATED));
   base::FilePath indexed_db_path = indexed_db_context_->data_path();
 
-  WebSecurityOrigin origin(
-      WebSecurityOrigin::createFromDatabaseIdentifier(params.origin));
-
   Context()->GetIDBFactory()->getDatabaseNames(
-      new IndexedDBCallbacks<WebDOMStringList>(this, params.ipc_thread_id,
-      params.ipc_callbacks_id), origin, NULL,
+      new IndexedDBCallbacks<WebVector<WebString> >(this, params.ipc_thread_id,
+      params.ipc_callbacks_id), params.database_identifier,
       webkit_base::FilePathToWebString(indexed_db_path));
 }
 
@@ -244,9 +236,8 @@
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT_DEPRECATED));
   base::FilePath indexed_db_path = indexed_db_context_->data_path();
 
-  GURL origin_url = DatabaseUtil::GetOriginFromIdentifier(params.origin);
-  WebSecurityOrigin origin(
-      WebSecurityOrigin::createFromDatabaseIdentifier(params.origin));
+  GURL origin_url =
+      DatabaseUtil::GetOriginFromIdentifier(params.database_identifier);
 
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT_DEPRECATED));
 
@@ -265,7 +256,8 @@
                                      origin_url),
       new IndexedDBDatabaseCallbacks(this, params.ipc_thread_id,
                                      params.ipc_database_callbacks_id),
-      origin, NULL, webkit_base::FilePathToWebString(indexed_db_path));
+      params.database_identifier,
+      webkit_base::FilePathToWebString(indexed_db_path));
 }
 
 void IndexedDBDispatcherHost::OnIDBFactoryDeleteDatabase(
@@ -278,7 +270,7 @@
       new IndexedDBCallbacks<WebData>(this,
                                       params.ipc_thread_id,
                                       params.ipc_callbacks_id),
-      WebSecurityOrigin::createFromDatabaseIdentifier(params.origin), NULL,
+      params.database_identifier,
       webkit_base::FilePathToWebString(indexed_db_path));
 }
 
@@ -770,14 +762,11 @@
   if (!idb_cursor)
     return;
 
-  WebKit::WebExceptionCode ec = 0;
   idb_cursor->advance(count,
                       new IndexedDBCallbacks<WebIDBCursor>(parent_,
                                                            ipc_thread_id,
                                                            ipc_callbacks_id,
-                                                           ipc_cursor_id),
-                      ec);
-  DCHECK(!ec);
+                                                           ipc_cursor_id));
 }
 
 void IndexedDBDispatcherHost::CursorDispatcherHost::OnContinue(
@@ -791,12 +780,10 @@
   if (!idb_cursor)
     return;
 
-  WebKit::WebExceptionCode ec = 0;
   idb_cursor->continueFunction(
       key, new IndexedDBCallbacks<WebIDBCursor>(parent_, ipc_thread_id,
                                                 ipc_callbacks_id,
-                                                ipc_cursor_id), ec);
-  DCHECK(!ec);
+                                                ipc_cursor_id));
 }
 
 void IndexedDBDispatcherHost::CursorDispatcherHost::OnPrefetch(
@@ -810,12 +797,10 @@
   if (!idb_cursor)
     return;
 
-  WebKit::WebExceptionCode ec = 0;
   idb_cursor->prefetchContinue(
       n, new IndexedDBCallbacks<WebIDBCursor>(parent_, ipc_thread_id,
                                               ipc_callbacks_id,
-                                              ipc_cursor_id), ec);
-  DCHECK(!ec);
+                                              ipc_cursor_id));
 }
 
 void IndexedDBDispatcherHost::CursorDispatcherHost::OnPrefetchReset(
@@ -839,11 +824,9 @@
   if (!idb_cursor)
     return;
 
-  WebKit::WebExceptionCode ec = 0;
   idb_cursor->deleteFunction(
       new IndexedDBCallbacks<WebData>(parent_, ipc_thread_id,
-                                      ipc_callbacks_id), ec);
-  DCHECK(!ec);
+                                      ipc_callbacks_id));
 }
 
 void IndexedDBDispatcherHost::CursorDispatcherHost::OnDestroyed(
diff --git a/content/browser/in_process_webkit/indexed_db_dispatcher_host.h b/content/browser/in_process_webkit/indexed_db_dispatcher_host.h
index 7298049..48a75d7 100644
--- a/content/browser/in_process_webkit/indexed_db_dispatcher_host.h
+++ b/content/browser/in_process_webkit/indexed_db_dispatcher_host.h
@@ -11,7 +11,6 @@
 #include "base/basictypes.h"
 #include "base/id_map.h"
 #include "content/public/browser/browser_message_filter.h"
-#include "third_party/WebKit/Source/WebKit/chromium/public/WebExceptionCode.h"
 
 class GURL;
 struct IndexedDBDatabaseMetadata;
diff --git a/content/browser/indexed_db/OWNERS b/content/browser/indexed_db/OWNERS
new file mode 100644
index 0000000..b106dad
--- /dev/null
+++ b/content/browser/indexed_db/OWNERS
@@ -0,0 +1,4 @@
+dgrogan@chromium.org
+michaeln@chromium.org
+jsbell@chromium.org
+alecflett@chromium.org
diff --git a/content/browser/in_process_webkit/indexed_db_context_impl.cc b/content/browser/indexed_db/indexed_db_context_impl.cc
similarity index 88%
rename from content/browser/in_process_webkit/indexed_db_context_impl.cc
rename to content/browser/indexed_db/indexed_db_context_impl.cc
index 5591dc7..b95be28 100644
--- a/content/browser/in_process_webkit/indexed_db_context_impl.cc
+++ b/content/browser/indexed_db/indexed_db_context_impl.cc
@@ -2,7 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "content/browser/in_process_webkit/indexed_db_context_impl.h"
+#include "content/browser/indexed_db/indexed_db_context_impl.h"
+
+#include <vector>
 
 #include "base/bind.h"
 #include "base/command_line.h"
@@ -11,14 +13,14 @@
 #include "base/message_loop_proxy.h"
 #include "base/string_util.h"
 #include "base/utf_string_conversions.h"
-#include "content/browser/in_process_webkit/indexed_db_quota_client.h"
+#include "content/browser/indexed_db/indexed_db_quota_client.h"
 #include "content/public/browser/browser_thread.h"
+#include "content/public/browser/indexed_db_info.h"
 #include "content/public/common/content_switches.h"
 #include "third_party/WebKit/Source/Platform/chromium/public/WebCString.h"
+#include "third_party/WebKit/Source/Platform/chromium/public/WebIDBDatabase.h"
+#include "third_party/WebKit/Source/Platform/chromium/public/WebIDBFactory.h"
 #include "third_party/WebKit/Source/Platform/chromium/public/WebString.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 "webkit/base/file_path_string_conversions.h"
 #include "webkit/database/database_util.h"
 #include "webkit/quota/quota_manager.h"
@@ -27,7 +29,6 @@
 using webkit_database::DatabaseUtil;
 using WebKit::WebIDBDatabase;
 using WebKit::WebIDBFactory;
-using WebKit::WebSecurityOrigin;
 
 namespace content {
 const base::FilePath::CharType IndexedDBContextImpl::kIndexedDBDirectory[] =
@@ -102,7 +103,7 @@
 
 WebIDBFactory* IndexedDBContextImpl::GetIDBFactory() {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT_DEPRECATED));
-  if (!idb_factory_.get()) {
+  if (!idb_factory_) {
     // Prime our cache of origins with existing databases so we can
     // detect when dbs are newly created.
     GetOriginSet();
@@ -122,6 +123,22 @@
   return origins;
 }
 
+std::vector<IndexedDBInfo> IndexedDBContextImpl::GetAllOriginsInfo() {
+  std::vector<GURL> origins = GetAllOrigins();
+  std::vector<IndexedDBInfo> result;
+  for (std::vector<GURL>::const_iterator iter = origins.begin();
+       iter != origins.end(); ++iter) {
+    const GURL& origin_url = *iter;
+
+    base::FilePath idb_directory = GetFilePath(origin_url);
+    result.push_back(IndexedDBInfo(origin_url,
+                                   GetOriginDiskUsage(origin_url),
+                                   GetOriginLastModified(origin_url),
+                                   idb_directory));
+  }
+  return result;
+}
+
 int64 IndexedDBContextImpl::GetOriginDiskUsage(const GURL& origin_url) {
   if (data_path_.empty() || !IsInOriginSet(origin_url))
     return 0;
@@ -132,8 +149,7 @@
 base::Time IndexedDBContextImpl::GetOriginLastModified(const GURL& origin_url) {
   if (data_path_.empty() || !IsInOriginSet(origin_url))
     return base::Time();
-  string16 origin_id = DatabaseUtil::GetOriginIdentifier(origin_url);
-  base::FilePath idb_directory = GetIndexedDBFilePath(origin_id);
+  base::FilePath idb_directory = GetFilePath(origin_url);
   base::PlatformFileInfo file_info;
   if (!file_util::GetFileInfo(idb_directory, &file_info))
     return base::Time();
@@ -142,6 +158,25 @@
 
 void IndexedDBContextImpl::DeleteForOrigin(const GURL& origin_url) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT_DEPRECATED));
+  ForceClose(origin_url);
+  if (data_path_.empty() || !IsInOriginSet(origin_url))
+    return;
+
+  base::FilePath idb_directory = GetFilePath(origin_url);
+  EnsureDiskUsageCacheInitialized(origin_url);
+  const bool recursive = true;
+  bool deleted = file_util::Delete(idb_directory, recursive);
+
+  QueryDiskAndUpdateQuotaUsage(origin_url);
+  if (deleted) {
+    RemoveFromOriginSet(origin_url);
+    origin_size_map_.erase(origin_url);
+    space_available_map_.erase(origin_url);
+  }
+}
+
+void IndexedDBContextImpl::ForceClose(const GURL& origin_url) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT_DEPRECATED));
   if (data_path_.empty() || !IsInOriginSet(origin_url))
     return;
 
@@ -154,22 +189,14 @@
       connections.erase(it++);
       db->forceClose();
     }
-    DCHECK(connections_[origin_url].size() == 0);
+    DCHECK_EQ(connections_[origin_url].size(), 0UL);
     connections_.erase(origin_url);
   }
+}
 
+base::FilePath IndexedDBContextImpl::GetFilePath(const GURL& origin_url) {
   string16 origin_id = DatabaseUtil::GetOriginIdentifier(origin_url);
-  base::FilePath idb_directory = GetIndexedDBFilePath(origin_id);
-  EnsureDiskUsageCacheInitialized(origin_url);
-  const bool recursive = true;
-  bool deleted = file_util::Delete(idb_directory, recursive);
-
-  QueryDiskAndUpdateQuotaUsage(origin_url);
-  if (deleted) {
-    RemoveFromOriginSet(origin_url);
-    origin_size_map_.erase(origin_url);
-    space_available_map_.erase(origin_url);
-  }
+  return GetIndexedDBFilePath(origin_id);
 }
 
 base::FilePath IndexedDBContextImpl::GetFilePathForTesting(
@@ -179,7 +206,7 @@
 
 void IndexedDBContextImpl::ConnectionOpened(const GURL& origin_url,
                                             WebIDBDatabase* connection) {
-  DCHECK(connections_[origin_url].count(connection) == 0);
+  DCHECK_EQ(connections_[origin_url].count(connection), 0UL);
   if (quota_manager_proxy()) {
     quota_manager_proxy()->NotifyStorageAccessed(
         quota::QuotaClient::kIndexedDatabase, origin_url,
@@ -352,7 +379,7 @@
 }
 
 std::set<GURL>* IndexedDBContextImpl::GetOriginSet() {
-  if (!origin_set_.get()) {
+  if (!origin_set_) {
     origin_set_.reset(new std::set<GURL>);
     std::vector<GURL> origins;
     GetAllOriginsAndPaths(data_path_, &origins, NULL);
diff --git a/content/browser/in_process_webkit/indexed_db_context_impl.h b/content/browser/indexed_db/indexed_db_context_impl.h
similarity index 85%
rename from content/browser/in_process_webkit/indexed_db_context_impl.h
rename to content/browser/indexed_db/indexed_db_context_impl.h
index 284f41f..e40e6ae 100644
--- a/content/browser/in_process_webkit/indexed_db_context_impl.h
+++ b/content/browser/indexed_db/indexed_db_context_impl.h
@@ -2,11 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CONTENT_BROWSER_IN_PROCESS_WEBKIT_INDEXED_DB_CONTEXT_IMPL_H_
-#define CONTENT_BROWSER_IN_PROCESS_WEBKIT_INDEXED_DB_CONTEXT_IMPL_H_
+#ifndef CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_CONTEXT_IMPL_H_
+#define CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_CONTEXT_IMPL_H_
 
 #include <map>
 #include <set>
+#include <vector>
 
 #include "base/compiler_specific.h"
 #include "base/files/file_path.h"
@@ -53,17 +54,16 @@
   static const base::FilePath::CharType kIndexedDBExtension[];
 
   // Disables the exit-time deletion of session-only data.
-  void SetForceKeepSessionState() {
-    force_keep_session_state_ = true;
-  }
+  void SetForceKeepSessionState() { force_keep_session_state_ = true; }
 
   // IndexedDBContext implementation:
   virtual std::vector<GURL> GetAllOrigins() OVERRIDE;
+  virtual std::vector<IndexedDBInfo> GetAllOriginsInfo() OVERRIDE;
   virtual int64 GetOriginDiskUsage(const GURL& origin_url) OVERRIDE;
   virtual base::Time GetOriginLastModified(const GURL& origin_url) OVERRIDE;
   virtual void DeleteForOrigin(const GURL& origin_url) OVERRIDE;
-  virtual base::FilePath GetFilePathForTesting(
-      const string16& origin_id) const OVERRIDE;
+  virtual base::FilePath GetFilePathForTesting(const string16& origin_id) const
+      OVERRIDE;
 
   // Methods called by IndexedDBDispatcherHost for quota support.
   void ConnectionOpened(const GURL& origin_url, WebKit::WebIDBDatabase*);
@@ -74,7 +74,13 @@
 
   quota::QuotaManagerProxy* quota_manager_proxy();
 
+  void ForceClose(const GURL& origin_url);
+  base::FilePath GetFilePath(const GURL& origin_url);
   base::FilePath data_path() const { return data_path_; }
+  bool IsInOriginSet(const GURL& origin_url) {
+    std::set<GURL>* set = GetOriginSet();
+    return set->find(origin_url) != set->end();
+  }
 
   // For unit tests allow to override the |data_path_|.
   void set_data_path_for_testing(const base::FilePath& data_path) {
@@ -98,8 +104,10 @@
   int64 ReadUsageFromDisk(const GURL& origin_url) const;
   void EnsureDiskUsageCacheInitialized(const GURL& origin_url);
   void QueryDiskAndUpdateQuotaUsage(const GURL& origin_url);
-  void GotUsageAndQuota(const GURL& origin_url, quota::QuotaStatusCode,
-                        int64 usage, int64 quota);
+  void GotUsageAndQuota(const GURL& origin_url,
+                        quota::QuotaStatusCode,
+                        int64 usage,
+                        int64 quota);
   void GotUpdatedQuota(const GURL& origin_url, int64 usage, int64 quota);
   void QueryAvailableQuota(const GURL& origin_url);
 
@@ -110,11 +118,6 @@
   void RemoveFromOriginSet(const GURL& origin_url) {
     GetOriginSet()->erase(origin_url);
   }
-  bool IsInOriginSet(const GURL& origin_url) {
-    std::set<GURL>* set = GetOriginSet();
-    return set->find(origin_url) != set->end();
-  }
-
   // Only for testing.
   void ResetCaches();
 
@@ -135,4 +138,4 @@
 
 }  // namespace content
 
-#endif  // CONTENT_BROWSER_IN_PROCESS_WEBKIT_INDEXED_DB_CONTEXT_IMPL_H_
+#endif  // CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_CONTEXT_IMPL_H_
diff --git a/content/browser/indexed_db/indexed_db_internals_ui.cc b/content/browser/indexed_db/indexed_db_internals_ui.cc
new file mode 100644
index 0000000..4d6f04b
--- /dev/null
+++ b/content/browser/indexed_db/indexed_db_internals_ui.cc
@@ -0,0 +1,316 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/indexed_db/indexed_db_internals_ui.h"
+
+#include <algorithm>
+#include <string>
+
+#include "base/bind.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/memory/scoped_vector.h"
+#include "base/threading/platform_thread.h"
+#include "base/values.h"
+#include "content/browser/indexed_db/indexed_db_context_impl.h"
+#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/download_manager.h"
+#include "content/public/browser/download_url_parameters.h"
+#include "content/public/browser/storage_partition.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_ui.h"
+#include "content/public/browser/web_ui_data_source.h"
+#include "content/public/common/url_constants.h"
+#include "grit/content_resources.h"
+#include "third_party/WebKit/Source/Platform/chromium/public/WebString.h"
+#include "third_party/zlib/google/zip.h"
+#include "webkit/base/file_path_string_conversions.h"
+#include "webkit/database/database_util.h"
+
+using webkit_database::DatabaseUtil;
+
+namespace content {
+
+IndexedDBInternalsUI::IndexedDBInternalsUI(WebUI* web_ui)
+    : WebUIController(web_ui) {
+  web_ui->RegisterMessageCallback(
+      "getAllOrigins",
+      base::Bind(&IndexedDBInternalsUI::GetAllOrigins, base::Unretained(this)));
+
+  web_ui->RegisterMessageCallback(
+      "downloadOriginData",
+      base::Bind(&IndexedDBInternalsUI::DownloadOriginData,
+                 base::Unretained(this)));
+
+  WebUIDataSource* source =
+      WebUIDataSource::Create(kChromeUIIndexedDBInternalsHost);
+  source->SetUseJsonJSFormatV2();
+  source->SetJsonPath("strings.js");
+  source->AddResourcePath("indexeddb_internals.js",
+                          IDR_INDEXED_DB_INTERNALS_JS);
+  source->AddResourcePath("indexeddb_internals.css",
+                          IDR_INDEXED_DB_INTERNALS_CSS);
+  source->SetDefaultResource(IDR_INDEXED_DB_INTERNALS_HTML);
+
+  BrowserContext* browser_context =
+      web_ui->GetWebContents()->GetBrowserContext();
+  WebUIDataSource::Add(browser_context, source);
+}
+
+IndexedDBInternalsUI::~IndexedDBInternalsUI() {}
+
+void IndexedDBInternalsUI::AddContextFromStoragePartition(
+    ContextList* contexts,
+    std::vector<base::FilePath>* paths,
+    StoragePartition* partition) {
+  scoped_refptr<IndexedDBContext> context = partition->GetIndexedDBContext();
+  contexts->push_back(context);
+  paths->push_back(partition->GetPath());
+}
+
+void IndexedDBInternalsUI::GetAllOrigins(const base::ListValue* args) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+  BrowserContext* browser_context =
+      web_ui()->GetWebContents()->GetBrowserContext();
+
+  scoped_ptr<std::vector<base::FilePath> > paths(
+      new std::vector<base::FilePath>);
+  scoped_ptr<ContextList> contexts(new ContextList);
+  BrowserContext::StoragePartitionCallback cb =
+      base::Bind(&AddContextFromStoragePartition, contexts.get(), paths.get());
+  BrowserContext::ForEachStoragePartition(browser_context, cb);
+
+  BrowserThread::PostTask(
+      BrowserThread::WEBKIT_DEPRECATED,
+      FROM_HERE,
+      base::Bind(&IndexedDBInternalsUI::GetAllOriginsOnWebkitThread,
+                 base::Unretained(this),
+                 base::Passed(&contexts),
+                 base::Passed(&paths)));
+}
+
+bool HostNameComparator(const IndexedDBInfo& i, const IndexedDBInfo& j) {
+  return i.origin_.host() < j.origin_.host();
+}
+
+void IndexedDBInternalsUI::GetAllOriginsOnWebkitThread(
+    const scoped_ptr<ContextList> contexts,
+    const scoped_ptr<std::vector<base::FilePath> > context_paths) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT_DEPRECATED));
+  DCHECK_EQ(contexts->size(), context_paths->size());
+
+  std::vector<base::FilePath>::const_iterator path_iter =
+      context_paths->begin();
+  for (ContextList::const_iterator iter = contexts->begin();
+       iter != contexts->end();
+       ++iter, ++path_iter) {
+    IndexedDBContext* context = *iter;
+    const base::FilePath& context_path = *path_iter;
+
+    scoped_ptr<std::vector<IndexedDBInfo> > info_list(
+        new std::vector<IndexedDBInfo>(context->GetAllOriginsInfo()));
+    std::sort(info_list->begin(), info_list->end(), HostNameComparator);
+    BrowserThread::PostTask(BrowserThread::UI,
+                            FROM_HERE,
+                            base::Bind(&IndexedDBInternalsUI::OnOriginsReady,
+                                       base::Unretained(this),
+                                       base::Passed(&info_list),
+                                       context_path));
+  }
+}
+
+void IndexedDBInternalsUI::OnOriginsReady(
+    scoped_ptr<std::vector<IndexedDBInfo> > origins,
+    const base::FilePath& path) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  base::ListValue urls;
+  for (std::vector<IndexedDBInfo>::const_iterator iter = origins->begin();
+       iter != origins->end();
+       ++iter) {
+    base::DictionaryValue* info = new DictionaryValue;
+    info->SetString("url", iter->origin_.spec());
+    info->SetDouble("size", iter->size_);
+    info->SetDouble("last_modified", iter->last_modified_.ToJsTime());
+    info->SetString("path", iter->path_.value());
+    urls.Append(info);
+  }
+  web_ui()->CallJavascriptFunction(
+      "indexeddb.onOriginsReady", urls, base::StringValue(path.value()));
+}
+
+static void FindContext(const base::FilePath& partition_path,
+                        StoragePartition** result_partition,
+                        scoped_refptr<IndexedDBContextImpl>* result_context,
+                        StoragePartition* storage_partition) {
+  if (storage_partition->GetPath() == partition_path) {
+    *result_partition = storage_partition;
+    *result_context = static_cast<IndexedDBContextImpl*>(
+        storage_partition->GetIndexedDBContext());
+  }
+}
+
+void IndexedDBInternalsUI::DownloadOriginData(const base::ListValue* args) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+  base::FilePath::StringType path_string;
+  if (!args->GetString(0, &path_string))
+    return;
+  const base::FilePath partition_path(path_string);
+
+  std::string url_string;
+  if (!args->GetString(1, &url_string))
+    return;
+  const GURL origin_url(url_string);
+
+  // search the origins to find the right context
+
+  BrowserContext* browser_context =
+      web_ui()->GetWebContents()->GetBrowserContext();
+
+  scoped_refptr<IndexedDBContextImpl> result_context;
+  StoragePartition* result_partition;
+  scoped_ptr<ContextList> contexts(new ContextList);
+  BrowserContext::StoragePartitionCallback cb = base::Bind(
+      &FindContext, partition_path, &result_partition, &result_context);
+  BrowserContext::ForEachStoragePartition(browser_context, cb);
+  DCHECK(result_partition);
+  DCHECK(result_context);
+
+  BrowserThread::PostTask(
+      BrowserThread::WEBKIT_DEPRECATED,
+      FROM_HERE,
+      base::Bind(&IndexedDBInternalsUI::DownloadOriginDataOnWebkitThread,
+                 base::Unretained(this),
+                 result_partition->GetPath(),
+                 result_context,
+                 origin_url));
+}
+
+void IndexedDBInternalsUI::DownloadOriginDataOnWebkitThread(
+    const base::FilePath& partition_path,
+    const scoped_refptr<IndexedDBContextImpl> context,
+    const GURL& origin_url) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT_DEPRECATED));
+
+  if (!context->IsInOriginSet(origin_url))
+    return;
+
+  context->ForceClose(origin_url);
+
+  base::ScopedTempDir temp_dir;
+  if (!temp_dir.CreateUniqueTempDir())
+    return;
+
+  // This will get cleaned up on the File thread after the download
+  // has completed.
+  base::FilePath temp_path = temp_dir.Take();
+
+  base::string16 origin_id = DatabaseUtil::GetOriginIdentifier(origin_url);
+  base::FilePath::StringType zip_name =
+      webkit_base::WebStringToFilePathString(origin_id);
+  base::FilePath zip_path =
+      temp_path.Append(zip_name).AddExtension(FILE_PATH_LITERAL("zip"));
+
+  // This happens on the "webkit" thread (which is really just the IndexedDB
+  // thread) as a simple way to avoid another script reopening the origin
+  // while we are zipping.
+  zip::Zip(context->GetFilePath(origin_url), zip_path, true);
+
+  BrowserThread::PostTask(BrowserThread::UI,
+                          FROM_HERE,
+                          base::Bind(&IndexedDBInternalsUI::OnDownloadDataReady,
+                                     base::Unretained(this),
+                                     partition_path,
+                                     origin_url,
+                                     temp_path,
+                                     zip_path));
+}
+
+void IndexedDBInternalsUI::OnDownloadDataReady(
+    const base::FilePath& partition_path,
+    const GURL& origin_url,
+    const base::FilePath temp_path,
+    const base::FilePath zip_path) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  const GURL url = GURL(FILE_PATH_LITERAL("file://") + zip_path.value());
+  BrowserContext* browser_context =
+      web_ui()->GetWebContents()->GetBrowserContext();
+  scoped_ptr<DownloadUrlParameters> dl_params(
+      DownloadUrlParameters::FromWebContents(web_ui()->GetWebContents(), url));
+  DownloadManager* dlm = BrowserContext::GetDownloadManager(browser_context);
+
+  const GURL referrer(web_ui()->GetWebContents()->GetURL());
+  dl_params->set_referrer(
+      content::Referrer(referrer, WebKit::WebReferrerPolicyDefault));
+
+  // This is how to watch for the download to finish: first wait for it
+  // to start, then attach a DownloadItem::Observer to observe the
+  // state change to the finished state.
+  dl_params->set_callback(base::Bind(&IndexedDBInternalsUI::OnDownloadStarted,
+                                     base::Unretained(this),
+                                     partition_path,
+                                     origin_url,
+                                     temp_path));
+  dlm->DownloadUrl(dl_params.Pass());
+}
+
+// The entire purpose of this class is to delete the temp file after
+// the download is complete.
+class FileDeleter : public DownloadItem::Observer {
+ public:
+  explicit FileDeleter(const base::FilePath& temp_dir) : temp_dir_(temp_dir) {}
+  virtual ~FileDeleter();
+
+  virtual void OnDownloadUpdated(DownloadItem* download) OVERRIDE;
+  virtual void OnDownloadOpened(DownloadItem* item) OVERRIDE {}
+  virtual void OnDownloadRemoved(DownloadItem* item) OVERRIDE {}
+  virtual void OnDownloadDestroyed(DownloadItem* item) OVERRIDE {}
+
+ private:
+  const base::FilePath temp_dir_;
+};
+
+void FileDeleter::OnDownloadUpdated(DownloadItem* item) {
+  switch (item->GetState()) {
+    case DownloadItem::IN_PROGRESS:
+      break;
+    case DownloadItem::COMPLETE:
+    case DownloadItem::CANCELLED:
+    case DownloadItem::INTERRUPTED: {
+      item->RemoveObserver(this);
+      BrowserThread::DeleteOnFileThread::Destruct(this);
+      break;
+    }
+    default:
+      NOTREACHED();
+  }
+}
+
+FileDeleter::~FileDeleter() {
+  base::ScopedTempDir path;
+  bool will_delete ALLOW_UNUSED = path.Set(temp_dir_);
+  DCHECK(will_delete);
+}
+
+void IndexedDBInternalsUI::OnDownloadStarted(
+    const base::FilePath& partition_path,
+    const GURL& origin_url,
+    const base::FilePath& temp_path,
+    DownloadItem* item,
+    net::Error error) {
+
+  if (error != net::OK) {
+    LOG(ERROR) << "Error downloading database dump: "
+               << net::ErrorToString(error);
+    return;
+  }
+
+  item->AddObserver(new FileDeleter(temp_path));
+  web_ui()->CallJavascriptFunction("indexeddb.onOriginDownloadReady",
+                                   base::StringValue(partition_path.value()),
+                                   base::StringValue(origin_url.spec()));
+}
+
+}  // namespace content
diff --git a/content/browser/indexed_db/indexed_db_internals_ui.h b/content/browser/indexed_db/indexed_db_internals_ui.h
new file mode 100644
index 0000000..bc9a5da
--- /dev/null
+++ b/content/browser/indexed_db/indexed_db_internals_ui.h
@@ -0,0 +1,63 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_INTERNALS_UI_H_
+#define CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_INTERNALS_UI_H_
+
+#include <vector>
+
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "content/public/browser/indexed_db_context.h"
+#include "content/public/browser/web_ui_controller.h"
+#include "net/base/net_errors.h"
+
+namespace base { class ListValue; }
+
+namespace content {
+
+class DownloadItem;
+class IndexedDBContextImpl;
+class StoragePartition;
+
+// The implementation for the chrome://indexeddb-internals page.
+class IndexedDBInternalsUI : public WebUIController {
+ public:
+  explicit IndexedDBInternalsUI(WebUI* web_ui);
+  virtual ~IndexedDBInternalsUI();
+
+ private:
+  typedef std::vector<scoped_refptr<IndexedDBContext> > ContextList;
+  void GetAllOrigins(const base::ListValue* args);
+  void GetAllOriginsOnWebkitThread(
+      const scoped_ptr<ContextList> contexts,
+      const scoped_ptr<std::vector<base::FilePath> > context_paths);
+  void OnOriginsReady(scoped_ptr<std::vector<IndexedDBInfo> > origins,
+                      const base::FilePath& path);
+
+  static void AddContextFromStoragePartition(ContextList* contexts,
+                                             std::vector<base::FilePath>* paths,
+                                             StoragePartition* partition);
+
+  void DownloadOriginData(const base::ListValue* args);
+  void DownloadOriginDataOnWebkitThread(
+      const base::FilePath& partition_path,
+      const scoped_refptr<IndexedDBContextImpl> context,
+      const GURL& origin_url);
+  void OnDownloadDataReady(const base::FilePath& partition_path,
+                           const GURL& origin_url,
+                           const base::FilePath temp_path,
+                           const base::FilePath zip_path);
+  void OnDownloadStarted(const base::FilePath& partition_path,
+                         const GURL& origin_url,
+                         const base::FilePath& temp_path,
+                         content::DownloadItem* item,
+                         net::Error error);
+
+  DISALLOW_COPY_AND_ASSIGN(IndexedDBInternalsUI);
+};
+
+}  // namespace content
+
+#endif  // CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_INTERNALS_UI_H_
diff --git a/content/browser/in_process_webkit/indexed_db_layout_browsertest.cc b/content/browser/indexed_db/indexed_db_layout_browsertest.cc
similarity index 94%
rename from content/browser/in_process_webkit/indexed_db_layout_browsertest.cc
rename to content/browser/indexed_db/indexed_db_layout_browsertest.cc
index e54958d..9f8b83b 100644
--- a/content/browser/in_process_webkit/indexed_db_layout_browsertest.cc
+++ b/content/browser/indexed_db/indexed_db_layout_browsertest.cc
@@ -24,8 +24,7 @@
 static const char* kBasicTests[] = {
   "basics.html",
   "basics-shared-workers.html",
-  // Failing on Precise bot (crbug.com/145592).
-  // "basics-workers.html",
+  "basics-workers.html",
   "database-basics.html",
   "factory-basics.html",
   "index-basics.html",
@@ -35,8 +34,9 @@
 
 static const char* kComplexTests[] = {
   "prefetch-bugfix-108071.html",
-  // Flaky: http://crbug.com/123685
-  // "pending-version-change-stuck-works-with-terminate.html",
+  // Flaky: http://crbug.com/226256
+  //"pending-version-change-stuck.html",
+  "pending-version-change-stuck-works-with-terminate.html",
   "pending-version-change-on-exit.html",
   NULL
 };
@@ -44,6 +44,7 @@
 static const char* kIndexTests[] = {
   "deleteIndex.html",
   // Flaky: http://crbug.com/123685
+  // Flaky: http://crbug.com/127244
   // "index-basics-workers.html",
   "index-count.html",
   "index-cursor.html",
diff --git a/content/browser/in_process_webkit/indexed_db_quota_client.cc b/content/browser/indexed_db/indexed_db_quota_client.cc
similarity index 96%
rename from content/browser/in_process_webkit/indexed_db_quota_client.cc
rename to content/browser/indexed_db/indexed_db_quota_client.cc
index 3096c95..91b5af1 100644
--- a/content/browser/in_process_webkit/indexed_db_quota_client.cc
+++ b/content/browser/indexed_db/indexed_db_quota_client.cc
@@ -2,14 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "content/browser/in_process_webkit/indexed_db_quota_client.h"
+#include "content/browser/indexed_db/indexed_db_quota_client.h"
 
 #include <vector>
 
 #include "base/file_util.h"
 #include "base/logging.h"
 #include "base/message_loop_proxy.h"
-#include "content/browser/in_process_webkit/indexed_db_context_impl.h"
+#include "content/browser/indexed_db/indexed_db_context_impl.h"
 #include "content/public/browser/browser_thread.h"
 #include "net/base/net_util.h"
 #include "webkit/database/database_util.h"
diff --git a/content/browser/in_process_webkit/indexed_db_quota_client.h b/content/browser/indexed_db/indexed_db_quota_client.h
similarity index 91%
rename from content/browser/in_process_webkit/indexed_db_quota_client.h
rename to content/browser/indexed_db/indexed_db_quota_client.h
index bf37b95..a7db5a4 100644
--- a/content/browser/in_process_webkit/indexed_db_quota_client.h
+++ b/content/browser/indexed_db/indexed_db_quota_client.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CONTENT_BROWER_IN_PROCESS_WEBKIT_QUOTA_CLIENT_H_
-#define CONTENT_BROWER_IN_PROCESS_WEBKIT_QUOTA_CLIENT_H_
+#ifndef CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_QUOTA_CLIENT_H_
+#define CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_QUOTA_CLIENT_H_
 
 #include <set>
 #include <string>
@@ -53,4 +53,4 @@
 
 }  // namespace content
 
-#endif  // CONTENT_BROWER_IN_PROCESS_WEBKIT_QUOTA_CLIENT_H_
+#endif  // CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_QUOTA_CLIENT_H_
diff --git a/content/browser/in_process_webkit/indexed_db_quota_client_unittest.cc b/content/browser/indexed_db/indexed_db_quota_client_unittest.cc
similarity index 92%
rename from content/browser/in_process_webkit/indexed_db_quota_client_unittest.cc
rename to content/browser/indexed_db/indexed_db_quota_client_unittest.cc
index 197bfc8..ea0aa76 100644
--- a/content/browser/in_process_webkit/indexed_db_quota_client_unittest.cc
+++ b/content/browser/indexed_db/indexed_db_quota_client_unittest.cc
@@ -11,8 +11,8 @@
 #include "base/message_loop.h"
 #include "base/message_loop_proxy.h"
 #include "content/browser/browser_thread_impl.h"
-#include "content/browser/in_process_webkit/indexed_db_context_impl.h"
-#include "content/browser/in_process_webkit/indexed_db_quota_client.h"
+#include "content/browser/indexed_db/indexed_db_context_impl.h"
+#include "content/browser/indexed_db/indexed_db_quota_client.h"
 #include "content/public/browser/storage_partition.h"
 #include "content/public/test/test_browser_context.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -38,13 +38,13 @@
         kOriginB("http://host:8000"),
         kOriginOther("http://other"),
         usage_(0),
-        weak_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)),
-        message_loop_(MessageLoop::TYPE_IO),
+        weak_factory_(this),
+        message_loop_(base::MessageLoop::TYPE_IO),
         db_thread_(BrowserThread::DB, &message_loop_),
         webkit_thread_(BrowserThread::WEBKIT_DEPRECATED, &message_loop_),
         file_thread_(BrowserThread::FILE, &message_loop_),
-        file_user_blocking_thread_(
-            BrowserThread::FILE_USER_BLOCKING, &message_loop_),
+        file_user_blocking_thread_(BrowserThread::FILE_USER_BLOCKING,
+                                   &message_loop_),
         io_thread_(BrowserThread::IO, &message_loop_) {
     browser_context_.reset(new TestBrowserContext());
     idb_context_ = static_cast<IndexedDBContextImpl*>(
@@ -68,7 +68,7 @@
     // doesn't outlive BrowserThread::WEBKIT_DEPRECATED.
     idb_context_ = NULL;
     browser_context_.reset();
-    MessageLoop::current()->RunUntilIdle();
+    base::MessageLoop::current()->RunUntilIdle();
   }
 
   int64 GetOriginUsage(
@@ -80,7 +80,7 @@
         origin, type,
         base::Bind(&IndexedDBQuotaClientTest::OnGetOriginUsageComplete,
                    weak_factory_.GetWeakPtr()));
-    MessageLoop::current()->RunUntilIdle();
+    base::MessageLoop::current()->RunUntilIdle();
     EXPECT_GT(usage_, -1);
     return usage_;
   }
@@ -94,7 +94,7 @@
         type,
         base::Bind(&IndexedDBQuotaClientTest::OnGetOriginsComplete,
                    weak_factory_.GetWeakPtr()));
-    MessageLoop::current()->RunUntilIdle();
+    base::MessageLoop::current()->RunUntilIdle();
     return origins_;
   }
 
@@ -108,7 +108,7 @@
         type, host,
         base::Bind(&IndexedDBQuotaClientTest::OnGetOriginsComplete,
                    weak_factory_.GetWeakPtr()));
-    MessageLoop::current()->RunUntilIdle();
+    base::MessageLoop::current()->RunUntilIdle();
     return origins_;
   }
 
@@ -119,7 +119,7 @@
         origin_url, kTemp,
         base::Bind(&IndexedDBQuotaClientTest::OnDeleteOriginComplete,
                    weak_factory_.GetWeakPtr()));
-    MessageLoop::current()->RunUntilIdle();
+    base::MessageLoop::current()->RunUntilIdle();
     return delete_status_;
   }
 
@@ -163,7 +163,7 @@
   quota::StorageType type_;
   scoped_refptr<IndexedDBContextImpl> idb_context_;
   base::WeakPtrFactory<IndexedDBQuotaClientTest> weak_factory_;
-  MessageLoop message_loop_;
+  base::MessageLoop message_loop_;
   BrowserThreadImpl db_thread_;
   BrowserThreadImpl webkit_thread_;
   BrowserThreadImpl file_thread_;
diff --git a/content/browser/in_process_webkit/indexed_db_unittest.cc b/content/browser/indexed_db/indexed_db_unittest.cc
similarity index 95%
rename from content/browser/in_process_webkit/indexed_db_unittest.cc
rename to content/browser/indexed_db/indexed_db_unittest.cc
index 13334fe..869049d 100644
--- a/content/browser/in_process_webkit/indexed_db_unittest.cc
+++ b/content/browser/indexed_db/indexed_db_unittest.cc
@@ -5,12 +5,12 @@
 #include "base/file_util.h"
 #include "base/files/scoped_temp_dir.h"
 #include "content/browser/browser_thread_impl.h"
-#include "content/browser/in_process_webkit/indexed_db_context_impl.h"
+#include "content/browser/indexed_db/indexed_db_context_impl.h"
 #include "content/public/browser/storage_partition.h"
 #include "content/public/common/url_constants.h"
 #include "content/public/test/test_browser_context.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/WebKit/Source/WebKit/chromium/public/WebIDBDatabase.h"
+#include "third_party/WebKit/Source/Platform/chromium/public/WebIDBDatabase.h"
 #include "webkit/database/database_util.h"
 #include "webkit/quota/mock_special_storage_policy.h"
 #include "webkit/quota/quota_manager.h"
@@ -23,14 +23,13 @@
 class IndexedDBTest : public testing::Test {
  public:
   IndexedDBTest()
-      : message_loop_(MessageLoop::TYPE_IO),
+      : message_loop_(base::MessageLoop::TYPE_IO),
         webkit_thread_(BrowserThread::WEBKIT_DEPRECATED, &message_loop_),
         file_thread_(BrowserThread::FILE_USER_BLOCKING, &message_loop_),
-        io_thread_(BrowserThread::IO, &message_loop_) {
-  }
+        io_thread_(BrowserThread::IO, &message_loop_) {}
 
  protected:
-  MessageLoop message_loop_;
+  base::MessageLoop message_loop_;
 
  private:
   BrowserThreadImpl webkit_thread_;
diff --git a/content/browser/loader/buffered_resource_handler.cc b/content/browser/loader/buffered_resource_handler.cc
index b942bb4..c41c911 100644
--- a/content/browser/loader/buffered_resource_handler.cc
+++ b/content/browser/loader/buffered_resource_handler.cc
@@ -201,7 +201,7 @@
       NOTREACHED();
       break;
     case STATE_REPLAYING:
-      MessageLoop::current()->PostTask(
+      base::MessageLoop::current()->PostTask(
           FROM_HERE,
           base::Bind(&BufferedResourceHandler::CallReplayReadCompleted,
                      weak_ptr_factory_.GetWeakPtr()));
diff --git a/content/browser/loader/global_routing_id.h b/content/browser/loader/global_routing_id.h
new file mode 100644
index 0000000..4715c5a
--- /dev/null
+++ b/content/browser/loader/global_routing_id.h
@@ -0,0 +1,42 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_PUBLIC_BROWSER_GLOBAL_ROUTING_ID_H_
+#define CONTENT_PUBLIC_BROWSER_GLOBAL_ROUTING_ID_H_
+
+namespace content {
+
+// Uniquely identifies the route from which a net::URLRequest comes.
+struct GlobalRoutingID {
+  GlobalRoutingID() : child_id(-1), route_id(-1) {
+  }
+
+  GlobalRoutingID(int child_id, int route_id)
+      : child_id(child_id),
+        route_id(route_id) {
+  }
+
+  // The unique ID of the child process (different from OS's PID).
+  int child_id;
+
+  // The route ID (unique for each URLRequest source).
+  int route_id;
+
+  bool operator<(const GlobalRoutingID& other) const {
+    if (child_id == other.child_id)
+      return route_id < other.route_id;
+    return child_id < other.child_id;
+  }
+  bool operator==(const GlobalRoutingID& other) const {
+    return child_id == other.child_id &&
+        route_id == other.route_id;
+  }
+  bool operator!=(const GlobalRoutingID& other) const {
+    return !(*this == other);
+  }
+};
+
+}  // namespace content
+
+#endif  // CONTENT_PUBLIC_BROWSER_GLOBAL_ROUTING_ID_H_
diff --git a/content/browser/loader/offline_policy.cc b/content/browser/loader/offline_policy.cc
new file mode 100644
index 0000000..9c9361f
--- /dev/null
+++ b/content/browser/loader/offline_policy.cc
@@ -0,0 +1,96 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/loader/offline_policy.h"
+
+#include "base/command_line.h"
+#include "base/metrics/histogram.h"
+#include "content/public/common/content_switches.h"
+#include "net/base/load_flags.h"
+#include "net/http/http_response_info.h"
+#include "net/url_request/url_request.h"
+
+namespace content {
+
+OfflinePolicy::OfflinePolicy()
+    : enabled_(CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kEnableOfflineCacheAccess)),
+      state_(INIT),
+      resource_loads_initiated_(0),
+      resource_loads_successfully_started_(0) {}
+
+OfflinePolicy::~OfflinePolicy() {
+  RecordAndResetStats();
+}
+
+void OfflinePolicy::RecordAndResetStats() {
+  if (enabled_ && OFFLINE == state_ && 0 != resource_loads_initiated_) {
+    UMA_HISTOGRAM_PERCENTAGE(
+        "OfflinePolicy.SuccessfulResourceLoadPercentage",
+        (resource_loads_successfully_started_ * 100 /
+         resource_loads_initiated_));
+  }
+  resource_loads_initiated_ = 0;
+  resource_loads_successfully_started_ = 0;
+}
+
+int OfflinePolicy::GetAdditionalLoadFlags(int current_flags,
+                                          bool reset_state) {
+  // Don't do anything if offline mode is disabled.
+  if (!enabled_)
+    return 0;
+
+  if (reset_state) {
+    RecordAndResetStats();
+    state_ = INIT;
+  }
+
+  ++resource_loads_initiated_;
+
+  // If a consumer has requested something contradictory, it wins; we
+  // don't modify the load flags.
+  if (current_flags &
+      (net::LOAD_BYPASS_CACHE | net::LOAD_PREFERRING_CACHE |
+       net::LOAD_ONLY_FROM_CACHE | net::LOAD_FROM_CACHE_IF_OFFLINE |
+       net::LOAD_DISABLE_CACHE)) {
+    return 0;
+  }
+
+  switch(state_) {
+    case INIT:
+      return net::LOAD_FROM_CACHE_IF_OFFLINE;
+    case ONLINE:
+      return 0;
+    case OFFLINE:
+      return net::LOAD_ONLY_FROM_CACHE;
+  }
+  NOTREACHED();
+  return 0;
+}
+
+void OfflinePolicy::UpdateStateForSuccessfullyStartedRequest(
+    const net::HttpResponseInfo& response_info) {
+  // Don't do anything if offline mode is disabled.
+  if (!enabled_)
+    return;
+
+  // If we get here, we're going to be providing some amount of information
+  // to the renderer.
+  ++resource_loads_successfully_started_;
+
+  if (state_ != INIT)
+    // We've already made the decision for the rest of this set
+    // of navigations.
+    return;
+
+  if (response_info.server_data_unavailable) {
+    state_ = OFFLINE;
+  } else if (response_info.network_accessed) {
+    // If we got the response from the network or validated it as part
+    // of this request, that means our connection to the host is working.
+    state_ = ONLINE;
+  }
+}
+
+}  // namespace content
diff --git a/content/browser/loader/offline_policy.h b/content/browser/loader/offline_policy.h
new file mode 100644
index 0000000..975d4ad
--- /dev/null
+++ b/content/browser/loader/offline_policy.h
@@ -0,0 +1,60 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_LOADER_OFFLINE_POLICY
+#define CONTENT_BROWSER_LOADER_OFFLINE_POLICY
+
+#include <map>
+
+#include "base/basictypes.h"
+#include "content/common/content_export.h"
+
+struct ResourceHostMsg_Request;
+
+namespace net {
+class HttpResponseInfo;
+class URLRequest;
+}
+
+namespace content {
+
+// This class controls under what conditions resources will be fetched
+// from cache even if stale rather than from the network.  For example,
+// one policy would be that if requests for a particular route (e.g. "tab")
+// is unable to reach the server, other requests made with the same route
+// can be loaded from cache without first requiring a network timeout.
+//
+// There is a single OfflinePolicy object per user navigation unit
+// (generally a tab).
+class CONTENT_EXPORT OfflinePolicy {
+ public:
+  OfflinePolicy();
+  ~OfflinePolicy();
+
+  // Return any additional load flags to be ORed for a request from
+  // this route with the given |resource_type|.  |reset_state| indicates
+  // that this request should reinitialized the internal state for this
+  // policy object (e.g. in the case of a main frame load).
+  int GetAdditionalLoadFlags(int current_flags, bool reset_state);
+
+  // Incorporate online/offline information from a successfully started request.
+  void UpdateStateForSuccessfullyStartedRequest(
+      const net::HttpResponseInfo& response_info);
+
+private:
+  enum State { INIT, ONLINE, OFFLINE };
+
+  void RecordAndResetStats();
+
+  bool enabled_;
+  State state_;
+  int resource_loads_initiated_;
+  int resource_loads_successfully_started_;
+
+  DISALLOW_COPY_AND_ASSIGN(OfflinePolicy);
+};
+
+}  // namespace content
+
+#endif  // CONTENT_BROWSER_LOADER_OFFLINE_POLICY
diff --git a/content/browser/loader/offline_policy_unittest.cc b/content/browser/loader/offline_policy_unittest.cc
new file mode 100644
index 0000000..18c09df
--- /dev/null
+++ b/content/browser/loader/offline_policy_unittest.cc
@@ -0,0 +1,96 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/loader/offline_policy.h"
+
+#include "base/command_line.h"
+#include "content/public/common/content_switches.h"
+#include "net/base/load_flags.h"
+#include "net/http/http_response_info.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "webkit/glue/resource_type.h"
+
+namespace content {
+
+class OfflinePolicyTest : public testing::Test {
+ protected:
+  virtual void SetUp() {
+    CommandLine::ForCurrentProcess()->AppendSwitch(
+        switches::kEnableOfflineCacheAccess);
+    policy_ = new OfflinePolicy;
+  }
+
+  virtual void TearDown() {
+    delete policy_;
+    policy_ = NULL;
+  }
+
+  OfflinePolicy* policy_;
+};
+
+// Confirm that the initial state of an offline object is to return
+// LOAD_FROM_CACHE_IF_OFFLINE until it gets changed.
+TEST_F(OfflinePolicyTest, InitialState) {
+  // Two loads without any reset, no UpdateStateForSuccessfullyStartedRequest.
+  EXPECT_EQ(net::LOAD_FROM_CACHE_IF_OFFLINE,
+            policy_->GetAdditionalLoadFlags(0, true));
+  EXPECT_EQ(net::LOAD_FROM_CACHE_IF_OFFLINE,
+            policy_->GetAdditionalLoadFlags(0, false));
+}
+
+// Completion without any network probing doesn't change result value.
+TEST_F(OfflinePolicyTest, CompletedUncertain) {
+  EXPECT_EQ(net::LOAD_FROM_CACHE_IF_OFFLINE,
+            policy_->GetAdditionalLoadFlags(0, true));
+  net::HttpResponseInfo response_info;
+  policy_->UpdateStateForSuccessfullyStartedRequest(response_info);
+  EXPECT_EQ(net::LOAD_FROM_CACHE_IF_OFFLINE,
+            policy_->GetAdditionalLoadFlags(0, false));
+}
+
+// Completion with a failed network probe changes result value.
+TEST_F(OfflinePolicyTest, CompletedNoNetwork) {
+  EXPECT_EQ(net::LOAD_FROM_CACHE_IF_OFFLINE,
+            policy_->GetAdditionalLoadFlags(0, true));
+  net::HttpResponseInfo response_info;
+  response_info.server_data_unavailable = true;
+  policy_->UpdateStateForSuccessfullyStartedRequest(response_info);
+  EXPECT_EQ(net::LOAD_ONLY_FROM_CACHE,
+            policy_->GetAdditionalLoadFlags(0, false));
+}
+
+// Completion with a successful network probe changes result value.
+TEST_F(OfflinePolicyTest, CompletedNetwork) {
+  EXPECT_EQ(net::LOAD_FROM_CACHE_IF_OFFLINE,
+            policy_->GetAdditionalLoadFlags(0, true));
+  net::HttpResponseInfo response_info;
+  response_info.network_accessed = true;
+  policy_->UpdateStateForSuccessfullyStartedRequest(response_info);
+  EXPECT_EQ(0, policy_->GetAdditionalLoadFlags(0, false));
+}
+
+// A new navigation resets a state change.
+TEST_F(OfflinePolicyTest, NewNavigationReset) {
+  EXPECT_EQ(net::LOAD_FROM_CACHE_IF_OFFLINE,
+            policy_->GetAdditionalLoadFlags(0, true));
+  net::HttpResponseInfo response_info;
+  response_info.network_accessed = true;
+  policy_->UpdateStateForSuccessfullyStartedRequest(response_info);
+  EXPECT_EQ(0, policy_->GetAdditionalLoadFlags(0, false));
+  EXPECT_EQ(net::LOAD_FROM_CACHE_IF_OFFLINE,
+            policy_->GetAdditionalLoadFlags(0, true));
+  EXPECT_EQ(net::LOAD_FROM_CACHE_IF_OFFLINE,
+            policy_->GetAdditionalLoadFlags(0, false));
+}
+
+// Cache related flags inhibit the returning of any special flags.
+TEST_F(OfflinePolicyTest, ConsumerFlagOverride) {
+  EXPECT_EQ(0, policy_->GetAdditionalLoadFlags(net::LOAD_BYPASS_CACHE, true));
+  net::HttpResponseInfo response_info;
+  response_info.server_data_unavailable = true;
+  policy_->UpdateStateForSuccessfullyStartedRequest(response_info);
+  EXPECT_EQ(0, policy_->GetAdditionalLoadFlags(net::LOAD_BYPASS_CACHE, false));
+}
+
+}
diff --git a/content/browser/loader/redirect_to_file_resource_handler.cc b/content/browser/loader/redirect_to_file_resource_handler.cc
index f3f81dd..4ab04ea 100644
--- a/content/browser/loader/redirect_to_file_resource_handler.cc
+++ b/content/browser/loader/redirect_to_file_resource_handler.cc
@@ -58,7 +58,7 @@
     int process_id,
     ResourceDispatcherHostImpl* host)
     : LayeredResourceHandler(next_handler.Pass()),
-      ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)),
+      weak_factory_(this),
       host_(host),
       process_id_(process_id),
       request_id_(-1),
diff --git a/content/browser/loader/render_view_host_tracker.cc b/content/browser/loader/render_view_host_tracker.cc
index 89a771b..2f006e8 100644
--- a/content/browser/loader/render_view_host_tracker.cc
+++ b/content/browser/loader/render_view_host_tracker.cc
@@ -9,44 +9,36 @@
 #include "content/browser/loader/resource_dispatcher_host_impl.h"
 #include "content/browser/loader/resource_scheduler.h"
 #include "content/public/browser/browser_thread.h"
-#include "content/public/browser/notification_service.h"
-#include "content/public/browser/notification_types.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/render_view_host.h"
 
 namespace content {
 
-RenderViewHostTracker::RenderViewHostTracker() {
+RenderViewHostTracker::RenderViewHostTracker()
+    : rvh_created_callback_(
+          base::Bind(&RenderViewHostTracker::RenderViewHostCreated,
+                     base::Unretained(this))) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  registrar_.Add(this, NOTIFICATION_RENDER_VIEW_HOST_CREATED,
-                 NotificationService::AllSources());
+  RenderViewHost::AddCreatedCallback(rvh_created_callback_);
 }
 
 RenderViewHostTracker::~RenderViewHostTracker() {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   DCHECK(observers_.empty());
+  RenderViewHost::RemoveCreatedCallback(rvh_created_callback_);
 }
 
-void RenderViewHostTracker::Observe(
-    int type,
-    const NotificationSource& source,
-    const NotificationDetails& details) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  RenderViewHost* rvh = content::Source<RenderViewHost>(source).ptr();
+void RenderViewHostTracker::RenderViewHostCreated(RenderViewHost* rvh) {
+  Observer* observer = new Observer(rvh, this);
+  observers_.insert(observer);
+
   int child_id = rvh->GetProcess()->GetID();
   int route_id = rvh->GetRoutingID();
-
-  switch (type) {
-    case NOTIFICATION_RENDER_VIEW_HOST_CREATED:
-      Observer* observer = new Observer(rvh, this);
-      observers_.insert(observer);
-      BrowserThread::PostTask(
-          BrowserThread::IO, FROM_HERE,
-          base::Bind(&ResourceDispatcherHostImpl::OnRenderViewHostCreated,
-                     base::Unretained(ResourceDispatcherHostImpl::Get()),
-                     child_id, route_id));
-      break;
-  }
+  BrowserThread::PostTask(
+      BrowserThread::IO, FROM_HERE,
+      base::Bind(&ResourceDispatcherHostImpl::OnRenderViewHostCreated,
+                 base::Unretained(ResourceDispatcherHostImpl::Get()),
+                 child_id, route_id));
 }
 
 void RenderViewHostTracker::RemoveObserver(Observer* observer) {
diff --git a/content/browser/loader/render_view_host_tracker.h b/content/browser/loader/render_view_host_tracker.h
index bab36de..7fc5fa0 100644
--- a/content/browser/loader/render_view_host_tracker.h
+++ b/content/browser/loader/render_view_host_tracker.h
@@ -7,8 +7,7 @@
 
 #include <set>
 
-#include "content/public/browser/notification_observer.h"
-#include "content/public/browser/notification_registrar.h"
+#include "content/public/browser/render_view_host.h"
 #include "content/public/browser/render_view_host_observer.h"
 
 namespace content {
@@ -18,12 +17,13 @@
 // operates on the IO thread. RenderViewHostTracker listens for renderer
 // notifications on the UI thread, then bounces them over to the IO thread so
 // the ResourceDispatcherHost can be notified.
-class CONTENT_EXPORT RenderViewHostTracker : public NotificationObserver {
+class CONTENT_EXPORT RenderViewHostTracker {
  public:
   RenderViewHostTracker();
   virtual ~RenderViewHostTracker();
 
  private:
+  // TODO(phajdan.jr): Move this declaration of inner class to the .cc file.
   class Observer : public RenderViewHostObserver {
    public:
     Observer(RenderViewHost* rvh,
@@ -40,14 +40,11 @@
   friend class Observer;
   typedef std::set<Observer*> ObserverSet;
 
-  // NotificationObserver interface:
-  virtual void Observe(int type,
-                       const NotificationSource& source,
-                       const NotificationDetails& details) OVERRIDE;
+  void RenderViewHostCreated(RenderViewHost* rvh);
 
   void RemoveObserver(Observer* observer);
 
-  content::NotificationRegistrar registrar_;
+  RenderViewHost::CreatedCallback rvh_created_callback_;
   ObserverSet observers_;
 };
 
diff --git a/content/browser/loader/resource_dispatcher_host_browsertest.cc b/content/browser/loader/resource_dispatcher_host_browsertest.cc
index 282fecc..68aded9 100644
--- a/content/browser/loader/resource_dispatcher_host_browsertest.cc
+++ b/content/browser/loader/resource_dispatcher_host_browsertest.cc
@@ -20,7 +20,7 @@
 #include "content/test/net/url_request_failed_job.h"
 #include "content/test/net/url_request_mock_http_job.h"
 #include "net/base/net_errors.h"
-#include "net/test/test_server.h"
+#include "net/test/spawned_test_server.h"
 
 namespace content {
 
diff --git a/content/browser/loader/resource_dispatcher_host_impl.cc b/content/browser/loader/resource_dispatcher_host_impl.cc
index 3849313..5b1a4db 100644
--- a/content/browser/loader/resource_dispatcher_host_impl.cc
+++ b/content/browser/loader/resource_dispatcher_host_impl.cc
@@ -18,6 +18,7 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/message_loop.h"
 #include "base/metrics/histogram.h"
+#include "base/metrics/sparse_histogram.h"
 #include "base/shared_memory.h"
 #include "base/stl_util.h"
 #include "base/third_party/dynamic_annotations/dynamic_annotations.h"
@@ -67,7 +68,7 @@
 #include "ipc/ipc_message_macros.h"
 #include "ipc/ipc_message_start.h"
 #include "net/base/auth.h"
-#include "net/base/cert_status_flags.h"
+#include "net/cert/cert_status_flags.h"
 #include "net/base/load_flags.h"
 #include "net/base/mime_util.h"
 #include "net/base/net_errors.h"
@@ -231,8 +232,10 @@
   return net_error;
 }
 
-int BuildLoadFlagsForRequest(const ResourceHostMsg_Request& request_data,
-                             int child_id, bool is_sync_load) {
+int BuildLoadFlagsForRequest(
+    const ResourceHostMsg_Request& request_data,
+    int child_id,
+    bool is_sync_load) {
   int load_flags = request_data.load_flags;
 
   // Although EV status is irrelevant to sub-frames and sub-resources, we have
@@ -414,11 +417,13 @@
   for (LoaderList::iterator i = loaders_to_cancel.begin();
        i != loaders_to_cancel.end(); ++i) {
     // There is no strict requirement that this be the case, but currently
-    // downloads and transferred requests are the only requests that aren't
-    // cancelled when the associated processes go away. It may be OK for this
-    // invariant to change in the future, but if this assertion fires without
-    // the invariant changing, then it's indicative of a leak.
-    DCHECK((*i)->GetRequestInfo()->is_download() || (*i)->is_transferring());
+    // downloads, streams  and transferred requests are the only requests that
+    // aren't cancelled when the associated processes go away. It may be OK for
+    // this invariant to change in the future, but if this assertion fires
+    // without the invariant changing, then it's indicative of a leak.
+    DCHECK((*i)->GetRequestInfo()->is_download() ||
+           (*i)->GetRequestInfo()->is_stream() ||
+           (*i)->is_transferring());
   }
 #endif
 
@@ -463,7 +468,7 @@
   base::debug::Alias(url_buf);
   CHECK(ContainsKey(active_resource_contexts_, context));
 
-  request->set_referrer(MaybeStripReferrer(GURL(request->referrer())).spec());
+  request->SetReferrer(MaybeStripReferrer(GURL(request->referrer())).spec());
   int extra_load_flags = net::LOAD_IS_DOWNLOAD;
   if (prefer_cache) {
     // If there is upload data attached, only retrieve from cache because there
@@ -478,6 +483,13 @@
     extra_load_flags |= net::LOAD_DISABLE_CACHE;
   }
   request->set_load_flags(request->load_flags() | extra_load_flags);
+
+  // No need to get offline load flags for downloads, but make sure
+  // we have an OfflinePolicy to receive request completions.
+  GlobalRoutingID id(child_id, route_id);
+  if (!offline_policy_map_[id])
+    offline_policy_map_[id] = new OfflinePolicy();
+
   // Check if the renderer is permitted to request the requested URL.
   if (!ChildProcessSecurityPolicyImpl::GetInstance()->
           CanRequestURL(child_id, url)) {
@@ -700,6 +712,12 @@
 
 void ResourceDispatcherHostImpl::DidReceiveResponse(ResourceLoader* loader) {
   ResourceRequestInfoImpl* info = loader->GetRequestInfo();
+  // There should be an entry in the map created when we dispatched the
+  // request.
+  GlobalRoutingID routing_id(info->GetGlobalRoutingID());
+  DCHECK(offline_policy_map_.end() != offline_policy_map_.find(routing_id));
+  offline_policy_map_[routing_id]->UpdateStateForSuccessfullyStartedRequest(
+      loader->request()->response_info());
 
   int render_process_id, render_view_id;
   if (!info->GetAssociatedRenderView(&render_process_id, &render_view_id))
@@ -724,27 +742,26 @@
   if (info->GetResourceType() == ResourceType::MAIN_FRAME) {
     // This enumeration has "3" appended to its name to distinguish it from
     // older versions.
-    UMA_HISTOGRAM_CUSTOM_ENUMERATION(
+    UMA_HISTOGRAM_SPARSE_SLOWLY(
         "Net.ErrorCodesForMainFrame3",
-        -loader->request()->status().error(),
-        base::CustomHistogram::ArrayToCustomRanges(
-            kAllNetErrorCodes, arraysize(kAllNetErrorCodes)));
+        -loader->request()->status().error());
 
     if (loader->request()->url().SchemeIsSecure() &&
         loader->request()->url().host() == "www.google.com") {
-      UMA_HISTOGRAM_CUSTOM_ENUMERATION(
+      UMA_HISTOGRAM_SPARSE_SLOWLY(
           "Net.ErrorCodesForHTTPSGoogleMainFrame2",
-          -loader->request()->status().error(),
-          base::CustomHistogram::ArrayToCustomRanges(
-              kAllNetErrorCodes, arraysize(kAllNetErrorCodes)));
+          -loader->request()->status().error());
     }
   } else {
+    if (info->GetResourceType() == ResourceType::IMAGE) {
+      UMA_HISTOGRAM_SPARSE_SLOWLY(
+          "Net.ErrorCodesForImages",
+          -loader->request()->status().error());
+    }
     // This enumeration has "2" appended to distinguish it from older versions.
-    UMA_HISTOGRAM_CUSTOM_ENUMERATION(
+    UMA_HISTOGRAM_SPARSE_SLOWLY(
         "Net.ErrorCodesForSubresources2",
-        -loader->request()->status().error(),
-        base::CustomHistogram::ArrayToCustomRanges(
-            kAllNetErrorCodes, arraysize(kAllNetErrorCodes)));
+        -loader->request()->status().error());
   }
 
   // Destroy the ResourceLoader.
@@ -787,17 +804,17 @@
   // Note that we have to do this in 2 passes as we cannot call
   // CancelBlockedRequestsForRoute while iterating over
   // blocked_loaders_map_, as it modifies it.
-  std::set<ProcessRouteIDs> ids;
+  std::set<GlobalRoutingID> ids;
   for (BlockedLoadersMap::const_iterator iter = blocked_loaders_map_.begin();
        iter != blocked_loaders_map_.end(); ++iter) {
-    std::pair<std::set<ProcessRouteIDs>::iterator, bool> result =
+    std::pair<std::set<GlobalRoutingID>::iterator, bool> result =
         ids.insert(iter->first);
     // We should not have duplicates.
     DCHECK(result.second);
   }
-  for (std::set<ProcessRouteIDs>::const_iterator iter = ids.begin();
+  for (std::set<GlobalRoutingID>::const_iterator iter = ids.begin();
        iter != ids.end(); ++iter) {
-    CancelBlockedRequestsForRoute(iter->first, iter->second);
+    CancelBlockedRequestsForRoute(iter->child_id, iter->route_id);
   }
 
   scheduler_.reset();
@@ -934,6 +951,12 @@
   int load_flags =
       BuildLoadFlagsForRequest(request_data, child_id, is_sync_load);
 
+  GlobalRoutingID id(child_id, route_id);
+  if (!offline_policy_map_[id])
+    offline_policy_map_[id] = new OfflinePolicy();
+  load_flags |= offline_policy_map_[id]->GetAdditionalLoadFlags(
+      load_flags, request_data.resource_type == ResourceType::MAIN_FRAME);
+
   // Construct the request.
   scoped_ptr<net::URLRequest> new_request;
   net::URLRequest* request;
@@ -951,7 +974,7 @@
 
     request->set_method(request_data.method);
     request->set_first_party_for_cookies(request_data.first_party_for_cookies);
-    request->set_referrer(referrer.url.spec());
+    request->SetReferrer(referrer.url.spec());
     webkit_glue::ConfigureURLRequestForReferrerPolicy(request,
                                                       referrer.policy);
     net::HttpRequestHeaders headers;
@@ -1267,13 +1290,19 @@
   scoped_ptr<net::URLRequest> request(
       request_context->CreateRequest(url, NULL));
   request->set_method("GET");
-  request->set_referrer(MaybeStripReferrer(referrer.url).spec());
+  request->SetReferrer(MaybeStripReferrer(referrer.url).spec());
   webkit_glue::ConfigureURLRequestForReferrerPolicy(request.get(),
                                                     referrer.policy);
   // So far, for saving page, we need fetch content from cache, in the
   // future, maybe we can use a configuration to configure this behavior.
   request->set_load_flags(net::LOAD_PREFERRING_CACHE);
 
+  // No need to get offline load flags for save files, but make sure
+  // we have an OfflinePolicy to receive request completions.
+  GlobalRoutingID id(child_id, route_id);
+  if (!offline_policy_map_[id])
+    offline_policy_map_[id] = new OfflinePolicy();
+
   // Since we're just saving some resources we need, disallow downloading.
   ResourceRequestInfoImpl* extra_info =
       CreateRequestInfo(child_id, route_id, false, context);
@@ -1324,7 +1353,8 @@
 
     // Don't cancel navigations that are transferring to another process,
     // since they belong to another process now.
-    if (!info->is_download() && !IsTransferredNavigation(id) &&
+    if (!info->is_download() && !info->is_stream() &&
+        !IsTransferredNavigation(id) &&
         (route_id == -1 || route_id == info->GetRouteID())) {
       matching_requests.push_back(id);
     }
@@ -1348,7 +1378,7 @@
 
   // Now deal with blocked requests if any.
   if (route_id != -1) {
-    if (blocked_loaders_map_.find(ProcessRouteIDs(child_id, route_id)) !=
+    if (blocked_loaders_map_.find(GlobalRoutingID(child_id, route_id)) !=
         blocked_loaders_map_.end()) {
       CancelBlockedRequestsForRoute(child_id, route_id);
     }
@@ -1360,14 +1390,35 @@
     std::set<int> route_ids;
     for (BlockedLoadersMap::const_iterator iter = blocked_loaders_map_.begin();
          iter != blocked_loaders_map_.end(); ++iter) {
-      if (iter->first.first == child_id)
-        route_ids.insert(iter->first.second);
+      if (iter->first.child_id == child_id)
+        route_ids.insert(iter->first.route_id);
     }
     for (std::set<int>::const_iterator iter = route_ids.begin();
         iter != route_ids.end(); ++iter) {
       CancelBlockedRequestsForRoute(child_id, *iter);
     }
   }
+
+  // Cleanup the offline state for the route.
+  if (-1 != route_id) {
+    OfflineMap::iterator it = offline_policy_map_.find(
+        GlobalRoutingID(child_id, route_id));
+    if (offline_policy_map_.end() != it) {
+      delete it->second;
+      offline_policy_map_.erase(it);
+    }
+  } else {
+    for (OfflineMap::iterator it = offline_policy_map_.begin();
+         offline_policy_map_.end() != it;) {
+      // Increment iterator so deletion doesn't invalidate it.
+      OfflineMap::iterator current_it = it++;
+
+      if (child_id == current_it->first.child_id) {
+        delete current_it->second;
+        offline_policy_map_.erase(current_it);
+      }
+    }
+  }
 }
 
 // Cancels the request and removes it from the list.
@@ -1394,7 +1445,7 @@
   pending_loaders_.erase(iter);
 
   // If we have no more pending requests, then stop the load state monitor
-  if (pending_loaders_.empty() && update_load_states_timer_.get())
+  if (pending_loaders_.empty() && update_load_states_timer_)
     update_load_states_timer_->Stop();
 }
 
@@ -1499,8 +1550,8 @@
   linked_ptr<ResourceLoader> loader(
       new ResourceLoader(request.Pass(), handler.Pass(), this));
 
-  ProcessRouteIDs pair_id(info->GetChildID(), info->GetRouteID());
-  BlockedLoadersMap::const_iterator iter = blocked_loaders_map_.find(pair_id);
+  GlobalRoutingID id(info->GetGlobalRoutingID());
+  BlockedLoadersMap::const_iterator iter = blocked_loaders_map_.find(id);
   if (iter != blocked_loaders_map_.end()) {
     // The request should be blocked.
     iter->second->push_back(loader);
@@ -1562,8 +1613,8 @@
   uint64 upload_size;
 };
 
-// Map from ProcessID+ViewID pair to LoadState
-typedef std::map<std::pair<int, int>, LoadInfo> LoadInfoMap;
+// Map from ProcessID+RouteID pair to LoadState
+typedef std::map<GlobalRoutingID, LoadInfo> LoadInfoMap;
 
 // Used to marshal calls to LoadStateChanged from the IO to UI threads.  We do
 // them all as a single callback to avoid spamming the UI thread.
@@ -1571,7 +1622,7 @@
   LoadInfoMap::const_iterator i;
   for (i = info_map.begin(); i != info_map.end(); ++i) {
     RenderViewHostImpl* view =
-        RenderViewHostImpl::FromID(i->first.first, i->first.second);
+        RenderViewHostImpl::FromID(i->first.child_id, i->first.route_id);
     if (view)  // The view could be gone at this point.
       view->LoadStateChanged(i->second.url, i->second.load_state,
                              i->second.upload_position,
@@ -1590,16 +1641,16 @@
 
   // Determine the largest upload size of all requests
   // in each View (good chance it's zero).
-  std::map<std::pair<int, int>, uint64> largest_upload_size;
+  std::map<GlobalRoutingID, uint64> largest_upload_size;
   for (i = pending_loaders_.begin(); i != pending_loaders_.end(); ++i) {
     net::URLRequest* request = i->second->request();
     ResourceRequestInfoImpl* info = i->second->GetRequestInfo();
     uint64 upload_size = request->GetUploadProgress().size();
     if (request->GetLoadState().state != net::LOAD_STATE_SENDING_REQUEST)
       upload_size = 0;
-    std::pair<int, int> key(info->GetChildID(), info->GetRouteID());
-    if (upload_size && largest_upload_size[key] < upload_size)
-      largest_upload_size[key] = upload_size;
+    GlobalRoutingID id(info->GetGlobalRoutingID());
+    if (upload_size && largest_upload_size[id] < upload_size)
+      largest_upload_size[id] = upload_size;
   }
 
   for (i = pending_loaders_.begin(); i != pending_loaders_.end(); ++i) {
@@ -1612,23 +1663,23 @@
     // progress ipc messages to the plugin process.
     i->second->ReportUploadProgress();
 
-    std::pair<int, int> key(info->GetChildID(), info->GetRouteID());
+    GlobalRoutingID id(info->GetGlobalRoutingID());
 
     // If a request is uploading data, ignore all other requests so that the
     // upload progress takes priority for being shown in the status bar.
-    if (largest_upload_size.find(key) != largest_upload_size.end() &&
-        progress.size() < largest_upload_size[key])
+    if (largest_upload_size.find(id) != largest_upload_size.end() &&
+        progress.size() < largest_upload_size[id])
       continue;
 
     net::LoadStateWithParam to_insert = load_state;
-    LoadInfoMap::iterator existing = info_map.find(key);
+    LoadInfoMap::iterator existing = info_map.find(id);
     if (existing != info_map.end()) {
       to_insert =
           MoreInterestingLoadState(existing->second.load_state, load_state);
       if (to_insert.state == existing->second.load_state.state)
         continue;
     }
-    LoadInfo& load_info = info_map[key];
+    LoadInfo& load_info = info_map[id];
     load_info.url = request->url();
     load_info.load_state = to_insert;
     load_info.upload_size = progress.size();
@@ -1646,7 +1697,7 @@
 void ResourceDispatcherHostImpl::BlockRequestsForRoute(int child_id,
                                                        int route_id) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-  ProcessRouteIDs key(child_id, route_id);
+  GlobalRoutingID key(child_id, route_id);
   DCHECK(blocked_loaders_map_.find(key) == blocked_loaders_map_.end()) <<
       "BlockRequestsForRoute called  multiple time for the same RVH";
   blocked_loaders_map_[key] = new BlockedLoadersList();
@@ -1667,7 +1718,7 @@
     int route_id,
     bool cancel_requests) {
   BlockedLoadersMap::iterator iter = blocked_loaders_map_.find(
-      std::pair<int, int>(child_id, route_id));
+      GlobalRoutingID(child_id, route_id));
   if (iter == blocked_loaders_map_.end()) {
     // It's possible to reach here if the renderer crashed while an interstitial
     // page was showing.
diff --git a/content/browser/loader/resource_dispatcher_host_impl.h b/content/browser/loader/resource_dispatcher_host_impl.h
index 5dc36e6..b459ec8 100644
--- a/content/browser/loader/resource_dispatcher_host_impl.h
+++ b/content/browser/loader/resource_dispatcher_host_impl.h
@@ -25,6 +25,8 @@
 #include "base/time.h"
 #include "base/timer.h"
 #include "content/browser/download/download_resource_handler.h"
+#include "content/browser/loader/global_routing_id.h"
+#include "content/browser/loader/offline_policy.h"
 #include "content/browser/loader/render_view_host_tracker.h"
 #include "content/browser/loader/resource_loader.h"
 #include "content/browser/loader/resource_loader_delegate.h"
@@ -32,6 +34,7 @@
 #include "content/common/content_export.h"
 #include "content/public/browser/child_process_data.h"
 #include "content/public/browser/download_id.h"
+#include "content/public/browser/global_request_id.h"
 #include "content/public/browser/notification_types.h"
 #include "content/public/browser/resource_dispatcher_host.h"
 #include "ipc/ipc_message.h"
@@ -60,7 +63,6 @@
 class SaveFileManager;
 class WebContentsImpl;
 struct DownloadSaveInfo;
-struct GlobalRequestID;
 struct Referrer;
 
 class CONTENT_EXPORT ResourceDispatcherHostImpl
@@ -409,8 +411,7 @@
   bool is_shutdown_;
 
   typedef std::vector<linked_ptr<ResourceLoader> > BlockedLoadersList;
-  typedef std::pair<int, int> ProcessRouteIDs;
-  typedef std::map<ProcessRouteIDs, BlockedLoadersList*> BlockedLoadersMap;
+  typedef std::map<GlobalRoutingID, BlockedLoadersList*> BlockedLoadersMap;
   BlockedLoadersMap blocked_loaders_map_;
 
   // Maps the child_ids to the approximate number of bytes
@@ -452,6 +453,10 @@
 
   RenderViewHostTracker tracker_;  // Lives on UI thread.
 
+  typedef std::map<GlobalRoutingID, OfflinePolicy*> OfflineMap;
+
+  OfflineMap offline_policy_map_;
+
   DISALLOW_COPY_AND_ASSIGN(ResourceDispatcherHostImpl);
 };
 
diff --git a/content/browser/loader/resource_dispatcher_host_unittest.cc b/content/browser/loader/resource_dispatcher_host_unittest.cc
index 329c939..5e1b440 100644
--- a/content/browser/loader/resource_dispatcher_host_unittest.cc
+++ b/content/browser/loader/resource_dispatcher_host_unittest.cc
@@ -113,7 +113,7 @@
 
 // Spin up the message loop to kick off the request.
 static void KickOffRequest() {
-  MessageLoop::current()->RunUntilIdle();
+  base::MessageLoop::current()->RunUntilIdle();
 }
 
 // We may want to move this to a shared space if it is useful for something else
@@ -497,7 +497,7 @@
       int route_id,
       bool is_continuation_of_transferred_request,
       ScopedVector<ResourceThrottle>* throttles) OVERRIDE {
-    if (user_data_.get()) {
+    if (user_data_) {
       const void* key = user_data_.get();
       request->SetUserData(key, user_data_.release());
     }
@@ -535,6 +535,14 @@
     filter_ = new ForwardingFilter(
         this, browser_context_->GetResourceContext());
   }
+
+  virtual ~ResourceDispatcherHostTest() {
+    for (std::set<int>::iterator it = child_ids_.begin();
+         it != child_ids_.end(); ++it) {
+      host_.CancelRequestsForProcess(*it);
+    }
+  }
+
   // IPC::Sender implementation
   virtual bool Send(IPC::Message* msg) OVERRIDE {
     accum_.AddMessage(*msg);
@@ -699,12 +707,12 @@
     scoped_ptr<IPC::Message> ack(
         new ResourceHostMsg_DataReceived_ACK(msg.routing_id(), request_id));
 
-    MessageLoop::current()->PostTask(
+    base::MessageLoop::current()->PostTask(
         FROM_HERE,
         base::Bind(&GenerateIPCMessage, filter_, base::Passed(&ack)));
   }
 
-  MessageLoopForIO message_loop_;
+  base::MessageLoopForIO message_loop_;
   BrowserThreadImpl ui_thread_;
   BrowserThreadImpl file_thread_;
   BrowserThreadImpl cache_thread_;
@@ -719,6 +727,7 @@
   net::URLRequest::ProtocolFactory* old_factory_;
   ResourceType::Type resource_type_;
   bool send_data_received_acks_;
+  std::set<int> child_ids_;
   static ResourceDispatcherHostTest* test_fixture_;
   static bool delay_start_;
   static bool delay_complete_;
@@ -741,6 +750,9 @@
     int render_view_id,
     int request_id,
     const GURL& url) {
+  // If it's already there, this'll be dropped on the floor, which is fine.
+  child_ids_.insert(filter->child_id());
+
   ResourceHostMsg_Request request =
       CreateResourceRequest("GET", resource_type_, url);
   ResourceHostMsg_RequestResource msg(render_view_id, request_id, request);
@@ -865,7 +877,7 @@
 
   // flush all the pending requests
   while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
-  MessageLoop::current()->RunUntilIdle();
+  base::MessageLoop::current()->RunUntilIdle();
 
   EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(0));
 
@@ -905,7 +917,7 @@
 
   // flush all the pending requests
   while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
-  MessageLoop::current()->RunUntilIdle();
+  base::MessageLoop::current()->RunUntilIdle();
 
   EXPECT_TRUE(was_deleted);
 
@@ -923,7 +935,7 @@
 
   // flush all the pending requests
   while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
-  MessageLoop::current()->RunUntilIdle();
+  base::MessageLoop::current()->RunUntilIdle();
 
   ResourceIPCAccumulator::ClassifiedMessages msgs;
   accum_.GetClassifiedMessages(&msgs);
@@ -950,7 +962,7 @@
 
   // flush all the pending requests
   while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
-  MessageLoop::current()->RunUntilIdle();
+  base::MessageLoop::current()->RunUntilIdle();
 
   EXPECT_EQ(0, host_.pending_requests());
 }
@@ -979,7 +991,7 @@
   ASSERT_FALSE(GenericResourceThrottle::active_throttle());
 
   // The request is started asynchronously.
-  MessageLoop::current()->RunUntilIdle();
+  base::MessageLoop::current()->RunUntilIdle();
 
   // Flush all the pending requests.
   while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
@@ -1009,7 +1021,7 @@
 
   // flush all the pending requests
   while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
-  MessageLoop::current()->RunUntilIdle();
+  base::MessageLoop::current()->RunUntilIdle();
 
   EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(0));
 
@@ -1080,7 +1092,7 @@
 
   // Make sure all requests have finished stage one. test_url_1 will have
   // finished.
-  MessageLoop::current()->RunUntilIdle();
+  base::MessageLoop::current()->RunUntilIdle();
 
   // TODO(mbelshe):
   // Now that the async IO path is in place, the IO always completes on the
@@ -1288,7 +1300,7 @@
             ResourceDispatcherHostImpl::CalculateApproximateMemoryCost(&req));
 
   // Add 9 bytes of referrer.
-  req.set_referrer("123456789");
+  req.SetReferrer("123456789");
   EXPECT_EQ(4436,
             ResourceDispatcherHostImpl::CalculateApproximateMemoryCost(&req));
 
@@ -1384,7 +1396,7 @@
 
   // Flush all the pending requests.
   while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
-  MessageLoop::current()->RunUntilIdle();
+  base::MessageLoop::current()->RunUntilIdle();
 
   EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(filter_->child_id()));
 
@@ -1733,14 +1745,13 @@
 
   // Temporarily replace ContentBrowserClient with one that will trigger the
   // transfer navigation code paths.
-  ContentBrowserClient* old_client = GetContentClient()->browser();
   TransfersAllNavigationsContentBrowserClient new_client;
-  GetContentClient()->set_browser_for_testing(&new_client);
+  ContentBrowserClient* old_client = SetBrowserClientForTesting(&new_client);
 
   MakeTestRequest(render_view_id, request_id, GURL("http://example.com/blah"));
 
   // Restore.
-  GetContentClient()->set_browser_for_testing(old_client);
+  SetBrowserClientForTesting(old_client);
 
   // This second filter is used to emulate a second process.
   scoped_refptr<ForwardingFilter> second_filter = new ForwardingFilter(
@@ -1760,11 +1771,13 @@
   request.transferred_request_child_id = filter_->child_id();
   request.transferred_request_request_id = request_id;
 
+  // For cleanup.
+  child_ids_.insert(second_filter->child_id());
   ResourceHostMsg_RequestResource transfer_request_msg(
       new_render_view_id, new_request_id, request);
   bool msg_was_ok;
   host_.OnMessageReceived(transfer_request_msg, second_filter, &msg_was_ok);
-  MessageLoop::current()->RunUntilIdle();
+  base::MessageLoop::current()->RunUntilIdle();
 
   // Flush all the pending requests.
   while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
@@ -1792,14 +1805,13 @@
 
   // Temporarily replace ContentBrowserClient with one that will trigger the
   // transfer navigation code paths.
-  ContentBrowserClient* old_client = GetContentClient()->browser();
   TransfersAllNavigationsContentBrowserClient new_client;
-  GetContentClient()->set_browser_for_testing(&new_client);
+  ContentBrowserClient* old_client = SetBrowserClientForTesting(&new_client);
 
   MakeTestRequest(render_view_id, request_id, GURL("http://example.com/blah"));
 
   // Restore.
-  GetContentClient()->set_browser_for_testing(old_client);
+  SetBrowserClientForTesting(old_client);
 
   // This second filter is used to emulate a second process.
   scoped_refptr<ForwardingFilter> second_filter = new ForwardingFilter(
@@ -1821,11 +1833,13 @@
   request.transferred_request_child_id = filter_->child_id();
   request.transferred_request_request_id = request_id;
 
+  // For cleanup.
+  child_ids_.insert(second_filter->child_id());
   ResourceHostMsg_RequestResource transfer_request_msg(
       new_render_view_id, new_request_id, request);
   bool msg_was_ok;
   host_.OnMessageReceived(transfer_request_msg, second_filter, &msg_was_ok);
-  MessageLoop::current()->RunUntilIdle();
+  base::MessageLoop::current()->RunUntilIdle();
 
   // Response data for "http://other.com/blerg":
   const std::string kResponseBody = "hello world";
@@ -1836,7 +1850,7 @@
   // OK, let the redirect happen.
   SetDelayedStartJobGeneration(false);
   CompleteStartRequest(second_filter, new_request_id);
-  MessageLoop::current()->RunUntilIdle();
+  base::MessageLoop::current()->RunUntilIdle();
 
   // Flush all the pending requests.
   while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
@@ -1845,7 +1859,7 @@
   ResourceHostMsg_FollowRedirect redirect_msg(
       new_render_view_id, new_request_id, false, GURL());
   host_.OnMessageReceived(redirect_msg, second_filter, &msg_was_ok);
-  MessageLoop::current()->RunUntilIdle();
+  base::MessageLoop::current()->RunUntilIdle();
 
   // Flush all the pending requests.
   while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
@@ -1954,7 +1968,7 @@
       host_.OnMessageReceived(msg, filter_.get(), &msg_was_ok);
     }
 
-    MessageLoop::current()->RunUntilIdle();
+    base::MessageLoop::current()->RunUntilIdle();
 
     msgs.clear();
     accum_.GetClassifiedMessages(&msgs);
diff --git a/content/browser/loader/resource_loader.cc b/content/browser/loader/resource_loader.cc
index a88aa05..6319512 100644
--- a/content/browser/loader/resource_loader.cc
+++ b/content/browser/loader/resource_loader.cc
@@ -437,14 +437,14 @@
       request_->FollowDeferredRedirect();
       break;
     case DEFERRED_READ:
-      MessageLoop::current()->PostTask(
+      base::MessageLoop::current()->PostTask(
           FROM_HERE,
           base::Bind(&ResourceLoader::ResumeReading,
                      weak_ptr_factory_.GetWeakPtr()));
       break;
     case DEFERRED_FINISH:
       // Delay self-destruction since we don't know how we were reached.
-      MessageLoop::current()->PostTask(
+      base::MessageLoop::current()->PostTask(
           FROM_HERE,
           base::Bind(&ResourceLoader::CallDidFinishLoading,
                      weak_ptr_factory_.GetWeakPtr()));
@@ -493,9 +493,10 @@
     // If the request isn't in flight, then we won't get an asynchronous
     // notification from the request, so we have to signal ourselves to finish
     // this request.
-    MessageLoop::current()->PostTask(
-        FROM_HERE, base::Bind(&ResourceLoader::ResponseCompleted,
-                              weak_ptr_factory_.GetWeakPtr()));
+    base::MessageLoop::current()->PostTask(
+        FROM_HERE,
+        base::Bind(&ResourceLoader::ResponseCompleted,
+                   weak_ptr_factory_.GetWeakPtr()));
   }
 }
 
@@ -529,7 +530,7 @@
       response->head.mime_type == "text/html" &&
       !request_->url().SchemeIs(chrome::kChromeUIScheme) &&
       !SiteInstance::IsSameWebSite(NULL, request_->url(),
-          request_->GetSanitizedReferrer())) {
+                                   GURL(request_->referrer()))) {
     response->head.mime_type = "application/browser-plugin";
   }
 
@@ -572,11 +573,12 @@
   } else {
     // Else, trigger OnReadCompleted asynchronously to avoid starving the IO
     // thread in case the URLRequest can provide data synchronously.
-    MessageLoop::current()->PostTask(
+    base::MessageLoop::current()->PostTask(
         FROM_HERE,
         base::Bind(&ResourceLoader::OnReadCompleted,
                    weak_ptr_factory_.GetWeakPtr(),
-                   request_.get(), bytes_read));
+                   request_.get(),
+                   bytes_read));
   }
 }
 
diff --git a/content/browser/loader/resource_loader_unittest.cc b/content/browser/loader/resource_loader_unittest.cc
index 781b62c..84e57a5 100644
--- a/content/browser/loader/resource_loader_unittest.cc
+++ b/content/browser/loader/resource_loader_unittest.cc
@@ -10,7 +10,7 @@
 #include "content/public/browser/resource_request_info.h"
 #include "content/public/test/mock_resource_context.h"
 #include "content/test/test_content_browser_client.h"
-#include "net/base/x509_certificate.h"
+#include "net/cert/x509_certificate.h"
 #include "net/ssl/client_cert_store.h"
 #include "net/ssl/ssl_cert_request_info.h"
 #include "net/url_request/url_request.h"
@@ -146,9 +146,9 @@
  protected:
   // testing::Test:
   virtual void SetUp() OVERRIDE {
-    message_loop_.reset(new MessageLoop(MessageLoop::TYPE_IO));
-    ui_thread_.reset(new BrowserThreadImpl(BrowserThread::UI,
-                                           message_loop_.get()));
+    message_loop_.reset(new base::MessageLoop(base::MessageLoop::TYPE_IO));
+    ui_thread_.reset(
+        new BrowserThreadImpl(BrowserThread::UI, message_loop_.get()));
     io_thread_.reset(new BrowserThreadImpl(BrowserThread::IO,
                                            message_loop_.get()));
   }
@@ -179,7 +179,7 @@
   virtual void DidReceiveResponse(ResourceLoader* loader) OVERRIDE {}
   virtual void DidFinishLoading(ResourceLoader* loader) OVERRIDE {}
 
-  scoped_ptr<MessageLoop> message_loop_;
+  scoped_ptr<base::MessageLoop> message_loop_;
   scoped_ptr<BrowserThreadImpl> ui_thread_;
   scoped_ptr<BrowserThreadImpl> io_thread_;
 
@@ -230,9 +230,8 @@
   cert_request_info->cert_authorities = dummy_authority;
 
   // Plug in test content browser client.
-  ContentBrowserClient* old_client = GetContentClient()->browser();
   SelectCertificateBrowserClient test_client;
-  GetContentClient()->set_browser_for_testing(&test_client);
+  ContentBrowserClient* old_client = SetBrowserClientForTesting(&test_client);
 
   // Everything is set up. Trigger the resource loader certificate request event
   // and run the message loop.
@@ -240,7 +239,7 @@
   message_loop_->RunUntilIdle();
 
   // Restore the original content browser client.
-  GetContentClient()->set_browser_for_testing(old_client);
+  SetBrowserClientForTesting(old_client);
 
   // Check if the test store was queried against correct |cert_authorities|.
   EXPECT_EQ(1, raw_ptr_to_store->request_count());
diff --git a/content/browser/loader/resource_request_info_impl.cc b/content/browser/loader/resource_request_info_impl.cc
index 8039a12..09b82ca 100644
--- a/content/browser/loader/resource_request_info_impl.cc
+++ b/content/browser/loader/resource_request_info_impl.cc
@@ -4,6 +4,7 @@
 
 #include "content/browser/loader/resource_request_info_impl.h"
 
+#include "content/browser/loader/global_routing_id.h"
 #include "content/browser/worker_host/worker_service_impl.h"
 #include "content/common/net/url_request_user_data.h"
 #include "content/public/browser/global_request_id.h"
@@ -221,6 +222,10 @@
   return GlobalRequestID(child_id_, request_id_);
 }
 
+GlobalRoutingID ResourceRequestInfoImpl::GetGlobalRoutingID() const {
+  return GlobalRoutingID(child_id_, route_id_);
+}
+
 void ResourceRequestInfoImpl::set_requested_blob_data(
     webkit_blob::BlobData* data) {
   requested_blob_data_ = data;
diff --git a/content/browser/loader/resource_request_info_impl.h b/content/browser/loader/resource_request_info_impl.h
index 8b23b2a..1c663257 100644
--- a/content/browser/loader/resource_request_info_impl.h
+++ b/content/browser/loader/resource_request_info_impl.h
@@ -24,6 +24,7 @@
 class CrossSiteResourceHandler;
 class ResourceContext;
 struct GlobalRequestID;
+struct GlobalRoutingID;
 
 // Holds the data ResourceDispatcherHost associates with each request.
 // Retrieve this data by calling ResourceDispatcherHost::InfoForRequest.
@@ -82,6 +83,7 @@
   CONTENT_EXPORT void AssociateWithRequest(net::URLRequest* request);
 
   CONTENT_EXPORT GlobalRequestID GetGlobalRequestID() const;
+  GlobalRoutingID GetGlobalRoutingID() const;
 
   // CrossSiteResourceHandler for this request.  May be null.
   CrossSiteResourceHandler* cross_site_handler() {
diff --git a/content/browser/loader/resource_scheduler.cc b/content/browser/loader/resource_scheduler.cc
index 4f377dc..6e75c73 100644
--- a/content/browser/loader/resource_scheduler.cc
+++ b/content/browser/loader/resource_scheduler.cc
@@ -11,9 +11,12 @@
 #include "content/public/browser/resource_request_info.h"
 #include "content/public/browser/resource_throttle.h"
 #include "ipc/ipc_message_macros.h"
+#include "net/base/host_port_pair.h"
 #include "net/base/load_flags.h"
 #include "net/base/request_priority.h"
+#include "net/http/http_server_properties.h"
 #include "net/url_request/url_request.h"
+#include "net/url_request/url_request_context.h"
 
 namespace content {
 
@@ -324,6 +327,7 @@
 //
 //   * Higher priority requests (>= net::LOW).
 //   * Synchronous requests.
+//   * Requests to SPDY-capable origin servers.
 //
 // 2. The remainder are delayable requests, which follow these rules:
 //
@@ -333,8 +337,19 @@
 //   * Never exceed 10 delayable requests in flight per client.
 bool ResourceScheduler::ShouldStartRequest(ScheduledResourceRequest* request,
                                            Client* client) const {
-  if (request->url_request()->priority() >= net::LOW ||
-      !ResourceRequestInfo::ForRequest(request->url_request())->IsAsync()) {
+  const net::URLRequest& url_request = *request->url_request();
+  const net::HttpServerProperties& http_server_properties =
+      *url_request.context()->http_server_properties();
+
+  // TODO(willchan): We should really improve this algorithm as described in
+  // crbug.com/164101. Also, theoretically we should not count a SPDY request
+  // against the delayable requests limit.
+  bool origin_supports_spdy = http_server_properties.SupportsSpdy(
+      net::HostPortPair::FromURL(url_request.url()));
+
+  if (url_request.priority() >= net::LOW ||
+      !ResourceRequestInfo::ForRequest(&url_request)->IsAsync() ||
+      origin_supports_spdy) {
     return true;
   }
 
diff --git a/content/browser/loader/resource_scheduler_unittest.cc b/content/browser/loader/resource_scheduler_unittest.cc
index 428110f..cfaf459 100644
--- a/content/browser/loader/resource_scheduler_unittest.cc
+++ b/content/browser/loader/resource_scheduler_unittest.cc
@@ -16,6 +16,8 @@
 #include "content/public/browser/resource_controller.h"
 #include "content/public/browser/resource_throttle.h"
 #include "content/public/common/process_type.h"
+#include "net/base/host_port_pair.h"
+#include "net/http/http_server_properties_impl.h"
 #include "net/url_request/url_request.h"
 #include "net/url_request/url_request_test_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -120,10 +122,11 @@
  protected:
   ResourceSchedulerTest()
       : next_request_id_(0),
-        message_loop_(MessageLoop::TYPE_IO),
+        message_loop_(base::MessageLoop::TYPE_IO),
         ui_thread_(BrowserThread::UI, &message_loop_),
         io_thread_(BrowserThread::IO, &message_loop_) {
     scheduler_.OnClientCreated(kChildId, kRouteId);
+    context_.set_http_server_properties(&http_server_properties_);
   }
 
   virtual ~ResourceSchedulerTest() {
@@ -196,11 +199,12 @@
   }
 
   int next_request_id_;
-  MessageLoop message_loop_;
+  base::MessageLoop message_loop_;
   BrowserThreadImpl ui_thread_;
   BrowserThreadImpl io_thread_;
   ResourceDispatcherHostImpl rdh_;
   ResourceScheduler scheduler_;
+  net::HttpServerPropertiesImpl http_server_properties_;
   net::TestURLRequestContext context_;
 };
 
@@ -227,6 +231,20 @@
   EXPECT_TRUE(low->started());
 }
 
+TEST_F(ResourceSchedulerTest, LowBlocksUntilBodyInsertedExceptSpdy) {
+  http_server_properties_.SetSupportsSpdy(
+      net::HostPortPair("spdyhost", 443), true);
+  scoped_ptr<TestRequest> high(NewRequest("http://host/high", net::HIGHEST));
+  scoped_ptr<TestRequest> low_spdy(
+      NewRequest("https://spdyhost/high", net::LOWEST));
+  scoped_ptr<TestRequest> low(NewRequest("http://host/low", net::LOWEST));
+  EXPECT_TRUE(high->started());
+  EXPECT_TRUE(low_spdy->started());
+  EXPECT_FALSE(low->started());
+  scheduler_.OnWillInsertBody(kChildId, kRouteId);
+  EXPECT_TRUE(low->started());
+}
+
 TEST_F(ResourceSchedulerTest, NavigationResetsState) {
   scheduler_.OnWillInsertBody(kChildId, kRouteId);
   scheduler_.OnNavigate(kChildId, kRouteId);
diff --git a/content/browser/loader/sync_resource_handler.cc b/content/browser/loader/sync_resource_handler.cc
index 3b9ee1d..879c267 100644
--- a/content/browser/loader/sync_resource_handler.cc
+++ b/content/browser/loader/sync_resource_handler.cc
@@ -83,8 +83,6 @@
   result_.download_file_path = response->head.download_file_path;
   result_.request_time = response->head.request_time;
   result_.response_time = response->head.response_time;
-  result_.connection_id = response->head.connection_id;
-  result_.connection_reused = response->head.connection_reused;
   result_.load_timing = response->head.load_timing;
   result_.devtools_info = response->head.devtools_info;
   return true;
diff --git a/content/browser/mach_broker_mac.cc b/content/browser/mach_broker_mac.cc
deleted file mode 100644
index 325db75..0000000
--- a/content/browser/mach_broker_mac.cc
+++ /dev/null
@@ -1,232 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/mach_broker_mac.h"
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/command_line.h"
-#include "base/logging.h"
-#include "base/mac/foundation_util.h"
-#include "base/mach_ipc_mac.h"
-#include "base/string_util.h"
-#include "base/stringprintf.h"
-#include "base/sys_string_conversions.h"
-#include "base/threading/platform_thread.h"
-#include "content/browser/renderer_host/render_process_host_impl.h"
-#include "content/public/browser/child_process_data.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/notification_service.h"
-#include "content/public/browser/notification_types.h"
-#include "content/public/common/content_switches.h"
-
-namespace content {
-
-namespace {
-// Prints a string representation of a Mach error code.
-std::string MachErrorCode(kern_return_t err) {
-  return base::StringPrintf("0x%x %s", err, mach_error_string(err));
-}
-}  // namespace
-
-class MachListenerThreadDelegate : public base::PlatformThread::Delegate {
- public:
-  MachListenerThreadDelegate(MachBroker* broker) : broker_(broker) {
-    DCHECK(broker_);
-    std::string port_name = MachBroker::GetMachPortName();
-
-    // Create the receive port in the constructor, not in ThreadMain().  It is
-    // important to create and register the receive port before starting the
-    // thread so that child processes will always have someone who's listening.
-    receive_port_.reset(new base::ReceivePort(port_name.c_str()));
-  }
-
-  // Implement |PlatformThread::Delegate|.
-  virtual void ThreadMain() OVERRIDE {
-    base::MachReceiveMessage message;
-    kern_return_t err;
-    while ((err = receive_port_->WaitForMessage(&message,
-                                                MACH_MSG_TIMEOUT_NONE)) ==
-           KERN_SUCCESS) {
-      // 0 was the secret message id.  Reject any messages that don't have it.
-      if (message.GetMessageID() != 0) {
-        LOG(ERROR) << "Received message with incorrect id: "
-                   << message.GetMessageID();
-        continue;
-      }
-
-      const task_t child_task = message.GetTranslatedPort(0);
-      if (child_task == MACH_PORT_NULL) {
-        LOG(ERROR) << "parent GetTranslatedPort(0) failed.";
-        continue;
-      }
-
-      // It is possible for the child process to die after the call to
-      // |pid_for_task()| but before the call to |FinalizePid()|.  To prevent
-      // 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.
-      base::AutoLock lock(broker_->GetLock());
-
-      int pid;
-      err = pid_for_task(child_task, &pid);
-      if (err == KERN_SUCCESS) {
-        broker_->FinalizePid(pid,
-                             MachBroker::MachInfo().SetTask(child_task));
-      } else {
-        LOG(ERROR) << "Error getting pid for task " << child_task
-                   << ": " << MachErrorCode(err);
-      }
-    }
-
-    LOG(ERROR) << "Mach listener thread exiting; "
-               << "parent WaitForMessage() likely failed: "
-               << MachErrorCode(err);
-  }
-
- private:
-  // The Mach port to listen on.  Created on thread startup.
-  scoped_ptr<base::ReceivePort> receive_port_;
-
-  // The MachBroker to use when new child task rights are received.  Can be
-  // NULL.
-  MachBroker* broker_;  // weak
-
-  DISALLOW_COPY_AND_ASSIGN(MachListenerThreadDelegate);
-};
-
-// Returns the global MachBroker.
-MachBroker* MachBroker::GetInstance() {
-  return Singleton<MachBroker, LeakySingletonTraits<MachBroker> >::get();
-}
-
-void MachBroker::EnsureRunning() {
-  lock_.AssertAcquired();
-
-  if (!listener_thread_started_) {
-    listener_thread_started_ = true;
-
-    BrowserThread::PostTask(
-        BrowserThread::UI, FROM_HERE,
-        base::Bind(&MachBroker::RegisterNotifications, base::Unretained(this)));
-
-    // Intentional leak.  This thread is never joined or reaped.
-    base::PlatformThread::CreateNonJoinable(
-        0, new MachListenerThreadDelegate(this));
-  }
-}
-
-// Adds a placeholder to the map for the given pid with MACH_PORT_NULL.
-void MachBroker::AddPlaceholderForPid(base::ProcessHandle pid) {
-  lock_.AssertAcquired();
-
-  MachInfo mach_info;
-  DCHECK_EQ(0u, mach_map_.count(pid));
-  mach_map_[pid] = mach_info;
-}
-
-// Updates the mapping for |pid| to include the given |mach_info|.
-void MachBroker::FinalizePid(base::ProcessHandle pid,
-                             const MachInfo& mach_info) {
-  lock_.AssertAcquired();
-
-  const int count = mach_map_.count(pid);
-  if (count == 0) {
-    // Do nothing for unknown pids.
-    LOG(ERROR) << "Unknown process " << pid << " is sending Mach IPC messages!";
-    return;
-  }
-
-  DCHECK_EQ(1, count);
-  DCHECK(mach_map_[pid].mach_task_ == MACH_PORT_NULL);
-  if (mach_map_[pid].mach_task_ == MACH_PORT_NULL)
-    mach_map_[pid] = mach_info;
-}
-
-// Removes all mappings belonging to |pid| from the broker.
-void MachBroker::InvalidatePid(base::ProcessHandle pid) {
-  base::AutoLock lock(lock_);
-  MachBroker::MachMap::iterator it = mach_map_.find(pid);
-  if (it == mach_map_.end())
-    return;
-
-  kern_return_t kr = mach_port_deallocate(mach_task_self(),
-                                          it->second.mach_task_);
-  LOG_IF(WARNING, kr != KERN_SUCCESS)
-     << "Failed to mach_port_deallocate mach task " << it->second.mach_task_
-     << ", error " << MachErrorCode(kr);
-  mach_map_.erase(it);
-}
-
-base::Lock& MachBroker::GetLock() {
-  return lock_;
-}
-
-// Returns the mach task belonging to |pid|.
-mach_port_t MachBroker::TaskForPid(base::ProcessHandle pid) const {
-  base::AutoLock lock(lock_);
-  MachBroker::MachMap::const_iterator it = mach_map_.find(pid);
-  if (it == mach_map_.end())
-    return MACH_PORT_NULL;
-  return it->second.mach_task_;
-}
-
-void MachBroker::BrowserChildProcessHostDisconnected(
-    const ChildProcessData& data) {
-  InvalidatePid(data.handle);
-}
-
-void MachBroker::BrowserChildProcessCrashed(const ChildProcessData& data) {
-  InvalidatePid(data.handle);
-}
-
-void MachBroker::Observe(int type,
-                         const NotificationSource& source,
-                         const NotificationDetails& details) {
-  // TODO(rohitrao): These notifications do not always carry the proper PIDs,
-  // especially when the renderer is already gone or has crashed.  Find a better
-  // way to listen for child process deaths.  http://crbug.com/55734
-  base::ProcessHandle handle = 0;
-  switch (type) {
-    case NOTIFICATION_RENDERER_PROCESS_CLOSED:
-      handle = Details<RenderProcessHost::RendererClosedDetails>(
-          details)->handle;
-      break;
-    case NOTIFICATION_RENDERER_PROCESS_TERMINATED:
-      handle = Source<RenderProcessHost>(source)->GetHandle();
-      break;
-    default:
-      NOTREACHED() << "Unexpected notification";
-      break;
-  }
-  InvalidatePid(handle);
-}
-
-// static
-std::string MachBroker::GetMachPortName() {
-  const CommandLine* command_line = CommandLine::ForCurrentProcess();
-  const bool is_child = command_line->HasSwitch(switches::kProcessType);
-
-  // In non-browser (child) processes, use the parent's pid.
-  const pid_t pid = is_child ? getppid() : getpid();
-  return base::StringPrintf("%s.rohitfork.%d", base::mac::BaseBundleID(), pid);
-}
-
-MachBroker::MachBroker() : listener_thread_started_(false) {
-}
-
-MachBroker::~MachBroker() {}
-
-void MachBroker::RegisterNotifications() {
-  registrar_.Add(this, NOTIFICATION_RENDERER_PROCESS_CLOSED,
-                 NotificationService::AllBrowserContextsAndSources());
-  registrar_.Add(this, NOTIFICATION_RENDERER_PROCESS_TERMINATED,
-                 NotificationService::AllBrowserContextsAndSources());
-
-  // No corresponding StopObservingBrowserChildProcesses,
-  // we leak this singleton.
-  BrowserChildProcessObserver::Add(this);
-}
-
-}  // namespace content
diff --git a/content/browser/mach_broker_mac.h b/content/browser/mach_broker_mac.h
index 011df04..e38e86f 100644
--- a/content/browser/mach_broker_mac.h
+++ b/content/browser/mach_broker_mac.h
@@ -38,48 +38,30 @@
                                   public BrowserChildProcessObserver,
                                   public NotificationObserver {
  public:
+  // For use in child processes. This will send the task port of the current
+  // process over Mach IPC to the port registered by name (via this class) in
+  // the parent process. Returns true if the message was sent successfully
+  // and false if otherwise.
+  static bool ChildSendTaskPortToParent();
+
   // Returns the global MachBroker.
   static MachBroker* GetInstance();
 
-  // Performs any necessary setup that cannot happen in the constructor.
-  // Callers MUST acquire the lock given by GetLock() before calling this
-  // method (and release the lock afterwards).
-  void EnsureRunning();
-
-  struct MachInfo {
-    MachInfo() : mach_task_(MACH_PORT_NULL) {}
-
-    MachInfo& SetTask(mach_port_t task) {
-      mach_task_ = task;
-      return *this;
-    }
-
-    mach_port_t mach_task_;
-  };
-
-  // Adds a placeholder to the map for the given pid with MACH_PORT_NULL.
-  // Callers are expected to later update the port with FinalizePid().  Callers
-  // MUST acquire the lock given by GetLock() before calling this method (and
-  // release the lock afterwards).
-  void AddPlaceholderForPid(base::ProcessHandle pid);
-
-  // Updates the mapping for |pid| to include the given |mach_info|.  Does
-  // nothing if PlaceholderForPid() has not already been called for the given
-  // |pid|.  Callers MUST acquire the lock given by GetLock() before calling
-  // this method (and release the lock afterwards).
-  void FinalizePid(base::ProcessHandle pid, const MachInfo& mach_info);
-
-  // Removes all mappings belonging to |pid| from the broker.
-  void InvalidatePid(base::ProcessHandle pid);
-
   // The lock that protects this MachBroker object.  Clients MUST acquire and
   // release this lock around calls to EnsureRunning(), PlaceholderForPid(),
   // and FinalizePid().
   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.
-  static std::string GetMachPortName();
+  // Performs any necessary setup that cannot happen in the constructor.
+  // Callers MUST acquire the lock given by GetLock() before calling this
+  // method (and release the lock afterwards).
+  void EnsureRunning();
+
+  // Adds a placeholder to the map for the given pid with MACH_PORT_NULL.
+  // Callers are expected to later update the port with FinalizePid().  Callers
+  // MUST acquire the lock given by GetLock() before calling this method (and
+  // release the lock afterwards).
+  void AddPlaceholderForPid(base::ProcessHandle pid);
 
   // Implement |ProcessMetrics::PortProvider|.
   virtual mach_port_t TaskForPid(base::ProcessHandle process) const OVERRIDE;
@@ -96,11 +78,24 @@
                        const NotificationDetails& details) OVERRIDE;
  private:
   friend class MachBrokerTest;
+  friend class MachListenerThreadDelegate;
   friend struct DefaultSingletonTraits<MachBroker>;
 
   MachBroker();
   virtual ~MachBroker();
 
+  // Updates the mapping for |pid| to include the given |mach_info|.  Does
+  // nothing if PlaceholderForPid() has not already been called for the given
+  // |pid|.  Callers MUST acquire the lock given by GetLock() before calling
+  // this method (and release the lock afterwards).
+  void FinalizePid(base::ProcessHandle pid, mach_port_t task_port);
+
+  // Removes all mappings belonging to |pid| from the broker.
+  void InvalidatePid(base::ProcessHandle pid);
+
+  // Returns the Mach port name to use when sending or receiving messages.
+  // Does the Right Thing in the browser and in child processes.
+  static std::string GetMachPortName();
   // Callback used to register notifications on the UI thread.
   void RegisterNotifications();
 
@@ -112,7 +107,7 @@
   NotificationRegistrar registrar_;
 
   // Stores mach info for every process in the broker.
-  typedef std::map<base::ProcessHandle, MachInfo> MachMap;
+  typedef std::map<base::ProcessHandle, mach_port_t> MachMap;
   MachMap mach_map_;
 
   // Mutex that guards |mach_map_|.
diff --git a/content/browser/mach_broker_mac.mm b/content/browser/mach_broker_mac.mm
new file mode 100644
index 0000000..783b708
--- /dev/null
+++ b/content/browser/mach_broker_mac.mm
@@ -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 "content/browser/mach_broker_mac.h"
+
+#include <bsm/libbsm.h>
+#include <servers/bootstrap.h>
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/command_line.h"
+#include "base/logging.h"
+#include "base/mac/foundation_util.h"
+#include "base/mac/scoped_mach_port.h"
+#include "base/string_util.h"
+#include "base/stringprintf.h"
+#include "base/strings/sys_string_conversions.h"
+#include "base/threading/platform_thread.h"
+#include "content/browser/renderer_host/render_process_host_impl.h"
+#include "content/public/browser/child_process_data.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/notification_service.h"
+#include "content/public/browser/notification_types.h"
+#include "content/public/common/content_switches.h"
+
+namespace content {
+
+namespace {
+
+// Prints a string representation of a Mach error code.
+std::string MachErrorCode(kern_return_t err) {
+  return base::StringPrintf("0x%x %s", err, mach_error_string(err));
+}
+
+// Mach message structure used in the child as a sending message.
+struct MachBroker_ChildSendMsg {
+  mach_msg_header_t header;
+  mach_msg_body_t body;
+  mach_msg_port_descriptor_t child_task_port;
+};
+
+// Complement to the ChildSendMsg, this is used in the parent for receiving
+// a message. Contains a message trailer with audit information.
+struct MachBroker_ParentRecvMsg : public MachBroker_ChildSendMsg {
+  mach_msg_audit_trailer_t trailer;
+};
+
+}  // namespace
+
+class MachListenerThreadDelegate : public base::PlatformThread::Delegate {
+ public:
+  explicit MachListenerThreadDelegate(MachBroker* broker)
+      : broker_(broker),
+        server_port_(MACH_PORT_NULL) {
+    DCHECK(broker_);
+  }
+
+  bool Init() {
+    DCHECK(server_port_ == MACH_PORT_NULL);
+
+    mach_port_t port;
+    kern_return_t kr = mach_port_allocate(mach_task_self(),
+                                          MACH_PORT_RIGHT_RECEIVE,
+                                          &port);
+    if (kr != KERN_SUCCESS) {
+      LOG(ERROR) << "Failed to allocate MachBroker server port: "
+                 << MachErrorCode(kr);
+      return false;
+    }
+
+    // Allocate a send right for the server port.
+    kr = mach_port_insert_right(
+        mach_task_self(), port, port, MACH_MSG_TYPE_MAKE_SEND);
+    if (kr != KERN_SUCCESS) {
+      LOG(ERROR) << "Failed to insert send right for MachBroker server port: "
+                 << MachErrorCode(kr);
+      return false;
+    }
+
+    server_port_.reset(port);
+
+    // Register the port with the bootstrap server. Because bootstrap_register
+    // is deprecated, this has to be wraped in an ObjC interface.
+    NSPort* ns_port = [NSMachPort portWithMachPort:port
+                                           options:NSMachPortDeallocateNone];
+    NSString* name = base::SysUTF8ToNSString(broker_->GetMachPortName());
+    return [[NSMachBootstrapServer sharedInstance] registerPort:ns_port
+                                                           name:name];
+  }
+
+  // Implement |PlatformThread::Delegate|.
+  virtual void ThreadMain() OVERRIDE {
+    MachBroker_ParentRecvMsg msg;
+    bzero(&msg, sizeof(msg));
+    msg.header.msgh_size = sizeof(msg);
+    msg.header.msgh_local_port = server_port_.get();
+
+    kern_return_t kr;
+    do {
+      // Use the kernel audit information to make sure this message is from
+      // a task that this process spawned. The kernel audit token contains the
+      // unspoofable pid of the task that sent the message.
+      mach_msg_option_t options = MACH_RCV_MSG |
+          MACH_RCV_TRAILER_TYPE(MACH_RCV_TRAILER_AUDIT) |
+          MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_AUDIT);
+
+      kr = mach_msg(&msg.header, options, 0, sizeof(msg), server_port_,
+          MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
+      if (kr == KERN_SUCCESS) {
+        // TODO(rsesek): In the 10.7 SDK, there's audit_token_to_pid().
+        pid_t child_pid;
+        audit_token_to_au32(msg.trailer.msgh_audit,
+            NULL, NULL, NULL, NULL, NULL, &child_pid, NULL, NULL);
+
+        mach_port_t child_task_port = msg.child_task_port.name;
+
+        // Take the lock and update the broker information.
+        base::AutoLock lock(broker_->GetLock());
+        broker_->FinalizePid(child_pid, child_task_port);
+      }
+    } while (kr == KERN_SUCCESS);
+
+    LOG(ERROR) << "MachBroker thread exiting; mach_msg() likely failed: "
+               << MachErrorCode(kr);
+  }
+
+ private:
+  // The MachBroker to use when new child task rights are received.  Can be
+  // NULL.
+  MachBroker* broker_;  // weak
+
+  base::mac::ScopedMachPort server_port_;
+
+  DISALLOW_COPY_AND_ASSIGN(MachListenerThreadDelegate);
+};
+
+bool MachBroker::ChildSendTaskPortToParent() {
+  // Look up the named MachBroker port that's been registered with the
+  // bootstrap server.
+  mach_port_t bootstrap_port;
+  kern_return_t kr = task_get_bootstrap_port(mach_task_self(), &bootstrap_port);
+  if (kr != KERN_SUCCESS) {
+    LOG(ERROR) << "Failed to look up bootstrap port: " << MachErrorCode(kr);
+    return false;
+  }
+
+  mach_port_t parent_port;
+  kr = bootstrap_look_up(bootstrap_port,
+      const_cast<char*>(GetMachPortName().c_str()), &parent_port);
+  if (kr != KERN_SUCCESS) {
+    LOG(ERROR) << "Failed to look up named parent port: " << MachErrorCode(kr);
+    return false;
+  }
+
+  // Create the check in message. This will copy a send right on this process'
+  // (the child's) task port and send it to the parent.
+  MachBroker_ChildSendMsg msg;
+  bzero(&msg, sizeof(msg));
+  msg.header.msgh_bits = MACH_MSGH_BITS_REMOTE(MACH_MSG_TYPE_COPY_SEND) |
+                         MACH_MSGH_BITS_COMPLEX;
+  msg.header.msgh_remote_port = parent_port;
+  msg.header.msgh_size = sizeof(msg);
+  msg.body.msgh_descriptor_count = 1;
+  msg.child_task_port.name = mach_task_self();
+  msg.child_task_port.disposition = MACH_MSG_TYPE_PORT_SEND;
+  msg.child_task_port.type = MACH_MSG_PORT_DESCRIPTOR;
+
+  kr = mach_msg(&msg.header, MACH_SEND_MSG | MACH_SEND_TIMEOUT, sizeof(msg),
+      0, MACH_PORT_NULL, 100 /*milliseconds*/, MACH_PORT_NULL);
+  if (kr != KERN_SUCCESS) {
+    LOG(ERROR) << "Failed to send task port to parent: " << MachErrorCode(kr);
+    return false;
+  }
+
+  return true;
+}
+
+MachBroker* MachBroker::GetInstance() {
+  return Singleton<MachBroker, LeakySingletonTraits<MachBroker> >::get();
+}
+
+base::Lock& MachBroker::GetLock() {
+  return lock_;
+}
+
+void MachBroker::EnsureRunning() {
+  lock_.AssertAcquired();
+
+  if (!listener_thread_started_) {
+    listener_thread_started_ = true;
+
+    BrowserThread::PostTask(
+        BrowserThread::UI, FROM_HERE,
+        base::Bind(&MachBroker::RegisterNotifications, base::Unretained(this)));
+
+    // Intentional leak.  This thread is never joined or reaped.
+    MachListenerThreadDelegate* thread = new MachListenerThreadDelegate(this);
+    if (thread->Init()) {
+      base::PlatformThread::CreateNonJoinable(0, thread);
+    } else {
+      LOG(ERROR) << "Failed to initialize the MachListenerThreadDelegate";
+    }
+  }
+}
+
+void MachBroker::AddPlaceholderForPid(base::ProcessHandle pid) {
+  lock_.AssertAcquired();
+
+  DCHECK_EQ(0u, mach_map_.count(pid));
+  mach_map_[pid] = MACH_PORT_NULL;
+}
+
+mach_port_t MachBroker::TaskForPid(base::ProcessHandle pid) const {
+  base::AutoLock lock(lock_);
+  MachBroker::MachMap::const_iterator it = mach_map_.find(pid);
+  if (it == mach_map_.end())
+    return MACH_PORT_NULL;
+  return it->second;
+}
+
+void MachBroker::BrowserChildProcessHostDisconnected(
+    const ChildProcessData& data) {
+  InvalidatePid(data.handle);
+}
+
+void MachBroker::BrowserChildProcessCrashed(const ChildProcessData& data) {
+  InvalidatePid(data.handle);
+}
+
+void MachBroker::Observe(int type,
+                         const NotificationSource& source,
+                         const NotificationDetails& details) {
+  // TODO(rohitrao): These notifications do not always carry the proper PIDs,
+  // especially when the renderer is already gone or has crashed.  Find a better
+  // way to listen for child process deaths.  http://crbug.com/55734
+  base::ProcessHandle handle = 0;
+  switch (type) {
+    case NOTIFICATION_RENDERER_PROCESS_CLOSED:
+      handle = Details<RenderProcessHost::RendererClosedDetails>(
+          details)->handle;
+      break;
+    case NOTIFICATION_RENDERER_PROCESS_TERMINATED:
+      handle = Source<RenderProcessHost>(source)->GetHandle();
+      break;
+    default:
+      NOTREACHED() << "Unexpected notification";
+      break;
+  }
+  InvalidatePid(handle);
+}
+
+MachBroker::MachBroker() : listener_thread_started_(false) {
+}
+
+MachBroker::~MachBroker() {}
+
+void MachBroker::FinalizePid(base::ProcessHandle pid,
+                             mach_port_t task_port) {
+  lock_.AssertAcquired();
+
+  MachMap::iterator it = mach_map_.find(pid);
+  if (it == mach_map_.end()) {
+    // Do nothing for unknown pids.
+    LOG(ERROR) << "Unknown process " << pid << " is sending Mach IPC messages!";
+    return;
+  }
+
+  DCHECK(it->second == MACH_PORT_NULL);
+  if (it->second == MACH_PORT_NULL)
+    it->second = task_port;
+}
+
+void MachBroker::InvalidatePid(base::ProcessHandle pid) {
+  base::AutoLock lock(lock_);
+  MachBroker::MachMap::iterator it = mach_map_.find(pid);
+  if (it == mach_map_.end())
+    return;
+
+  kern_return_t kr = mach_port_deallocate(mach_task_self(),
+                                          it->second);
+  LOG_IF(WARNING, kr != KERN_SUCCESS)
+     << "Failed to mach_port_deallocate mach task " << it->second
+     << ", error " << MachErrorCode(kr);
+  mach_map_.erase(it);
+}
+
+// static
+std::string MachBroker::GetMachPortName() {
+  const CommandLine* command_line = CommandLine::ForCurrentProcess();
+  const bool is_child = command_line->HasSwitch(switches::kProcessType);
+
+  // In non-browser (child) processes, use the parent's pid.
+  const pid_t pid = is_child ? getppid() : getpid();
+  return base::StringPrintf("%s.rohitfork.%d", base::mac::BaseBundleID(), pid);
+}
+
+void MachBroker::RegisterNotifications() {
+  registrar_.Add(this, NOTIFICATION_RENDERER_PROCESS_CLOSED,
+                 NotificationService::AllBrowserContextsAndSources());
+  registrar_.Add(this, NOTIFICATION_RENDERER_PROCESS_TERMINATED,
+                 NotificationService::AllBrowserContextsAndSources());
+
+  // No corresponding StopObservingBrowserChildProcesses,
+  // we leak this singleton.
+  BrowserChildProcessObserver::Add(this);
+}
+
+}  // namespace content
diff --git a/content/browser/mach_broker_mac_unittest.cc b/content/browser/mach_broker_mac_unittest.cc
index 7bd88a5..a7eca4f 100644
--- a/content/browser/mach_broker_mac_unittest.cc
+++ b/content/browser/mach_broker_mac_unittest.cc
@@ -17,11 +17,15 @@
     broker_.AddPlaceholderForPid(pid);
   }
 
+  void InvalidatePid(base::ProcessHandle pid) {
+    broker_.InvalidatePid(pid);
+  }
+
   // Helper function to acquire/release locks and call |FinalizePid()|.
   void FinalizePid(base::ProcessHandle pid,
-                   const MachBroker::MachInfo& mach_info) {
+                   mach_port_t task_port) {
     base::AutoLock lock(broker_.GetLock());
-    broker_.FinalizePid(pid, mach_info);
+    broker_.FinalizePid(pid, task_port);
   }
 
  protected:
@@ -39,7 +43,7 @@
   EXPECT_EQ(0u, broker_.TaskForPid(1));
 
   // Finalize PID 1.
-  FinalizePid(1, MachBroker::MachInfo().SetTask(100u));
+  FinalizePid(1, 100u);
   EXPECT_EQ(100u, broker_.TaskForPid(1));
 
   // Should be no entry for PID 2.
@@ -48,16 +52,16 @@
 
 TEST_F(MachBrokerTest, Invalidate) {
   AddPlaceholderForPid(1);
-  FinalizePid(1, MachBroker::MachInfo().SetTask(100u));
+  FinalizePid(1, 100u);
 
   EXPECT_EQ(100u, broker_.TaskForPid(1));
-  broker_.InvalidatePid(1u);
+  InvalidatePid(1u);
   EXPECT_EQ(0u, broker_.TaskForPid(1));
 }
 
 TEST_F(MachBrokerTest, FinalizeUnknownPid) {
   // Finalizing an entry for an unknown pid should not add it to the map.
-  FinalizePid(1u, MachBroker::MachInfo().SetTask(100u));
+  FinalizePid(1u, 100u);
   EXPECT_EQ(0u, broker_.TaskForPid(1u));
 }
 
diff --git a/content/browser/media/encrypted_media_browsertest.cc b/content/browser/media/encrypted_media_browsertest.cc
index c41b955..34cbd65 100644
--- a/content/browser/media/encrypted_media_browsertest.cc
+++ b/content/browser/media/encrypted_media_browsertest.cc
@@ -21,13 +21,22 @@
 #include "media/base/media_switches.h"
 #include "webkit/media/crypto/key_systems.h"
 
+#include "widevine_cdm_version.h"  // In SHARED_INTERMEDIATE_DIR.
+
+#if defined(WIDEVINE_CDM_AVAILABLE) && defined(OS_LINUX)
+#include <gnu/libc-version.h>
+#endif  // defined(WIDEVINE_CDM_AVAILABLE) && defined(OS_LINUX)
+
 // Platform-specific filename relative to the chrome executable.
 #if defined(OS_WIN)
-static const wchar_t kLibraryName[] = L"clearkeycdmadapter.dll";
+static const char kClearKeyLibraryName[] = "clearkeycdmadapter.dll";
+static const char kWidevineLibraryName[] = "widevinecdmadapter.dll";
 #elif defined(OS_MACOSX)
-static const char kLibraryName[] = "clearkeycdmadapter.plugin";
+static const char kClearKeyLibraryName[] = "clearkeycdmadapter.plugin";
+static const char kWidevineLibraryName[] = "widevinecdmadapter.plugin";
 #elif defined(OS_POSIX)
-static const char kLibraryName[] = "libclearkeycdmadapter.so";
+static const char kClearKeyLibraryName[] = "libclearkeycdmadapter.so";
+static const char kWidevineLibraryName[] = "libwidevinecdmadapter.so";
 #endif
 
 // Available key systems.
@@ -35,12 +44,17 @@
 static const char kExternalClearKeyKeySystem[] =
     "org.chromium.externalclearkey";
 
+// Supported media types.
 static const char kWebMAudioOnly[] = "audio/webm; codecs=\"vorbis\"";
 static const char kWebMVideoOnly[] = "video/webm; codecs=\"vp8\"";
 static const char kWebMAudioVideo[] = "video/webm; codecs=\"vorbis, vp8\"";
 static const char kMP4AudioOnly[] = "audio/mp4; codecs=\"mp4a.40.2\"";
 static const char kMP4VideoOnly[] = "video/mp4; codecs=\"avc1.4D4041\"";
 
+// Common test expectations.
+const string16 kExpectedEnded = ASCIIToUTF16("ENDED");
+const string16 kExpectedWebKitError = ASCIIToUTF16("WEBKITKEYERROR");
+
 namespace content {
 
 class EncryptedMediaTest : public testing::WithParamInterface<const char*>,
@@ -48,14 +62,16 @@
  public:
   void TestSimplePlayback(const char* encrypted_media, const char* media_type,
                           const char* key_system, const string16 expectation) {
-    PlayEncryptedMedia("encrypted_media_player.html", encrypted_media,
-                       media_type, key_system, expectation);
+    ASSERT_NO_FATAL_FAILURE(
+        PlayEncryptedMedia("encrypted_media_player.html", encrypted_media,
+                           media_type, key_system, expectation));
   }
 
   void TestFrameSizeChange(const char* key_system, const string16 expectation) {
-    PlayEncryptedMedia("encrypted_frame_size_change.html",
-                       "frame_size_change-av-enc-v.webm", kWebMAudioVideo,
-                       key_system, expectation);
+    ASSERT_NO_FATAL_FAILURE(
+        PlayEncryptedMedia("encrypted_frame_size_change.html",
+                           "frame_size_change-av-enc-v.webm", kWebMAudioVideo,
+                           key_system, expectation));
   }
 
   void PlayEncryptedMedia(const char* html_page, const char* media_file,
@@ -91,28 +107,73 @@
  protected:
   // Registers any CDM plugins not registered by default.
   virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
-    command_line->AppendSwitch(switches::kDisableAudio);
+    RegisterPepperPlugin(command_line, kClearKeyLibraryName,
+                         kExternalClearKeyKeySystem);
+  }
 
-    // Append the switch to register the Clear Key CDM plugin.
+  virtual void RegisterPepperPlugin(CommandLine* command_line,
+                                    const std::string& library_name,
+                                    const std::string& key_system) {
+    // Append the switch to register the Clear Key CDM Adapter.
     base::FilePath plugin_dir;
     EXPECT_TRUE(PathService::Get(base::DIR_MODULE, &plugin_dir));
-    base::FilePath plugin_lib = plugin_dir.Append(kLibraryName);
+#if defined(OS_WIN)
+    base::FilePath plugin_lib = plugin_dir.Append(ASCIIToWide(library_name));
+#else
+    base::FilePath plugin_lib = plugin_dir.Append(library_name);
+#endif
     EXPECT_TRUE(file_util::PathExists(plugin_lib));
     base::FilePath::StringType pepper_plugin = plugin_lib.value();
-    pepper_plugin.append(FILE_PATH_LITERAL(
-        "#Clear Key CDM#Clear Key CDM 0.1.0.0#0.1.0.0;"));
+    pepper_plugin.append(FILE_PATH_LITERAL("#CDM#0.1.0.0;"));
 #if defined(OS_WIN)
-      pepper_plugin.append(ASCIIToWide(
-          webkit_media::GetPluginType(kExternalClearKeyKeySystem)));
+    pepper_plugin.append(ASCIIToWide(webkit_media::GetPluginType(key_system)));
 #else
-      pepper_plugin.append(
-          webkit_media::GetPluginType(kExternalClearKeyKeySystem));
+    pepper_plugin.append(webkit_media::GetPluginType(key_system));
 #endif
     command_line->AppendSwitchNative(switches::kRegisterPepperPlugins,
                                      pepper_plugin);
   }
 };
 
+#if defined(WIDEVINE_CDM_AVAILABLE)
+class WVEncryptedMediaTest : public EncryptedMediaTest {
+ public:
+  // Tests that the following happen after trying to play encrypted media:
+  // - webkitneedkey event is fired.
+  // - webkitGenerateKeyRequest() does not fail.
+  // - webkitkeymessage is fired
+  // - webkitAddKey() generates a WebKitKeyError since no real WV key is added.
+  void TestSimplePlayback(const char* encrypted_media, const char* media_type,
+                          const char* key_system) {
+    // TODO(shadi): Remove after bots upgrade to precise.
+    // Don't run on lucid bots since the CDM is not compatible (glibc < 2.14)
+#if defined(OS_LINUX)
+    if(strcmp(gnu_get_libc_version(), "2.11.1") == 0) {
+      LOG(INFO) << "Skipping test; not supported on glibc version: "
+          << gnu_get_libc_version();
+      return;
+    }
+#endif  // defined(OS_LINUX)
+    EncryptedMediaTest::TestSimplePlayback(encrypted_media, media_type,
+                                           key_system, kExpectedWebKitError);
+    bool receivedKeyMessage = false;
+    EXPECT_TRUE(ExecuteScriptAndExtractBool(
+        shell()->web_contents(),
+        "window.domAutomationController.send(video.receivedKeyMessage);",
+        &receivedKeyMessage));
+    ASSERT_TRUE(receivedKeyMessage);
+  }
+
+ protected:
+  // Registers any CDM plugins not registered by default.
+  virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
+    command_line->AppendSwitch(switches::kAllowFileAccessFromFiles);
+    RegisterPepperPlugin(command_line, kWidevineLibraryName,
+                         kWidevineKeySystem);
+  }
+};
+#endif  // defined(WIDEVINE_CDM_AVAILABLE)
+
 INSTANTIATE_TEST_CASE_P(ClearKey, EncryptedMediaTest,
                         ::testing::Values(kClearKeyKeySystem));
 
@@ -122,44 +183,33 @@
 IN_PROC_BROWSER_TEST_F(EncryptedMediaTest, InvalidKeySystem) {
   const string16 kExpected = ASCIIToUTF16(
       StringToUpperASCII(std::string("GenerateKeyRequestException")));
-  ASSERT_NO_FATAL_FAILURE(
-      TestSimplePlayback("bear-320x240-av-enc_av.webm", kWebMAudioVideo,
-                         "com.example.invalid", kExpected));
+  TestSimplePlayback("bear-320x240-av-enc_av.webm", kWebMAudioVideo,
+                     "com.example.invalid", kExpected);
 }
 
 IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_AudioOnly_WebM) {
-  const string16 kExpected = ASCIIToUTF16("ENDED");
-  ASSERT_NO_FATAL_FAILURE(
-      TestSimplePlayback("bear-a-enc_a.webm", kWebMAudioOnly,
-                         GetParam(), kExpected));
+  TestSimplePlayback("bear-a-enc_a.webm", kWebMAudioOnly, GetParam(),
+                     kExpectedEnded);
 }
 
 IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_AudioClearVideo_WebM) {
-  const string16 kExpected = ASCIIToUTF16("ENDED");
-  ASSERT_NO_FATAL_FAILURE(
-      TestSimplePlayback("bear-320x240-av-enc_a.webm", kWebMAudioVideo,
-                         GetParam(), kExpected));
+  TestSimplePlayback("bear-320x240-av-enc_a.webm", kWebMAudioVideo, GetParam(),
+                     kExpectedEnded);
 }
 
 IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_VideoAudio_WebM) {
-  const string16 kExpected = ASCIIToUTF16("ENDED");
-  ASSERT_NO_FATAL_FAILURE(
-      TestSimplePlayback("bear-320x240-av-enc_av.webm", kWebMAudioVideo,
-                         GetParam(), kExpected));
+  TestSimplePlayback("bear-320x240-av-enc_av.webm", kWebMAudioVideo, GetParam(),
+                     kExpectedEnded);
 }
 
 IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_VideoOnly_WebM) {
-  const string16 kExpected = ASCIIToUTF16("ENDED");
-  ASSERT_NO_FATAL_FAILURE(
-      TestSimplePlayback("bear-320x240-v-enc_v.webm", kWebMVideoOnly,
-                         GetParam(), kExpected));
+  TestSimplePlayback("bear-320x240-v-enc_v.webm", kWebMVideoOnly, GetParam(),
+                     kExpectedEnded);
 }
 
 IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_VideoClearAudio_WebM) {
-  const string16 kExpected = ASCIIToUTF16("ENDED");
-  ASSERT_NO_FATAL_FAILURE(
-      TestSimplePlayback("bear-320x240-av-enc_v.webm", kWebMAudioVideo,
-                         GetParam(), kExpected));
+  TestSimplePlayback("bear-320x240-av-enc_v.webm", kWebMAudioVideo,GetParam(),
+                     kExpectedEnded);
 }
 
 IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, FrameChangeVideo) {
@@ -168,24 +218,61 @@
   if (base::win::GetVersion() < base::win::VERSION_VISTA)
     return;
 #endif
-  const string16 kExpected = ASCIIToUTF16("ENDED");
-  ASSERT_NO_FATAL_FAILURE(TestFrameSizeChange(GetParam(), kExpected));
+  TestFrameSizeChange(GetParam(), kExpectedEnded);
 }
 
 #if defined(GOOGLE_CHROME_BUILD) || defined(USE_PROPRIETARY_CODECS)
 IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_VideoOnly_MP4) {
-  const string16 kExpected = ASCIIToUTF16("ENDED");
-  ASSERT_NO_FATAL_FAILURE(
-      TestSimplePlayback("bear-640x360-v_frag-cenc.mp4", kMP4VideoOnly,
-                         GetParam(), kExpected));
+  TestSimplePlayback("bear-640x360-v_frag-cenc.mp4", kMP4VideoOnly, GetParam(),
+                     kExpectedEnded);
 }
 
 IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_AudioOnly_MP4) {
-  const string16 kExpected = ASCIIToUTF16("ENDED");
-  ASSERT_NO_FATAL_FAILURE(
-      TestSimplePlayback("bear-640x360-a_frag-cenc.mp4", kMP4AudioOnly,
-                         GetParam(), kExpected));
+  TestSimplePlayback("bear-640x360-a_frag-cenc.mp4", kMP4AudioOnly, GetParam(),
+                     kExpectedEnded);
 }
 #endif
 
+// Run only when WV CDM is available.
+#if defined(WIDEVINE_CDM_AVAILABLE)
+// See http://crbug.com/237636.
+#if !defined(DISABLE_WIDEVINE_CDM_BROWSERTESTS)
+IN_PROC_BROWSER_TEST_F(WVEncryptedMediaTest, Playback_AudioOnly_WebM) {
+  TestSimplePlayback("bear-a-enc_a.webm", kWebMAudioOnly, kWidevineKeySystem);
+}
+
+IN_PROC_BROWSER_TEST_F(WVEncryptedMediaTest, Playback_AudioClearVideo_WebM) {
+  TestSimplePlayback("bear-320x240-av-enc_a.webm", kWebMAudioVideo,
+                     kWidevineKeySystem);
+}
+
+IN_PROC_BROWSER_TEST_F(WVEncryptedMediaTest, Playback_VideoAudio_WebM) {
+  TestSimplePlayback("bear-320x240-av-enc_av.webm", kWebMAudioVideo,
+                     kWidevineKeySystem);
+}
+
+IN_PROC_BROWSER_TEST_F(WVEncryptedMediaTest, Playback_VideoOnly_WebM) {
+  TestSimplePlayback("bear-320x240-v-enc_v.webm", kWebMVideoOnly,
+                     kWidevineKeySystem);
+}
+
+IN_PROC_BROWSER_TEST_F(WVEncryptedMediaTest, Playback_VideoClearAudio_WebM) {
+  TestSimplePlayback("bear-320x240-av-enc_v.webm", kWebMAudioVideo,
+                     kWidevineKeySystem);
+}
+
+#if defined(GOOGLE_CHROME_BUILD) || defined(USE_PROPRIETARY_CODECS)
+IN_PROC_BROWSER_TEST_F(WVEncryptedMediaTest, Playback_VideoOnly_MP4) {
+  TestSimplePlayback("bear-640x360-v_frag-cenc.mp4", kMP4VideoOnly,
+                     kWidevineKeySystem);
+}
+
+IN_PROC_BROWSER_TEST_F(WVEncryptedMediaTest, Playback_AudioOnly_MP4) {
+  TestSimplePlayback("bear-640x360-a_frag-cenc.mp4", kMP4AudioOnly,
+                     kWidevineKeySystem);
+}
+#endif  // defined(GOOGLE_CHROME_BUILD) || defined(USE_PROPRIETARY_CODECS)
+#endif  // !defined(DISABLE_WIDEVINE_CDM_BROWSERTESTS)
+#endif  // defined(WIDEVINE_CDM_AVAILABLE)
+
 }  // namespace content
diff --git a/content/browser/media/media_internals.cc b/content/browser/media/media_internals.cc
index 6b55d2a..f69169e 100644
--- a/content/browser/media/media_internals.cc
+++ b/content/browser/media/media_internals.cc
@@ -48,18 +48,21 @@
                     "volume", new base::FundamentalValue(volume));
 }
 
-void MediaInternals::OnMediaEvent(
-    int render_process_id, const media::MediaLogEvent& event) {
+void MediaInternals::OnMediaEvents(
+    int render_process_id, const std::vector<media::MediaLogEvent>& events) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
 
   // Notify observers that |event| has occured.
-  base::DictionaryValue dict;
-  dict.SetInteger("renderer", render_process_id);
-  dict.SetInteger("player", event.id);
-  dict.SetString("type", media::MediaLog::EventTypeToString(event.type));
-  dict.SetDouble("time", event.time.ToDoubleT());
-  dict.Set("params", event.params.DeepCopy());
-  SendUpdate("media.onMediaEvent", &dict);
+  for (std::vector<media::MediaLogEvent>::const_iterator event = events.begin();
+      event != events.end(); ++event) {
+    base::DictionaryValue dict;
+    dict.SetInteger("renderer", render_process_id);
+    dict.SetInteger("player", event->id);
+    dict.SetString("type", media::MediaLog::EventTypeToString(event->type));
+    dict.SetDouble("time", event->time.ToDoubleT());
+    dict.Set("params", event->params.DeepCopy());
+    SendUpdate("media.onMediaEvent", &dict);
+  }
 }
 
 void MediaInternals::AddUpdateCallback(const UpdateCallback& callback) {
diff --git a/content/browser/media/media_internals.h b/content/browser/media/media_internals.h
index 5c901d5..170587a 100644
--- a/content/browser/media/media_internals.h
+++ b/content/browser/media/media_internals.h
@@ -39,8 +39,8 @@
   virtual void OnSetAudioStreamPlaying(void* host, int stream_id,
                                        bool playing);
 
-  // Called when the status of an audio stream is set to "created", "flushed",
-  // "closed", or "error".
+  // Called when the status of an audio stream is set to "created", "closed", or
+  // "error".
   virtual void OnSetAudioStreamStatus(void* host, int stream_id,
                                       const std::string& status);
 
@@ -49,8 +49,8 @@
                                       double volume);
 
   // Called when a MediaEvent occurs.
-  virtual void OnMediaEvent(int render_process_id,
-                            const media::MediaLogEvent& event);
+  virtual void OnMediaEvents(int render_process_id,
+                             const std::vector<media::MediaLogEvent>& events);
 
   // Called with the update string.
   typedef base::Callback<void(const string16&)> UpdateCallback;
diff --git a/content/browser/media/media_internals_proxy.cc b/content/browser/media/media_internals_proxy.cc
index 5d837d6..0c214d1 100644
--- a/content/browser/media/media_internals_proxy.cc
+++ b/content/browser/media/media_internals_proxy.cc
@@ -152,12 +152,11 @@
 
   // Send the updates to the page in kMediaInternalsProxyEventDelayMilliseconds
   // if an update is not already pending.
-  if (!pending_net_updates_.get()) {
+  if (!pending_net_updates_) {
     pending_net_updates_.reset(new base::ListValue());
-    MessageLoop::current()->PostDelayedTask(
+    base::MessageLoop::current()->PostDelayedTask(
         FROM_HERE,
-        base::Bind(
-            &MediaInternalsProxy::SendNetEventsOnUIThread, this),
+        base::Bind(&MediaInternalsProxy::SendNetEventsOnUIThread, this),
         base::TimeDelta::FromMilliseconds(
             kMediaInternalsProxyEventDelayMilliseconds));
   }
diff --git a/content/browser/media/media_internals_ui.cc b/content/browser/media/media_internals_ui.cc
index f35395e..812825d 100644
--- a/content/browser/media/media_internals_ui.cc
+++ b/content/browser/media/media_internals_ui.cc
@@ -16,7 +16,7 @@
 
 WebUIDataSource* CreateMediaInternalsHTMLSource() {
   WebUIDataSource* source =
-      WebUIDataSource::Create(chrome::kChromeUIMediaInternalsHost);
+      WebUIDataSource::Create(kChromeUIMediaInternalsHost);
 
   source->SetJsonPath("strings.js");
   source->AddResourcePath("media_internals.js", IDR_MEDIA_INTERNALS_JS);
diff --git a/content/browser/media/media_internals_unittest.cc b/content/browser/media/media_internals_unittest.cc
index 0db2580..5edd55d 100644
--- a/content/browser/media/media_internals_unittest.cc
+++ b/content/browser/media/media_internals_unittest.cc
@@ -41,7 +41,7 @@
 
   void UpdateItem(const std::string& item, const std::string& property,
                   base::Value* value) {
-    internals_->UpdateItem("", item, property, value);
+    internals_->UpdateItem(std::string(), item, property, value);
   }
 
   void SendUpdate(const std::string& function, base::Value* value) {
@@ -53,7 +53,7 @@
     internals_.reset(new MediaInternals());
   }
 
-  MessageLoop loop_;
+  base::MessageLoop loop_;
   TestBrowserThread io_thread_;
   scoped_ptr<MediaInternals> internals_;
 };
diff --git a/content/browser/media/webrtc_browsertest.cc b/content/browser/media/webrtc_browsertest.cc
index e0d086d..3ae9371 100644
--- a/content/browser/media/webrtc_browsertest.cc
+++ b/content/browser/media/webrtc_browsertest.cc
@@ -10,7 +10,7 @@
 #include "content/shell/shell.h"
 #include "content/test/content_browser_test.h"
 #include "content/test/content_browser_test_utils.h"
-#include "net/test/test_server.h"
+#include "net/test/spawned_test_server.h"
 
 #if defined(OS_WIN)
 #include "base/win/windows_version.h"
@@ -47,7 +47,7 @@
 // see that the success callback is called. If the error callback is called or
 // none of the callbacks are called the tests will simply time out and fail.
 IN_PROC_BROWSER_TEST_F(WebrtcBrowserTest, GetVideoStreamAndStop) {
-  GURL url(test_server()->GetURL("files/media/getusermedia_and_stop.html"));
+  GURL url(test_server()->GetURL("files/media/getusermedia.html"));
   NavigateToURL(shell(), url);
 
   EXPECT_TRUE(ExecuteJavascript("getUserMedia({video: true});"));
@@ -56,7 +56,7 @@
 }
 
 IN_PROC_BROWSER_TEST_F(WebrtcBrowserTest, GetAudioAndVideoStreamAndStop) {
-  GURL url(test_server()->GetURL("files/media/getusermedia_and_stop.html"));
+  GURL url(test_server()->GetURL("files/media/getusermedia.html"));
   NavigateToURL(shell(), url);
 
   EXPECT_TRUE(ExecuteJavascript("getUserMedia({video: true, audio: true});"));
@@ -64,6 +64,15 @@
   ExpectTitle("OK");
 }
 
+IN_PROC_BROWSER_TEST_F(WebrtcBrowserTest, GetAudioAndVideoStreamAndClone) {
+  GURL url(test_server()->GetURL("files/media/getusermedia.html"));
+  NavigateToURL(shell(), url);
+
+  EXPECT_TRUE(ExecuteJavascript("getUserMediaAndClone();"));
+
+  ExpectTitle("OK");
+}
+
 // These tests will make a complete PeerConnection-based call and verify that
 // video is playing for the call.
 IN_PROC_BROWSER_TEST_F(WebrtcBrowserTest, CanSetupVideoCall) {
@@ -90,8 +99,7 @@
       ExecuteJavascript("callAndSendDtmf('123,abc');"));
 }
 
-// This test is flaky on Win XP, Win7 and Linux Precise. Disabling on all just
-// in case.
+// TODO(miu): Test is flaky.  http://crbug.com/236102
 IN_PROC_BROWSER_TEST_F(WebrtcBrowserTest,
                        DISABLED_CanMakeEmptyCallThenAddStreamsAndRenegotiate) {
   GURL url(test_server()->GetURL("files/media/peerconnection-call.html"));
@@ -108,8 +116,16 @@
 // MSID and bundle attribute from the initial offer to verify that
 // video is playing for the call even if the initiating client don't support
 // MSID. http://tools.ietf.org/html/draft-alvestrand-rtcweb-msid-02
+// Disabled for win7_aura, see http://crbug.com/235089.
+#if defined(OS_WIN) && defined(USE_AURA)
+#define MAYBE_CanSetupAudioAndVideoCallWithoutMsidAndBundle\
+        DISABLED_CanSetupAudioAndVideoCallWithoutMsidAndBundle
+#else
+#define MAYBE_CanSetupAudioAndVideoCallWithoutMsidAndBundle\
+        CanSetupAudioAndVideoCallWithoutMsidAndBundle
+#endif
 IN_PROC_BROWSER_TEST_F(WebrtcBrowserTest,
-                       CanSetupAudioAndVideoCallWithoutMsidAndBundle) {
+                       MAYBE_CanSetupAudioAndVideoCallWithoutMsidAndBundle) {
   GURL url(test_server()->GetURL("files/media/peerconnection-call.html"));
   NavigateToURL(shell(), url);
 
@@ -139,7 +155,7 @@
 
 // This test will make a PeerConnection-based call and test an unreliable text
 // dataChannel and later add an audio and video track.
-// Flaky. http://crbug.com/175683
+// TODO(perkj): Fix flakiness. See: http://crbug.com/227409
 IN_PROC_BROWSER_TEST_F(WebrtcBrowserTest,
                        DISABLED_CallWithDataAndLaterAddMedia) {
   GURL url(test_server()->GetURL("files/media/peerconnection-call.html"));
@@ -149,5 +165,30 @@
   ExpectTitle("OK");
 }
 
-}  // namespace content
+// This test will make a PeerConnection-based call and send a new Video
+// MediaStream that has been created based on a MediaStream created with
+// getUserMedia.
+IN_PROC_BROWSER_TEST_F(WebrtcBrowserTest, CallWithNewVideoMediaStream) {
+  GURL url(test_server()->GetURL("files/media/peerconnection-call.html"));
+  NavigateToURL(shell(), url);
 
+  EXPECT_TRUE(ExecuteJavascript("callWithNewVideoMediaStream();"));
+  ExpectTitle("OK");
+}
+
+// This test will make a PeerConnection-based call and send a new Video
+// MediaStream that has been created based on a MediaStream created with
+// getUserMedia. When video is flowing, the VideoTrack is removed and an
+// AudioTrack is added instead.
+// TODO(phoglund): This test is manual since not all buildbots has an audio
+// input.
+IN_PROC_BROWSER_TEST_F(WebrtcBrowserTest, MANUAL_CallAndModifyStream) {
+  GURL url(test_server()->GetURL("files/media/peerconnection-call.html"));
+  NavigateToURL(shell(), url);
+
+  EXPECT_TRUE(
+      ExecuteJavascript("callWithNewVideoMediaStreamLaterSwitchToAudio();"));
+  ExpectTitle("OK");
+}
+
+}  // namespace content
diff --git a/content/browser/media/webrtc_internals.cc b/content/browser/media/webrtc_internals.cc
index 34703f5..efdba58 100644
--- a/content/browser/media/webrtc_internals.cc
+++ b/content/browser/media/webrtc_internals.cc
@@ -32,7 +32,7 @@
 
 }  // namespace
 
-WebRTCInternals::WebRTCInternals() {
+WebRTCInternals::WebRTCInternals() : is_recording_rtp_(false) {
   registrar_.Add(this, NOTIFICATION_RENDERER_PROCESS_TERMINATED,
                  NotificationService::AllBrowserContextsAndSources());
 
@@ -47,12 +47,12 @@
   return Singleton<WebRTCInternals>::get();
 }
 
-void WebRTCInternals::AddPeerConnection(int render_process_id,
-                                        ProcessId pid,
-                                        int lid,
-                                        const string& url,
-                                        const string& servers,
-                                        const string& constraints) {
+void WebRTCInternals::OnAddPeerConnection(int render_process_id,
+                                          ProcessId pid,
+                                          int lid,
+                                          const string& url,
+                                          const string& servers,
+                                          const string& constraints) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
   DictionaryValue* dict = new DictionaryValue();
@@ -71,7 +71,7 @@
     SendUpdate("addPeerConnection", dict);
 }
 
-void WebRTCInternals::RemovePeerConnection(ProcessId pid, int lid) {
+void WebRTCInternals::OnRemovePeerConnection(ProcessId pid, int lid) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   for (size_t i = 0; i < peer_connection_data_.GetSize(); ++i) {
     DictionaryValue* dict = NULL;
@@ -97,7 +97,7 @@
   }
 }
 
-void WebRTCInternals::UpdatePeerConnection(
+void WebRTCInternals::OnUpdatePeerConnection(
     ProcessId pid, int lid, const string& type, const string& value) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
@@ -138,8 +138,8 @@
   }
 }
 
-void WebRTCInternals::AddStats(base::ProcessId pid, int lid,
-                               const base::ListValue& value) {
+void WebRTCInternals::OnAddStats(base::ProcessId pid, int lid,
+                                 const base::ListValue& value) {
   if (observers_.size() == 0)
     return;
 
@@ -171,6 +171,20 @@
     SendUpdate("updateAllPeerConnections", &peer_connection_data_);
 }
 
+void WebRTCInternals::StartRtpRecording() {
+  if (!is_recording_rtp_) {
+    is_recording_rtp_ = true;
+    // TODO(justinlin): start RTP recording.
+  }
+}
+
+void WebRTCInternals::StopRtpRecording() {
+  if (is_recording_rtp_) {
+    is_recording_rtp_ = false;
+    // TODO(justinlin): stop RTP recording.
+  }
+}
+
 void WebRTCInternals::SendUpdate(const string& command, Value* value) {
   DCHECK_GT(observers_.size(), (size_t)0);
 
@@ -219,4 +233,13 @@
   }
 }
 
+// TODO(justlin): Calls this method as necessary to update the recording status
+// UI.
+void WebRTCInternals::SendRtpRecordingUpdate() {
+  DCHECK(is_recording_rtp_);
+  DictionaryValue update;
+  // TODO(justinlin): Fill in |update| with values as appropriate.
+  SendUpdate("updateDumpStatus", &update);
+}
+
 }  // namespace content
diff --git a/content/browser/media/webrtc_internals.h b/content/browser/media/webrtc_internals.h
index 7baff52..c5b110e 100644
--- a/content/browser/media/webrtc_internals.h
+++ b/content/browser/media/webrtc_internals.h
@@ -22,7 +22,7 @@
 // forwards the data to WebRTCInternalsUIObserver and
 // sends data collecting commands to the renderers.
 class CONTENT_EXPORT WebRTCInternals : public BrowserChildProcessObserver,
-                                       public NotificationObserver{
+                                       public NotificationObserver {
  public:
   static WebRTCInternals* GetInstance();
 
@@ -34,29 +34,29 @@
   // identify a PeerConnection, |url| is the url of the tab owning the
   // PeerConnection, |servers| is the servers configuration, |constraints| is
   // the media constraints used to initialize the PeerConnection.
-  void AddPeerConnection(int render_process_id,
-                         base::ProcessId pid,
-                         int lid,
-                         const std::string& url,
-                         const std::string& servers,
-                         const std::string& constraints);
+  void OnAddPeerConnection(int render_process_id,
+                           base::ProcessId pid,
+                           int lid,
+                           const std::string& url,
+                           const std::string& servers,
+                           const std::string& constraints);
 
   // This method is called when PeerConnection is destroyed.
   // |pid| is the renderer process id, |lid| is the renderer local id.
-  void RemovePeerConnection(base::ProcessId pid, int lid);
+  void OnRemovePeerConnection(base::ProcessId pid, int lid);
 
   // This method is called when a PeerConnection is updated.
   // |pid| is the renderer process id, |lid| is the renderer local id,
   // |type| is the update type, |value| is the detail of the update.
-  void UpdatePeerConnection(base::ProcessId pid,
-                            int lid,
-                            const std::string& type,
-                            const std::string& value);
+  void OnUpdatePeerConnection(base::ProcessId pid,
+                              int lid,
+                              const std::string& type,
+                              const std::string& value);
 
   // This method is called when results from PeerConnectionInterface::GetStats
   // are available. |pid| is the renderer process id, |lid| is the renderer
   // local id, |value| is the list of stats reports.
-  void AddStats(base::ProcessId pid, int lid, const base::ListValue& value);
+  void OnAddStats(base::ProcessId pid, int lid, const base::ListValue& value);
 
   // Methods for adding or removing WebRTCInternalsUIObserver.
   void AddObserver(WebRTCInternalsUIObserver *observer);
@@ -65,6 +65,10 @@
   // Sends all update data to the observers.
   void SendAllUpdates();
 
+  // Tells the renderer processes to start or stop recording RTP packets.
+  void StartRtpRecording();
+  void StopRtpRecording();
+
  private:
   friend struct DefaultSingletonTraits<WebRTCInternals>;
 
@@ -85,6 +89,8 @@
   // Called when a renderer exits (including crashes).
   void OnRendererExit(int render_process_id);
 
+  void SendRtpRecordingUpdate();
+
   ObserverList<WebRTCInternalsUIObserver> observers_;
 
   // |peer_connection_data_| is a list containing all the PeerConnection
@@ -102,6 +108,8 @@
   base::ListValue peer_connection_data_;
 
   NotificationRegistrar registrar_;
+
+  bool is_recording_rtp_;
 };
 
 }  // namespace content
diff --git a/content/browser/media/webrtc_internals_browsertest.cc b/content/browser/media/webrtc_internals_browsertest.cc
index a497c3d..5dcb3a9 100644
--- a/content/browser/media/webrtc_internals_browsertest.cc
+++ b/content/browser/media/webrtc_internals_browsertest.cc
@@ -2,16 +2,47 @@
 // 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/time.h"
 #include "base/utf_string_conversions.h"
+#include "content/public/common/content_switches.h"
 #include "content/public/test/browser_test_utils.h"
 #include "content/shell/shell.h"
 #include "content/test/content_browser_test.h"
 #include "content/test/content_browser_test_utils.h"
+#include "net/test/spawned_test_server.h"
 
 using std::string;
 namespace content {
 
+struct SsrcEntry {
+  string GetSsrcAttributeString() const {
+    std::stringstream ss;
+    ss << "a=ssrc:" << id;
+    std::map<string, string>::const_iterator iter;
+    for (iter = properties.begin(); iter != properties.end(); ++iter) {
+      ss << " " << iter->first << ":" << iter->second;
+    }
+    return ss.str();
+  }
+
+  string GetAsJSON() const {
+    std::stringstream ss;
+    ss << "{";
+    std::map<string, string>::const_iterator iter;
+    for (iter = properties.begin(); iter != properties.end(); ++iter) {
+      if (iter != properties.begin())
+        ss << ",";
+      ss << "\"" << iter->first << "\":\"" << iter->second << "\"";
+    }
+    ss << "}";
+    return ss.str();
+  }
+
+  string id;
+  std::map<string, string> properties;
+};
+
 struct EventEntry {
   string type;
   string value;
@@ -22,7 +53,7 @@
     std::stringstream ss;
     ss << "{timestamp:" << timestamp << ", values:[";
     std::map<string, string>::const_iterator iter;
-    for (iter = values.begin(); iter != values.end(); iter++) {
+    for (iter = values.begin(); iter != values.end(); ++iter) {
       ss << "'" << iter->first << "','" << iter->second << "',";
     }
     ss << "]}";
@@ -36,8 +67,7 @@
 struct StatsEntry {
   string type;
   string id;
-  StatsUnit local;
-  StatsUnit remote;
+  StatsUnit stats;
 };
 
 typedef std::map<string, std::vector<string> > StatsMap;
@@ -59,7 +89,7 @@
 
   string getLogIdString() const {
     std::stringstream ss;
-    ss << pid_ << "-" << lid_ << "-log";
+    ss << pid_ << "-" << lid_ << "-update-log";
     return ss.str();
   }
 
@@ -91,11 +121,26 @@
   WebRTCInternalsBrowserTest() {}
   virtual ~WebRTCInternalsBrowserTest() {}
 
+  virtual void SetUpOnMainThread() OVERRIDE {
+    // We need fake devices in this test since we want to run on naked VMs. We
+    // assume this switch is set by default in content_browsertests.
+    ASSERT_TRUE(CommandLine::ForCurrentProcess()->HasSwitch(
+        switches::kUseFakeDeviceForMediaStream));
+
+    ASSERT_TRUE(test_server()->Start());
+  }
+
  protected:
   bool ExecuteJavascript(const string& javascript) {
     return ExecuteScript(shell()->web_contents(), javascript);
   }
 
+  void ExpectTitle(const std::string& expected_title) const {
+    string16 expected_title16(ASCIIToUTF16(expected_title));
+    TitleWatcher title_watcher(shell()->web_contents(), expected_title16);
+    EXPECT_EQ(expected_title16, title_watcher.WaitAndGetTitle());
+  }
+
   // Execute the javascript of addPeerConnection.
   void ExecuteAddPeerConnectionJs(const PeerConnectionEntry& pc) {
     std::stringstream ss;
@@ -145,12 +190,10 @@
       std::stringstream ss;
       ss << "var row = $('" << log_id << "').rows[" << (i + 1) << "];"
             "var cell = row.lastChild;"
-            "var type = cell.firstChild.textContent;"
-            "var value = cell.lastChild.lastChild.value;"
-            "window.domAutomationController.send(type + ':' + value);";
+            "window.domAutomationController.send(cell.firstChild.textContent);";
       ASSERT_TRUE(ExecuteScriptAndExtractString(
           shell()->web_contents(), ss.str(), &result));
-      EXPECT_EQ(pc.events_[i].type + ":" + pc.events_[i].value, result);
+      EXPECT_EQ(pc.events_[i].type + pc.events_[i].value, result);
     }
   }
 
@@ -170,23 +213,18 @@
   // Execute addStats and verifies that the stats table has the right content.
   void ExecuteAndVerifyAddStats(
       PeerConnectionEntry& pc, const string& type, const string& id,
-      StatsUnit& local, StatsUnit& remote) {
-    StatsEntry entry = {type, id, local, remote};
+      StatsUnit& stats) {
+    StatsEntry entry = {type, id, stats};
 
     // Adds each new value to the map of stats history.
     std::map<string, string>::iterator iter;
-    for (iter = local.values.begin(); iter != local.values.end(); iter++) {
+    for (iter = stats.values.begin(); iter != stats.values.end(); iter++) {
       pc.stats_[type + "-" + id][iter->first].push_back(iter->second);
     }
-    for (iter = remote.values.begin(); iter != remote.values.end(); iter++) {
-      pc.stats_[type + "-" + id][iter->first].push_back(iter->second);
-    }
-
     std::stringstream ss;
     ss << "{pid:" << pc.pid_ << ", lid:" << pc.lid_ << ","
            "reports:[" << "{id:'" << id << "', type:'" << type << "', "
-                           "local:" << local.GetString() << ", "
-                           "remote:" << remote.GetString() << "}]}";
+                           "stats:" << stats.GetString() << "}]}";
 
     ASSERT_TRUE(ExecuteJavascript("addStats(" + ss.str() + ")"));
     VerifyStatsTable(pc, entry);
@@ -195,18 +233,14 @@
 
   // Verifies that the stats table has the right content.
   void VerifyStatsTable(const PeerConnectionEntry& pc,
-                       const StatsEntry& report) {
+                        const StatsEntry& report) {
     string table_id =
         pc.getIdString() + "-table-" + report.type + "-" + report.id;
     VerifyElementWithId(table_id);
 
     std::map<string, string>::const_iterator iter;
-    for (iter = report.local.values.begin();
-         iter != report.local.values.end(); iter++) {
-      VerifyStatsTableRow(table_id, iter->first, iter->second);
-    }
-    for (iter = report.remote.values.begin();
-         iter != report.remote.values.end(); iter++) {
+    for (iter = report.stats.values.begin();
+         iter != report.stats.values.end(); iter++) {
       VerifyStatsTableRow(table_id, iter->first, iter->second);
     }
   }
@@ -254,7 +288,7 @@
     ASSERT_TRUE(ExecuteScriptAndExtractBool(
         shell()->web_contents(),
         "window.domAutomationController.send("
-        "   graphViews['" + graph_id + "'] != null)",
+           "graphViews['" + graph_id + "'] != null)",
         &result));
     EXPECT_TRUE(result);
 
@@ -267,6 +301,17 @@
         shell()->web_contents(), ss.str(), &actual_value));
     EXPECT_EQ(value, actual_value);
   }
+
+  // Get the JSON string of the ssrc info from the page.
+  string GetSsrcInfo(const string& ssrc_id) {
+    string result;
+    EXPECT_TRUE(ExecuteScriptAndExtractString(
+        shell()->web_contents(),
+        "window.domAutomationController.send(JSON.stringify("
+           "ssrcInfoManager.streamInfoContainer_['" + ssrc_id + "']))",
+        &result));
+    return result;
+  }
 };
 
 IN_PROC_BROWSER_TEST_F(WebRTCInternalsBrowserTest, AddAndRemovePeerConnection) {
@@ -321,8 +366,21 @@
   PeerConnectionEntry pc_2(1, 1);
   ExecuteAddPeerConnectionJs(pc_2);
 
-  ExecuteAndVerifyUpdatePeerConnection(pc_2, "e2", "v2");
-  ExecuteAndVerifyUpdatePeerConnection(pc_2, "e3", "v3");
+  SsrcEntry ssrc1, ssrc2;
+  ssrc1.id = "ssrcid1";
+  ssrc1.properties["msid"] = "mymsid";
+  ssrc2.id = "ssrcid2";
+  ssrc2.properties["label"] = "mylabel";
+  ssrc2.properties["cname"] = "mycname";
+
+  ExecuteAndVerifyUpdatePeerConnection(pc_2, "setRemoteDescription",
+      ssrc1.GetSsrcAttributeString());
+
+  ExecuteAndVerifyUpdatePeerConnection(pc_2, "setLocalDescription",
+      ssrc2.GetSsrcAttributeString());
+
+  EXPECT_EQ(ssrc1.GetAsJSON(), GetSsrcInfo(ssrc1.id));
+  EXPECT_EQ(ssrc2.GetAsJSON(), GetSsrcInfo(ssrc2.id));
 }
 
 // Tests that adding random named stats updates the dataSeries and graphs.
@@ -335,21 +393,18 @@
 
   const string type = "ssrc";
   const string id = "1234";
-  StatsUnit local = {FAKE_TIME_STAMP};
-  local.values["bitrate"] = "2000";
-  local.values["framerate"] = "30";
-  StatsUnit remote = {FAKE_TIME_STAMP};
-  remote.values["jitter"] = "1";
-  remote.values["rtt"] = "20";
+  StatsUnit stats = {FAKE_TIME_STAMP};
+  stats.values["bitrate"] = "2000";
+  stats.values["framerate"] = "30";
 
   // Add new stats and verify the stats table and graphs.
-  ExecuteAndVerifyAddStats(pc, type, id, local, remote);
+  ExecuteAndVerifyAddStats(pc, type, id, stats);
   VerifyStatsGraph(pc);
 
   // Update existing stats and verify the stats table and graphs.
-  local.values["bitrate"] = "2001";
-  local.values["framerate"] = "31";
-  ExecuteAndVerifyAddStats(pc, type, id, local, remote);
+  stats.values["bitrate"] = "2001";
+  stats.values["framerate"] = "31";
+  ExecuteAndVerifyAddStats(pc, type, id, stats);
   VerifyStatsGraph(pc);
 }
 
@@ -361,15 +416,15 @@
   PeerConnectionEntry pc(1, 0);
   ExecuteAddPeerConnectionJs(pc);
 
-  StatsUnit local = {FAKE_TIME_STAMP};
-  local.values["googAvailableSendBandwidth"] = "1000000";
-  local.values["googTargetEncBitrate"] = "1000";
-  local.values["googActualEncBitrate"] = "1000000";
-  local.values["googRetransmitBitrate"] = "10";
-  local.values["googTransmitBitrate"] = "1000000";
+  StatsUnit stats = {FAKE_TIME_STAMP};
+  stats.values["googAvailableSendBandwidth"] = "1000000";
+  stats.values["googTargetEncBitrate"] = "1000";
+  stats.values["googActualEncBitrate"] = "1000000";
+  stats.values["googRetransmitBitrate"] = "10";
+  stats.values["googTransmitBitrate"] = "1000000";
   const string stats_type = "bwe";
   const string stats_id = "videobwe";
-  ExecuteAndVerifyAddStats(pc, stats_type, stats_id, local, local);
+  ExecuteAndVerifyAddStats(pc, stats_type, stats_id, stats);
 
   string graph_id =
       pc.getIdString() + "-" + stats_type + "-" + stats_id + "-bweCompound";
@@ -389,7 +444,7 @@
         "window.domAutomationController.send("
         "   graphViews['" + graph_id + "'].getDataSeriesCount())",
         &count));
-  EXPECT_EQ((int)local.values.size(), count);
+  EXPECT_EQ((int)stats.values.size(), count);
 }
 
 // Tests that the total packet/byte count is converted to count per second,
@@ -414,18 +469,17 @@
   const string converted_values[] = {"1000", "8000", "1000", "8000"};
 
   // Send the first data point.
-  StatsUnit remote = {FAKE_TIME_STAMP};
-  StatsUnit local = {FAKE_TIME_STAMP};
+  StatsUnit stats = {FAKE_TIME_STAMP};
   for (int i = 0; i < num_converted_stats; ++i)
-    local.values[stats_names[i]] = first_value;
+    stats.values[stats_names[i]] = first_value;
 
-  ExecuteAndVerifyAddStats(pc, stats_type, stats_id, local, remote);
+  ExecuteAndVerifyAddStats(pc, stats_type, stats_id, stats);
 
   // Send the second data point at 1000ms after the first data point.
-  local.timestamp += 1000;
+  stats.timestamp += 1000;
   for (int i = 0; i < num_converted_stats; ++i)
-    local.values[stats_names[i]] = second_value;
-  ExecuteAndVerifyAddStats(pc, stats_type, stats_id, local, remote);
+    stats.values[stats_names[i]] = second_value;
+  ExecuteAndVerifyAddStats(pc, stats_type, stats_id, stats);
 
   // Verifies the graph data matches converted_values.
   string graph_id_prefix = pc.getIdString() + "-" + stats_type + "-" + stats_id;
@@ -435,4 +489,83 @@
   }
 }
 
+// Sanity check of the page content under a real PeerConnection call.
+IN_PROC_BROWSER_TEST_F(WebRTCInternalsBrowserTest, withRealPeerConnectionCall) {
+  // Start a peerconnection call in the first window.
+  GURL url(test_server()->GetURL("files/media/peerconnection-call.html"));
+  NavigateToURL(shell(), url);
+  ASSERT_TRUE(ExecuteJavascript("call({video:true});"));
+  ExpectTitle("OK");
+
+  // Open webrtc-internals in the second window.
+  GURL url2("chrome://webrtc-internals");
+  Shell* shell2 = CreateBrowser();
+  NavigateToURL(shell2, url2);
+
+  const int NUMBER_OF_PEER_CONNECTIONS = 2;
+
+  // Verifies the number of peerconnections.
+  int count = 0;
+  ASSERT_TRUE(ExecuteScriptAndExtractInt(
+      shell2->web_contents(),
+      "window.domAutomationController.send("
+          "$('peer-connections-list').getElementsByTagName('li').length);",
+      &count));
+  EXPECT_EQ(NUMBER_OF_PEER_CONNECTIONS, count);
+
+  // Verifies the the event tables.
+  ASSERT_TRUE(ExecuteScriptAndExtractInt(
+      shell2->web_contents(),
+      "window.domAutomationController.send($('peer-connections-list')"
+          ".getElementsByClassName('update-log-table').length);",
+      &count));
+  EXPECT_EQ(NUMBER_OF_PEER_CONNECTIONS, count);
+
+  ASSERT_TRUE(ExecuteScriptAndExtractInt(
+      shell2->web_contents(),
+      "window.domAutomationController.send($('peer-connections-list')"
+          ".getElementsByClassName('update-log-table')[0].rows.length);",
+      &count));
+  EXPECT_GT(count, 1);
+
+  ASSERT_TRUE(ExecuteScriptAndExtractInt(
+      shell2->web_contents(),
+      "window.domAutomationController.send($('peer-connections-list')"
+          ".getElementsByClassName('update-log-table')[1].rows.length);",
+      &count));
+  EXPECT_GT(count, 1);
+
+  // Wait until the stats table containers are created.
+  count = 0;
+  while (count != NUMBER_OF_PEER_CONNECTIONS) {
+    ASSERT_TRUE(ExecuteScriptAndExtractInt(
+        shell2->web_contents(),
+        "window.domAutomationController.send("
+            "$('peer-connections-list').getElementsByClassName("
+                "'stats-table-container').length);",
+        &count));
+  }
+
+  // Verifies each stats table having more than one rows.
+  bool result = false;
+  ASSERT_TRUE(ExecuteScriptAndExtractBool(
+      shell2->web_contents(),
+      "var tableContainers = $('peer-connections-list')"
+          ".getElementsByClassName('stats-table-container');"
+      "var result = true;"
+      "for (var i = 0; i < tableContainers.length && result; ++i) {"
+        "var tables = tableContainers[i].getElementsByTagName('table');"
+        "for (var j = 0; j < tables.length && result; ++j) {"
+          "result = (tables[j].rows.length > 1);"
+        "}"
+        "if (!result) {"
+          "console.log(tableContainers[i].innerHTML);"
+        "}"
+      "}"
+      "window.domAutomationController.send(result);",
+      &result));
+
+  EXPECT_TRUE(result);
+}
+
 }  // namespace content
diff --git a/content/browser/media/webrtc_internals_message_handler.cc b/content/browser/media/webrtc_internals_message_handler.cc
index 9545b9d..c89cfba 100644
--- a/content/browser/media/webrtc_internals_message_handler.cc
+++ b/content/browser/media/webrtc_internals_message_handler.cc
@@ -32,6 +32,14 @@
   web_ui()->RegisterMessageCallback("getAllStats",
       base::Bind(&WebRTCInternalsMessageHandler::OnGetAllStats,
                  base::Unretained(this)));
+
+  web_ui()->RegisterMessageCallback("startRtpRecording",
+      base::Bind(&WebRTCInternalsMessageHandler::OnStartRtpRecording,
+                 base::Unretained(this)));
+
+  web_ui()->RegisterMessageCallback("stopRtpRecording",
+      base::Bind(&WebRTCInternalsMessageHandler::OnStopRtpRecording,
+                 base::Unretained(this)));
 }
 
 void WebRTCInternalsMessageHandler::OnGetAllUpdates(
@@ -47,6 +55,16 @@
   }
 }
 
+void WebRTCInternalsMessageHandler::OnStartRtpRecording(
+    const base::ListValue* list) {
+  WebRTCInternals::GetInstance()->StartRtpRecording();
+}
+
+void WebRTCInternalsMessageHandler::OnStopRtpRecording(
+    const base::ListValue* list) {
+  WebRTCInternals::GetInstance()->StopRtpRecording();
+}
+
 void WebRTCInternalsMessageHandler::OnUpdate(const std::string& command,
                                             const base::Value* args) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
diff --git a/content/browser/media/webrtc_internals_message_handler.h b/content/browser/media/webrtc_internals_message_handler.h
index 9600a41..ee2059a 100644
--- a/content/browser/media/webrtc_internals_message_handler.h
+++ b/content/browser/media/webrtc_internals_message_handler.h
@@ -33,6 +33,8 @@
   // Javascript message handler.
   void OnGetAllUpdates(const base::ListValue* list);
   void OnGetAllStats(const base::ListValue* list);
+  void OnStartRtpRecording(const base::ListValue* list);
+  void OnStopRtpRecording(const base::ListValue* list);
 
  private:
   DISALLOW_COPY_AND_ASSIGN(WebRTCInternalsMessageHandler);
diff --git a/content/browser/media/webrtc_internals_ui.cc b/content/browser/media/webrtc_internals_ui.cc
index 2137acb..5c4adc5 100644
--- a/content/browser/media/webrtc_internals_ui.cc
+++ b/content/browser/media/webrtc_internals_ui.cc
@@ -16,7 +16,7 @@
 
 WebUIDataSource* CreateWebRTCInternalsHTMLSource() {
   WebUIDataSource* source =
-      WebUIDataSource::Create(chrome::kChromeUIWebRTCInternalsHost);
+      WebUIDataSource::Create(kChromeUIWebRTCInternalsHost);
 
   source->SetJsonPath("strings.js");
   source->AddResourcePath("webrtc_internals.js", IDR_WEBRTC_INTERNALS_JS);
diff --git a/content/browser/media/webrtc_internals_unittest.cc b/content/browser/media/webrtc_internals_unittest.cc
index c9237f0..58c7d8d 100644
--- a/content/browser/media/webrtc_internals_unittest.cc
+++ b/content/browser/media/webrtc_internals_unittest.cc
@@ -56,7 +56,7 @@
     return prefix + kstatic_part1 + id + kstatic_part2 + suffix;
   }
 
-  MessageLoop io_loop_;
+  base::MessageLoop io_loop_;
   TestBrowserThread io_thread_;
 };
 
@@ -67,18 +67,18 @@
       new MockWebRTCInternalsProxy());
   WebRTCInternals::GetInstance()->AddObserver(observer.get());
   WebRTCInternals::GetInstance()->RemoveObserver(observer.get());
-  WebRTCInternals::GetInstance()->AddPeerConnection(
+  WebRTCInternals::GetInstance()->OnAddPeerConnection(
       0, 3, 4, kUrl, kServers, kContraints);
   EXPECT_EQ("", observer->command());
 
-  WebRTCInternals::GetInstance()->RemovePeerConnection(3, 4);
+  WebRTCInternals::GetInstance()->OnRemovePeerConnection(3, 4);
 }
 
 TEST_F(WebRTCInternalsTest, SendAddPeerConnectionUpdate) {
   scoped_ptr<MockWebRTCInternalsProxy> observer(
       new MockWebRTCInternalsProxy());
   WebRTCInternals::GetInstance()->AddObserver(observer.get());
-  WebRTCInternals::GetInstance()->AddPeerConnection(
+  WebRTCInternals::GetInstance()->OnAddPeerConnection(
       0, 1, 2, kUrl, kServers, kContraints);
   EXPECT_EQ("addPeerConnection", observer->command());
 
@@ -100,16 +100,16 @@
   EXPECT_EQ(kContraints, value);
 
   WebRTCInternals::GetInstance()->RemoveObserver(observer.get());
-  WebRTCInternals::GetInstance()->RemovePeerConnection(1, 2);
+  WebRTCInternals::GetInstance()->OnRemovePeerConnection(1, 2);
 }
 
 TEST_F(WebRTCInternalsTest, SendRemovePeerConnectionUpdate) {
   scoped_ptr<MockWebRTCInternalsProxy> observer(
       new MockWebRTCInternalsProxy());
   WebRTCInternals::GetInstance()->AddObserver(observer.get());
-  WebRTCInternals::GetInstance()->AddPeerConnection(
+  WebRTCInternals::GetInstance()->OnAddPeerConnection(
       0, 1, 2, kUrl, kServers, kContraints);
-  WebRTCInternals::GetInstance()->RemovePeerConnection(1, 2);
+  WebRTCInternals::GetInstance()->OnRemovePeerConnection(1, 2);
   EXPECT_EQ("removePeerConnection", observer->command());
 
   DictionaryValue* dict = NULL;
@@ -128,12 +128,12 @@
   scoped_ptr<MockWebRTCInternalsProxy> observer(
       new MockWebRTCInternalsProxy());
   WebRTCInternals::GetInstance()->AddObserver(observer.get());
-  WebRTCInternals::GetInstance()->AddPeerConnection(
+  WebRTCInternals::GetInstance()->OnAddPeerConnection(
       0, 1, 2, kUrl, kServers, kContraints);
 
   const string update_type = "fakeType";
   const string update_value = "fakeValue";
-  WebRTCInternals::GetInstance()->UpdatePeerConnection(
+  WebRTCInternals::GetInstance()->OnUpdatePeerConnection(
       1, 2, update_type, update_value);
 
   EXPECT_EQ("updatePeerConnection", observer->command());
@@ -153,7 +153,7 @@
   EXPECT_TRUE(dict->GetString("value", &value));
   EXPECT_EQ(update_value, value);
 
-  WebRTCInternals::GetInstance()->RemovePeerConnection(1, 2);
+  WebRTCInternals::GetInstance()->OnRemovePeerConnection(1, 2);
   WebRTCInternals::GetInstance()->RemoveObserver(observer.get());
 }
 
diff --git a/content/browser/net/OWNERS b/content/browser/net/OWNERS
new file mode 100644
index 0000000..82e44d8
--- /dev/null
+++ b/content/browser/net/OWNERS
@@ -0,0 +1 @@
+erikwright@chromium.org
diff --git a/content/browser/net/sqlite_persistent_cookie_store.cc b/content/browser/net/sqlite_persistent_cookie_store.cc
new file mode 100644
index 0000000..2822e40
--- /dev/null
+++ b/content/browser/net/sqlite_persistent_cookie_store.cc
@@ -0,0 +1,1223 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/net/sqlite_persistent_cookie_store.h"
+
+#include <list>
+#include <map>
+#include <set>
+#include <utility>
+
+#include "base/basictypes.h"
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/file_util.h"
+#include "base/files/file_path.h"
+#include "base/location.h"
+#include "base/logging.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/metrics/histogram.h"
+#include "base/sequenced_task_runner.h"
+#include "base/string_util.h"
+#include "base/stringprintf.h"
+#include "base/synchronization/lock.h"
+#include "base/threading/sequenced_worker_pool.h"
+#include "base/time.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/cookie_store_factory.h"
+#include "googleurl/src/gurl.h"
+#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
+#include "net/cookies/canonical_cookie.h"
+#include "net/cookies/cookie_constants.h"
+#include "net/cookies/cookie_util.h"
+#include "sql/error_delegate_util.h"
+#include "sql/meta_table.h"
+#include "sql/statement.h"
+#include "sql/transaction.h"
+#include "third_party/sqlite/sqlite3.h"
+#include "webkit/quota/special_storage_policy.h"
+
+using base::Time;
+
+namespace content {
+
+// This class is designed to be shared between any client thread and the
+// background task runner. It batches operations and commits them on a timer.
+//
+// SQLitePersistentCookieStore::Load is called to load all cookies.  It
+// delegates to Backend::Load, which posts a Backend::LoadAndNotifyOnDBThread
+// task to the background runner.  This task calls Backend::ChainLoadCookies(),
+// which repeatedly posts itself to the BG runner to load each eTLD+1's cookies
+// in separate tasks.  When this is complete, Backend::CompleteLoadOnIOThread is
+// posted to the client runner, which notifies the caller of
+// SQLitePersistentCookieStore::Load that the load is complete.
+//
+// If a priority load request is invoked via SQLitePersistentCookieStore::
+// LoadCookiesForKey, it is delegated to Backend::LoadCookiesForKey, which posts
+// Backend::LoadKeyAndNotifyOnDBThread to the BG runner. That routine loads just
+// that single domain key (eTLD+1)'s cookies, and posts a Backend::
+// CompleteLoadForKeyOnIOThread to the client runner to notify the caller of
+// SQLitePersistentCookieStore::LoadCookiesForKey that that load is complete.
+//
+// Subsequent to loading, mutations may be queued by any thread using
+// AddCookie, UpdateCookieAccessTime, and DeleteCookie. These are flushed to
+// disk on the BG runner every 30 seconds, 512 operations, or call to Flush(),
+// whichever occurs first.
+class SQLitePersistentCookieStore::Backend
+    : public base::RefCountedThreadSafe<SQLitePersistentCookieStore::Backend> {
+ public:
+  Backend(
+      const base::FilePath& path,
+      const scoped_refptr<base::SequencedTaskRunner>& client_task_runner,
+      const scoped_refptr<base::SequencedTaskRunner>& background_task_runner,
+      bool restore_old_session_cookies,
+      quota::SpecialStoragePolicy* special_storage_policy)
+      : path_(path),
+        db_(NULL),
+        num_pending_(0),
+        force_keep_session_state_(false),
+        initialized_(false),
+        corruption_detected_(false),
+        restore_old_session_cookies_(restore_old_session_cookies),
+        special_storage_policy_(special_storage_policy),
+        num_cookies_read_(0),
+        client_task_runner_(client_task_runner),
+        background_task_runner_(background_task_runner),
+        num_priority_waiting_(0),
+        total_priority_requests_(0) {
+  }
+
+  // Creates or loads the SQLite database.
+  void Load(const LoadedCallback& loaded_callback);
+
+  // Loads cookies for the domain key (eTLD+1).
+  void LoadCookiesForKey(const std::string& domain,
+      const LoadedCallback& loaded_callback);
+
+  // Batch a cookie addition.
+  void AddCookie(const net::CanonicalCookie& cc);
+
+  // Batch a cookie access time update.
+  void UpdateCookieAccessTime(const net::CanonicalCookie& cc);
+
+  // Batch a cookie deletion.
+  void DeleteCookie(const net::CanonicalCookie& cc);
+
+  // Commit pending operations as soon as possible.
+  void Flush(const base::Closure& callback);
+
+  // Commit any pending operations and close the database.  This must be called
+  // before the object is destructed.
+  void Close();
+
+  void SetForceKeepSessionState();
+
+ private:
+  friend class base::RefCountedThreadSafe<SQLitePersistentCookieStore::Backend>;
+
+  class KillDatabaseErrorDelegate : public sql::ErrorDelegate {
+   public:
+    explicit KillDatabaseErrorDelegate(Backend* backend);
+
+    virtual ~KillDatabaseErrorDelegate() {}
+
+    // ErrorDelegate implementation.
+    virtual int OnError(int error,
+                        sql::Connection* connection,
+                        sql::Statement* stmt) OVERRIDE;
+
+   private:
+    // Do not increment the count on Backend, as that would create a circular
+    // reference (Backend -> Connection -> ErrorDelegate -> Backend).
+    Backend* backend_;
+
+    // True if the delegate has previously attempted to kill the database.
+    bool attempted_to_kill_database_;
+
+    DISALLOW_COPY_AND_ASSIGN(KillDatabaseErrorDelegate);
+  };
+
+  // You should call Close() before destructing this object.
+  ~Backend() {
+    DCHECK(!db_.get()) << "Close should have already been called.";
+    DCHECK(num_pending_ == 0 && pending_.empty());
+  }
+
+  // Database upgrade statements.
+  bool EnsureDatabaseVersion();
+
+  class PendingOperation {
+   public:
+    typedef enum {
+      COOKIE_ADD,
+      COOKIE_UPDATEACCESS,
+      COOKIE_DELETE,
+    } OperationType;
+
+    PendingOperation(OperationType op, const net::CanonicalCookie& cc)
+        : op_(op), cc_(cc) { }
+
+    OperationType op() const { return op_; }
+    const net::CanonicalCookie& cc() const { return cc_; }
+
+   private:
+    OperationType op_;
+    net::CanonicalCookie cc_;
+  };
+
+ private:
+  // Creates or loads the SQLite database on background runner.
+  void LoadAndNotifyInBackground(const LoadedCallback& loaded_callback,
+                                 const base::Time& posted_at);
+
+  // Loads cookies for the domain key (eTLD+1) on background runner.
+  void LoadKeyAndNotifyInBackground(const std::string& domains,
+                                    const LoadedCallback& loaded_callback,
+                                    const base::Time& posted_at);
+
+  // Notifies the CookieMonster when loading completes for a specific domain key
+  // or for all domain keys. Triggers the callback and passes it all cookies
+  // that have been loaded from DB since last IO notification.
+  void Notify(const LoadedCallback& loaded_callback, bool load_success);
+
+  // Sends notification when the entire store is loaded, and reports metrics
+  // for the total time to load and aggregated results from any priority loads
+  // that occurred.
+  void CompleteLoadInForeground(const LoadedCallback& loaded_callback,
+                                bool load_success);
+
+  // Sends notification when a single priority load completes. Updates priority
+  // load metric data. The data is sent only after the final load completes.
+  void CompleteLoadForKeyInForeground(const LoadedCallback& loaded_callback,
+                                      bool load_success);
+
+  // Sends all metrics, including posting a ReportMetricsInBackground task.
+  // Called after all priority and regular loading is complete.
+  void ReportMetrics();
+
+  // Sends background-runner owned metrics (i.e., the combined duration of all
+  // BG-runner tasks).
+  void ReportMetricsInBackground();
+
+  // Initialize the data base.
+  bool InitializeDatabase();
+
+  // Loads cookies for the next domain key from the DB, then either reschedules
+  // itself or schedules the provided callback to run on the client runner (if
+  // all domains are loaded).
+  void ChainLoadCookies(const LoadedCallback& loaded_callback);
+
+  // Load all cookies for a set of domains/hosts
+  bool LoadCookiesForDomains(const std::set<std::string>& key);
+
+  // Batch a cookie operation (add or delete)
+  void BatchOperation(PendingOperation::OperationType op,
+                      const net::CanonicalCookie& cc);
+  // Commit our pending operations to the database.
+  void Commit();
+  // Close() executed on the background runner.
+  void InternalBackgroundClose();
+
+  void DeleteSessionCookiesOnStartup();
+
+  void DeleteSessionCookiesOnShutdown();
+
+  void KillDatabase();
+  void ScheduleKillDatabase();
+
+  void PostBackgroundTask(const tracked_objects::Location& origin,
+                          const base::Closure& task);
+  void PostClientTask(const tracked_objects::Location& origin,
+                      const base::Closure& task);
+
+  base::FilePath path_;
+  scoped_ptr<sql::Connection> db_;
+  sql::MetaTable meta_table_;
+
+  typedef std::list<PendingOperation*> PendingOperationsList;
+  PendingOperationsList pending_;
+  PendingOperationsList::size_type num_pending_;
+  // True if the persistent store should skip delete on exit rules.
+  bool force_keep_session_state_;
+  // Guard |cookies_|, |pending_|, |num_pending_|, |force_keep_session_state_|
+  base::Lock lock_;
+
+  // Temporary buffer for cookies loaded from DB. Accumulates cookies to reduce
+  // the number of messages sent to the client runner. Sent back in response to
+  // individual load requests for domain keys or when all loading completes.
+  std::vector<net::CanonicalCookie*> cookies_;
+
+  // Map of domain keys(eTLD+1) to domains/hosts that are to be loaded from DB.
+  std::map<std::string, std::set<std::string> > keys_to_load_;
+
+  // Map of (domain keys(eTLD+1), is secure cookie) to number of cookies in the
+  // database.
+  typedef std::pair<std::string, bool> CookieOrigin;
+  typedef std::map<CookieOrigin, int> CookiesPerOriginMap;
+  CookiesPerOriginMap cookies_per_origin_;
+
+  // Indicates if DB has been initialized.
+  bool initialized_;
+
+  // Indicates if the kill-database callback has been scheduled.
+  bool corruption_detected_;
+
+  // If false, we should filter out session cookies when reading the DB.
+  bool restore_old_session_cookies_;
+
+  // Policy defining what data is deleted on shutdown.
+  scoped_refptr<quota::SpecialStoragePolicy> special_storage_policy_;
+
+  // The cumulative time spent loading the cookies on the background runner.
+  // Incremented and reported from the background runner.
+  base::TimeDelta cookie_load_duration_;
+
+  // The total number of cookies read. Incremented and reported on the
+  // background runner.
+  int num_cookies_read_;
+
+  scoped_refptr<base::SequencedTaskRunner> client_task_runner_;
+  scoped_refptr<base::SequencedTaskRunner> background_task_runner_;
+
+  // Guards the following metrics-related properties (only accessed when
+  // starting/completing priority loads or completing the total load).
+  base::Lock metrics_lock_;
+  int num_priority_waiting_;
+  // The total number of priority requests.
+  int total_priority_requests_;
+  // The time when |num_priority_waiting_| incremented to 1.
+  base::Time current_priority_wait_start_;
+  // The cumulative duration of time when |num_priority_waiting_| was greater
+  // than 1.
+  base::TimeDelta priority_wait_duration_;
+
+  DISALLOW_COPY_AND_ASSIGN(Backend);
+};
+
+SQLitePersistentCookieStore::Backend::KillDatabaseErrorDelegate::
+KillDatabaseErrorDelegate(Backend* backend)
+    : backend_(backend),
+      attempted_to_kill_database_(false) {
+}
+
+int SQLitePersistentCookieStore::Backend::KillDatabaseErrorDelegate::OnError(
+    int error, sql::Connection* connection, sql::Statement* stmt) {
+  // Do not attempt to kill database more than once. If the first time failed,
+  // it is unlikely that a second time will be successful.
+  if (!attempted_to_kill_database_ && sql::IsErrorCatastrophic(error)) {
+    attempted_to_kill_database_ = true;
+
+    backend_->ScheduleKillDatabase();
+  }
+
+  return error;
+}
+
+namespace {
+
+// Version number of the database.
+//
+// Version 6 adds cookie priorities. This allows developers to influence the
+// order in which cookies are evicted in order to meet domain cookie limits.
+//
+// Version 5 adds the columns has_expires and is_persistent, so that the
+// database can store session cookies as well as persistent cookies. Databases
+// of version 5 are incompatible with older versions of code. If a database of
+// version 5 is read by older code, session cookies will be treated as normal
+// cookies. Currently, these fields are written, but not read anymore.
+//
+// In version 4, we migrated the time epoch.  If you open the DB with an older
+// version on Mac or Linux, the times will look wonky, but the file will likely
+// be usable. On Windows version 3 and 4 are the same.
+//
+// Version 3 updated the database to include the last access time, so we can
+// expire them in decreasing order of use when we've reached the maximum
+// number of cookies.
+const int kCurrentVersionNumber = 6;
+const int kCompatibleVersionNumber = 5;
+
+// Possible values for the 'priority' column.
+enum DBCookiePriority {
+  kCookiePriorityLow = 0,
+  kCookiePriorityMedium = 1,
+  kCookiePriorityHigh = 2,
+};
+
+DBCookiePriority CookiePriorityToDBCookiePriority(net::CookiePriority value) {
+  switch (value) {
+    case net::COOKIE_PRIORITY_LOW:
+      return kCookiePriorityLow;
+    case net::COOKIE_PRIORITY_MEDIUM:
+      return kCookiePriorityMedium;
+    case net::COOKIE_PRIORITY_HIGH:
+      return kCookiePriorityHigh;
+  }
+
+  NOTREACHED();
+  return kCookiePriorityMedium;
+}
+
+net::CookiePriority DBCookiePriorityToCookiePriority(DBCookiePriority value) {
+  switch (value) {
+    case kCookiePriorityLow:
+      return net::COOKIE_PRIORITY_LOW;
+    case kCookiePriorityMedium:
+      return net::COOKIE_PRIORITY_MEDIUM;
+    case kCookiePriorityHigh:
+      return net::COOKIE_PRIORITY_HIGH;
+  }
+
+  NOTREACHED();
+  return net::COOKIE_PRIORITY_DEFAULT;
+}
+
+// Increments a specified TimeDelta by the duration between this object's
+// constructor and destructor. Not thread safe. Multiple instances may be
+// created with the same delta instance as long as their lifetimes are nested.
+// The shortest lived instances have no impact.
+class IncrementTimeDelta {
+ public:
+  explicit IncrementTimeDelta(base::TimeDelta* delta) :
+      delta_(delta),
+      original_value_(*delta),
+      start_(base::Time::Now()) {}
+
+  ~IncrementTimeDelta() {
+    *delta_ = original_value_ + base::Time::Now() - start_;
+  }
+
+ private:
+  base::TimeDelta* delta_;
+  base::TimeDelta original_value_;
+  base::Time start_;
+
+  DISALLOW_COPY_AND_ASSIGN(IncrementTimeDelta);
+};
+
+// Initializes the cookies table, returning true on success.
+bool InitTable(sql::Connection* db) {
+  if (!db->DoesTableExist("cookies")) {
+    std::string stmt(base::StringPrintf(
+        "CREATE TABLE cookies ("
+            "creation_utc INTEGER NOT NULL UNIQUE PRIMARY KEY,"
+            "host_key TEXT NOT NULL,"
+            "name TEXT NOT NULL,"
+            "value TEXT NOT NULL,"
+            "path TEXT NOT NULL,"
+            "expires_utc INTEGER NOT NULL,"
+            "secure INTEGER NOT NULL,"
+            "httponly INTEGER NOT NULL,"
+            "last_access_utc INTEGER NOT NULL, "
+            "has_expires INTEGER NOT NULL DEFAULT 1, "
+            "persistent INTEGER NOT NULL DEFAULT 1,"
+            "priority INTEGER NOT NULL DEFAULT %d)",
+        CookiePriorityToDBCookiePriority(net::COOKIE_PRIORITY_DEFAULT)));
+    if (!db->Execute(stmt.c_str()))
+      return false;
+  }
+
+  // Older code created an index on creation_utc, which is already
+  // primary key for the table.
+  if (!db->Execute("DROP INDEX IF EXISTS cookie_times"))
+    return false;
+
+  if (!db->Execute("CREATE INDEX IF NOT EXISTS domain ON cookies(host_key)"))
+    return false;
+
+  return true;
+}
+
+}  // namespace
+
+void SQLitePersistentCookieStore::Backend::Load(
+    const LoadedCallback& loaded_callback) {
+  // This function should be called only once per instance.
+  DCHECK(!db_.get());
+  PostBackgroundTask(FROM_HERE, base::Bind(
+      &Backend::LoadAndNotifyInBackground, this,
+      loaded_callback, base::Time::Now()));
+}
+
+void SQLitePersistentCookieStore::Backend::LoadCookiesForKey(
+    const std::string& key,
+    const LoadedCallback& loaded_callback) {
+  {
+    base::AutoLock locked(metrics_lock_);
+    if (num_priority_waiting_ == 0)
+      current_priority_wait_start_ = base::Time::Now();
+    num_priority_waiting_++;
+    total_priority_requests_++;
+  }
+
+  PostBackgroundTask(FROM_HERE, base::Bind(
+      &Backend::LoadKeyAndNotifyInBackground,
+      this, key, loaded_callback, base::Time::Now()));
+}
+
+void SQLitePersistentCookieStore::Backend::LoadAndNotifyInBackground(
+    const LoadedCallback& loaded_callback, const base::Time& posted_at) {
+  DCHECK(background_task_runner_->RunsTasksOnCurrentThread());
+  IncrementTimeDelta increment(&cookie_load_duration_);
+
+  UMA_HISTOGRAM_CUSTOM_TIMES(
+      "Cookie.TimeLoadDBQueueWait",
+      base::Time::Now() - posted_at,
+      base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(1),
+      50);
+
+  if (!InitializeDatabase()) {
+    PostClientTask(FROM_HERE, base::Bind(
+        &Backend::CompleteLoadInForeground, this, loaded_callback, false));
+  } else {
+    ChainLoadCookies(loaded_callback);
+  }
+}
+
+void SQLitePersistentCookieStore::Backend::LoadKeyAndNotifyInBackground(
+    const std::string& key,
+    const LoadedCallback& loaded_callback,
+    const base::Time& posted_at) {
+  DCHECK(background_task_runner_->RunsTasksOnCurrentThread());
+  IncrementTimeDelta increment(&cookie_load_duration_);
+
+  UMA_HISTOGRAM_CUSTOM_TIMES(
+      "Cookie.TimeKeyLoadDBQueueWait",
+      base::Time::Now() - posted_at,
+      base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(1),
+      50);
+
+  bool success = false;
+  if (InitializeDatabase()) {
+    std::map<std::string, std::set<std::string> >::iterator
+      it = keys_to_load_.find(key);
+    if (it != keys_to_load_.end()) {
+      success = LoadCookiesForDomains(it->second);
+      keys_to_load_.erase(it);
+    } else {
+      success = true;
+    }
+  }
+
+  PostClientTask(FROM_HERE, base::Bind(
+      &SQLitePersistentCookieStore::Backend::CompleteLoadForKeyInForeground,
+      this, loaded_callback, success));
+}
+
+void SQLitePersistentCookieStore::Backend::CompleteLoadForKeyInForeground(
+    const LoadedCallback& loaded_callback,
+    bool load_success) {
+  DCHECK(client_task_runner_->RunsTasksOnCurrentThread());
+
+  Notify(loaded_callback, load_success);
+
+  {
+    base::AutoLock locked(metrics_lock_);
+    num_priority_waiting_--;
+    if (num_priority_waiting_ == 0) {
+      priority_wait_duration_ +=
+          base::Time::Now() - current_priority_wait_start_;
+    }
+  }
+
+}
+
+void SQLitePersistentCookieStore::Backend::ReportMetricsInBackground() {
+  UMA_HISTOGRAM_CUSTOM_TIMES(
+      "Cookie.TimeLoad",
+      cookie_load_duration_,
+      base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(1),
+      50);
+}
+
+void SQLitePersistentCookieStore::Backend::ReportMetrics() {
+  PostBackgroundTask(FROM_HERE, base::Bind(
+      &SQLitePersistentCookieStore::Backend::ReportMetricsInBackground, this));
+
+  {
+    base::AutoLock locked(metrics_lock_);
+    UMA_HISTOGRAM_CUSTOM_TIMES(
+        "Cookie.PriorityBlockingTime",
+        priority_wait_duration_,
+        base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(1),
+        50);
+
+    UMA_HISTOGRAM_COUNTS_100(
+        "Cookie.PriorityLoadCount",
+        total_priority_requests_);
+
+    UMA_HISTOGRAM_COUNTS_10000(
+        "Cookie.NumberOfLoadedCookies",
+        num_cookies_read_);
+  }
+}
+
+void SQLitePersistentCookieStore::Backend::CompleteLoadInForeground(
+    const LoadedCallback& loaded_callback, bool load_success) {
+  Notify(loaded_callback, load_success);
+
+  if (load_success)
+    ReportMetrics();
+}
+
+void SQLitePersistentCookieStore::Backend::Notify(
+    const LoadedCallback& loaded_callback,
+    bool load_success) {
+  DCHECK(client_task_runner_->RunsTasksOnCurrentThread());
+
+  std::vector<net::CanonicalCookie*> cookies;
+  {
+    base::AutoLock locked(lock_);
+    cookies.swap(cookies_);
+  }
+
+  loaded_callback.Run(cookies);
+}
+
+bool SQLitePersistentCookieStore::Backend::InitializeDatabase() {
+  DCHECK(background_task_runner_->RunsTasksOnCurrentThread());
+
+  if (initialized_ || corruption_detected_) {
+    // Return false if we were previously initialized but the DB has since been
+    // closed, or if corruption caused a database reset during initialization.
+    return db_ != NULL;
+  }
+
+  base::Time start = base::Time::Now();
+
+  const base::FilePath dir = path_.DirName();
+  if (!file_util::PathExists(dir) && !file_util::CreateDirectory(dir)) {
+    return false;
+  }
+
+  int64 db_size = 0;
+  if (file_util::GetFileSize(path_, &db_size))
+    UMA_HISTOGRAM_COUNTS("Cookie.DBSizeInKB", db_size / 1024 );
+
+  db_.reset(new sql::Connection);
+  db_->set_error_histogram_name("Sqlite.Cookie.Error");
+  db_->set_error_delegate(new KillDatabaseErrorDelegate(this));
+
+  if (!db_->Open(path_)) {
+    NOTREACHED() << "Unable to open cookie DB.";
+    if (corruption_detected_)
+      db_->Raze();
+    meta_table_.Reset();
+    db_.reset();
+    return false;
+  }
+
+  if (!EnsureDatabaseVersion() || !InitTable(db_.get())) {
+    NOTREACHED() << "Unable to open cookie DB.";
+    if (corruption_detected_)
+      db_->Raze();
+    meta_table_.Reset();
+    db_.reset();
+    return false;
+  }
+
+  UMA_HISTOGRAM_CUSTOM_TIMES(
+    "Cookie.TimeInitializeDB",
+    base::Time::Now() - start,
+    base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(1),
+    50);
+
+  start = base::Time::Now();
+
+  // Retrieve all the domains
+  sql::Statement smt(db_->GetUniqueStatement(
+    "SELECT DISTINCT host_key FROM cookies"));
+
+  if (!smt.is_valid()) {
+    if (corruption_detected_)
+      db_->Raze();
+    meta_table_.Reset();
+    db_.reset();
+    return false;
+  }
+
+  // Build a map of domain keys (always eTLD+1) to domains.
+  while (smt.Step()) {
+    std::string domain = smt.ColumnString(0);
+    std::string key =
+      net::RegistryControlledDomainService::GetDomainAndRegistry(domain);
+
+    std::map<std::string, std::set<std::string> >::iterator it =
+      keys_to_load_.find(key);
+    if (it == keys_to_load_.end())
+      it = keys_to_load_.insert(std::make_pair
+                                (key, std::set<std::string>())).first;
+    it->second.insert(domain);
+  }
+
+  UMA_HISTOGRAM_CUSTOM_TIMES(
+    "Cookie.TimeInitializeDomainMap",
+    base::Time::Now() - start,
+    base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(1),
+    50);
+
+  initialized_ = true;
+  return true;
+}
+
+void SQLitePersistentCookieStore::Backend::ChainLoadCookies(
+    const LoadedCallback& loaded_callback) {
+  DCHECK(background_task_runner_->RunsTasksOnCurrentThread());
+  IncrementTimeDelta increment(&cookie_load_duration_);
+
+  bool load_success = true;
+
+  if (!db_) {
+    // Close() has been called on this store.
+    load_success = false;
+  } else if (keys_to_load_.size() > 0) {
+    // Load cookies for the first domain key.
+    std::map<std::string, std::set<std::string> >::iterator
+      it = keys_to_load_.begin();
+    load_success = LoadCookiesForDomains(it->second);
+    keys_to_load_.erase(it);
+  }
+
+  // If load is successful and there are more domain keys to be loaded,
+  // then post a background task to continue chain-load;
+  // Otherwise notify on client runner.
+  if (load_success && keys_to_load_.size() > 0) {
+    PostBackgroundTask(FROM_HERE, base::Bind(
+        &Backend::ChainLoadCookies, this, loaded_callback));
+  } else {
+    PostClientTask(FROM_HERE, base::Bind(
+        &Backend::CompleteLoadInForeground, this,
+        loaded_callback, load_success));
+    if (load_success && !restore_old_session_cookies_)
+      DeleteSessionCookiesOnStartup();
+  }
+}
+
+bool SQLitePersistentCookieStore::Backend::LoadCookiesForDomains(
+  const std::set<std::string>& domains) {
+  DCHECK(background_task_runner_->RunsTasksOnCurrentThread());
+
+  sql::Statement smt;
+  if (restore_old_session_cookies_) {
+    smt.Assign(db_->GetCachedStatement(
+        SQL_FROM_HERE,
+        "SELECT creation_utc, host_key, name, value, path, expires_utc, "
+        "secure, httponly, last_access_utc, has_expires, persistent, priority "
+        "FROM cookies WHERE host_key = ?"));
+  } else {
+    smt.Assign(db_->GetCachedStatement(
+        SQL_FROM_HERE,
+        "SELECT creation_utc, host_key, name, value, path, expires_utc, "
+        "secure, httponly, last_access_utc, has_expires, persistent, priority "
+        "FROM cookies WHERE host_key = ? AND persistent = 1"));
+  }
+  if (!smt.is_valid()) {
+    smt.Clear();  // Disconnect smt_ref from db_.
+    meta_table_.Reset();
+    db_.reset();
+    return false;
+  }
+
+  std::vector<net::CanonicalCookie*> cookies;
+  std::set<std::string>::const_iterator it = domains.begin();
+  for (; it != domains.end(); ++it) {
+    smt.BindString(0, *it);
+    while (smt.Step()) {
+      scoped_ptr<net::CanonicalCookie> cc(new net::CanonicalCookie(
+          // The "source" URL is not used with persisted cookies.
+          GURL(),                                         // Source
+          smt.ColumnString(2),                            // name
+          smt.ColumnString(3),                            // value
+          smt.ColumnString(1),                            // domain
+          smt.ColumnString(4),                            // path
+          Time::FromInternalValue(smt.ColumnInt64(0)),    // creation_utc
+          Time::FromInternalValue(smt.ColumnInt64(5)),    // expires_utc
+          Time::FromInternalValue(smt.ColumnInt64(8)),    // last_access_utc
+          smt.ColumnInt(6) != 0,                          // secure
+          smt.ColumnInt(7) != 0,                          // httponly
+          DBCookiePriorityToCookiePriority(
+              static_cast<DBCookiePriority>(smt.ColumnInt(11)))));  // priority
+      DLOG_IF(WARNING,
+              cc->CreationDate() > Time::Now()) << L"CreationDate too recent";
+      cookies_per_origin_[CookieOrigin(cc->Domain(), cc->IsSecure())]++;
+      cookies.push_back(cc.release());
+      ++num_cookies_read_;
+    }
+    smt.Reset(true);
+  }
+  {
+    base::AutoLock locked(lock_);
+    cookies_.insert(cookies_.end(), cookies.begin(), cookies.end());
+  }
+  return true;
+}
+
+bool SQLitePersistentCookieStore::Backend::EnsureDatabaseVersion() {
+  // Version check.
+  if (!meta_table_.Init(
+      db_.get(), kCurrentVersionNumber, kCompatibleVersionNumber)) {
+    return false;
+  }
+
+  if (meta_table_.GetCompatibleVersionNumber() > kCurrentVersionNumber) {
+    LOG(WARNING) << "Cookie database is too new.";
+    return false;
+  }
+
+  int cur_version = meta_table_.GetVersionNumber();
+  if (cur_version == 2) {
+    sql::Transaction transaction(db_.get());
+    if (!transaction.Begin())
+      return false;
+    if (!db_->Execute("ALTER TABLE cookies ADD COLUMN last_access_utc "
+                     "INTEGER DEFAULT 0") ||
+        !db_->Execute("UPDATE cookies SET last_access_utc = creation_utc")) {
+      LOG(WARNING) << "Unable to update cookie database to version 3.";
+      return false;
+    }
+    ++cur_version;
+    meta_table_.SetVersionNumber(cur_version);
+    meta_table_.SetCompatibleVersionNumber(
+        std::min(cur_version, kCompatibleVersionNumber));
+    transaction.Commit();
+  }
+
+  if (cur_version == 3) {
+    // The time epoch changed for Mac & Linux in this version to match Windows.
+    // This patch came after the main epoch change happened, so some
+    // developers have "good" times for cookies added by the more recent
+    // versions. So we have to be careful to only update times that are under
+    // the old system (which will appear to be from before 1970 in the new
+    // system). The magic number used below is 1970 in our time units.
+    sql::Transaction transaction(db_.get());
+    transaction.Begin();
+#if !defined(OS_WIN)
+    ignore_result(db_->Execute(
+        "UPDATE cookies "
+        "SET creation_utc = creation_utc + 11644473600000000 "
+        "WHERE rowid IN "
+        "(SELECT rowid FROM cookies WHERE "
+          "creation_utc > 0 AND creation_utc < 11644473600000000)"));
+    ignore_result(db_->Execute(
+        "UPDATE cookies "
+        "SET expires_utc = expires_utc + 11644473600000000 "
+        "WHERE rowid IN "
+        "(SELECT rowid FROM cookies WHERE "
+          "expires_utc > 0 AND expires_utc < 11644473600000000)"));
+    ignore_result(db_->Execute(
+        "UPDATE cookies "
+        "SET last_access_utc = last_access_utc + 11644473600000000 "
+        "WHERE rowid IN "
+        "(SELECT rowid FROM cookies WHERE "
+          "last_access_utc > 0 AND last_access_utc < 11644473600000000)"));
+#endif
+    ++cur_version;
+    meta_table_.SetVersionNumber(cur_version);
+    transaction.Commit();
+  }
+
+  if (cur_version == 4) {
+    const base::TimeTicks start_time = base::TimeTicks::Now();
+    sql::Transaction transaction(db_.get());
+    if (!transaction.Begin())
+      return false;
+    if (!db_->Execute("ALTER TABLE cookies "
+                      "ADD COLUMN has_expires INTEGER DEFAULT 1") ||
+        !db_->Execute("ALTER TABLE cookies "
+                      "ADD COLUMN persistent INTEGER DEFAULT 1")) {
+      LOG(WARNING) << "Unable to update cookie database to version 5.";
+      return false;
+    }
+    ++cur_version;
+    meta_table_.SetVersionNumber(cur_version);
+    meta_table_.SetCompatibleVersionNumber(
+        std::min(cur_version, kCompatibleVersionNumber));
+    transaction.Commit();
+    UMA_HISTOGRAM_TIMES("Cookie.TimeDatabaseMigrationToV5",
+                        base::TimeTicks::Now() - start_time);
+  }
+
+  if (cur_version == 5) {
+    const base::TimeTicks start_time = base::TimeTicks::Now();
+    sql::Transaction transaction(db_.get());
+    if (!transaction.Begin())
+      return false;
+    // Alter the table to add the priority column with a default value.
+    std::string stmt(base::StringPrintf(
+        "ALTER TABLE cookies ADD COLUMN priority INTEGER DEFAULT %d",
+        CookiePriorityToDBCookiePriority(net::COOKIE_PRIORITY_DEFAULT)));
+    if (!db_->Execute(stmt.c_str())) {
+      LOG(WARNING) << "Unable to update cookie database to version 6.";
+      return false;
+    }
+    ++cur_version;
+    meta_table_.SetVersionNumber(cur_version);
+    meta_table_.SetCompatibleVersionNumber(
+        std::min(cur_version, kCompatibleVersionNumber));
+    transaction.Commit();
+    UMA_HISTOGRAM_TIMES("Cookie.TimeDatabaseMigrationToV6",
+                        base::TimeTicks::Now() - start_time);
+  }
+
+  // Put future migration cases here.
+
+  if (cur_version < kCurrentVersionNumber) {
+    UMA_HISTOGRAM_COUNTS_100("Cookie.CorruptMetaTable", 1);
+
+    meta_table_.Reset();
+    db_.reset(new sql::Connection);
+    if (!file_util::Delete(path_, false) ||
+        !db_->Open(path_) ||
+        !meta_table_.Init(
+            db_.get(), kCurrentVersionNumber, kCompatibleVersionNumber)) {
+      UMA_HISTOGRAM_COUNTS_100("Cookie.CorruptMetaTableRecoveryFailed", 1);
+      NOTREACHED() << "Unable to reset the cookie DB.";
+      meta_table_.Reset();
+      db_.reset();
+      return false;
+    }
+  }
+
+  return true;
+}
+
+void SQLitePersistentCookieStore::Backend::AddCookie(
+    const net::CanonicalCookie& cc) {
+  BatchOperation(PendingOperation::COOKIE_ADD, cc);
+}
+
+void SQLitePersistentCookieStore::Backend::UpdateCookieAccessTime(
+    const net::CanonicalCookie& cc) {
+  BatchOperation(PendingOperation::COOKIE_UPDATEACCESS, cc);
+}
+
+void SQLitePersistentCookieStore::Backend::DeleteCookie(
+    const net::CanonicalCookie& cc) {
+  BatchOperation(PendingOperation::COOKIE_DELETE, cc);
+}
+
+void SQLitePersistentCookieStore::Backend::BatchOperation(
+    PendingOperation::OperationType op,
+    const net::CanonicalCookie& cc) {
+  // Commit every 30 seconds.
+  static const int kCommitIntervalMs = 30 * 1000;
+  // Commit right away if we have more than 512 outstanding operations.
+  static const size_t kCommitAfterBatchSize = 512;
+  DCHECK(!background_task_runner_->RunsTasksOnCurrentThread());
+
+  // We do a full copy of the cookie here, and hopefully just here.
+  scoped_ptr<PendingOperation> po(new PendingOperation(op, cc));
+
+  PendingOperationsList::size_type num_pending;
+  {
+    base::AutoLock locked(lock_);
+    pending_.push_back(po.release());
+    num_pending = ++num_pending_;
+  }
+
+  if (num_pending == 1) {
+    // We've gotten our first entry for this batch, fire off the timer.
+    if (!background_task_runner_->PostDelayedTask(
+            FROM_HERE, base::Bind(&Backend::Commit, this),
+            base::TimeDelta::FromMilliseconds(kCommitIntervalMs))) {
+      NOTREACHED() << "background_task_runner_ is not running.";
+    }
+  } else if (num_pending == kCommitAfterBatchSize) {
+    // We've reached a big enough batch, fire off a commit now.
+    PostBackgroundTask(FROM_HERE, base::Bind(&Backend::Commit, this));
+  }
+}
+
+void SQLitePersistentCookieStore::Backend::Commit() {
+  DCHECK(background_task_runner_->RunsTasksOnCurrentThread());
+
+  PendingOperationsList ops;
+  {
+    base::AutoLock locked(lock_);
+    pending_.swap(ops);
+    num_pending_ = 0;
+  }
+
+  // Maybe an old timer fired or we are already Close()'ed.
+  if (!db_.get() || ops.empty())
+    return;
+
+  sql::Statement add_smt(db_->GetCachedStatement(SQL_FROM_HERE,
+      "INSERT INTO cookies (creation_utc, host_key, name, value, path, "
+      "expires_utc, secure, httponly, last_access_utc, has_expires, "
+      "persistent, priority) "
+      "VALUES (?,?,?,?,?,?,?,?,?,?,?,?)"));
+  if (!add_smt.is_valid())
+    return;
+
+  sql::Statement update_access_smt(db_->GetCachedStatement(SQL_FROM_HERE,
+      "UPDATE cookies SET last_access_utc=? WHERE creation_utc=?"));
+  if (!update_access_smt.is_valid())
+    return;
+
+  sql::Statement del_smt(db_->GetCachedStatement(SQL_FROM_HERE,
+                         "DELETE FROM cookies WHERE creation_utc=?"));
+  if (!del_smt.is_valid())
+    return;
+
+  sql::Transaction transaction(db_.get());
+  if (!transaction.Begin())
+    return;
+
+  for (PendingOperationsList::iterator it = ops.begin();
+       it != ops.end(); ++it) {
+    // Free the cookies as we commit them to the database.
+    scoped_ptr<PendingOperation> po(*it);
+    switch (po->op()) {
+      case PendingOperation::COOKIE_ADD:
+        cookies_per_origin_[
+            CookieOrigin(po->cc().Domain(), po->cc().IsSecure())]++;
+        add_smt.Reset(true);
+        add_smt.BindInt64(0, po->cc().CreationDate().ToInternalValue());
+        add_smt.BindString(1, po->cc().Domain());
+        add_smt.BindString(2, po->cc().Name());
+        add_smt.BindString(3, po->cc().Value());
+        add_smt.BindString(4, po->cc().Path());
+        add_smt.BindInt64(5, po->cc().ExpiryDate().ToInternalValue());
+        add_smt.BindInt(6, po->cc().IsSecure());
+        add_smt.BindInt(7, po->cc().IsHttpOnly());
+        add_smt.BindInt64(8, po->cc().LastAccessDate().ToInternalValue());
+        add_smt.BindInt(9, po->cc().IsPersistent());
+        add_smt.BindInt(10, po->cc().IsPersistent());
+        add_smt.BindInt(
+            11, CookiePriorityToDBCookiePriority(po->cc().Priority()));
+        if (!add_smt.Run())
+          NOTREACHED() << "Could not add a cookie to the DB.";
+        break;
+
+      case PendingOperation::COOKIE_UPDATEACCESS:
+        update_access_smt.Reset(true);
+        update_access_smt.BindInt64(0,
+            po->cc().LastAccessDate().ToInternalValue());
+        update_access_smt.BindInt64(1,
+            po->cc().CreationDate().ToInternalValue());
+        if (!update_access_smt.Run())
+          NOTREACHED() << "Could not update cookie last access time in the DB.";
+        break;
+
+      case PendingOperation::COOKIE_DELETE:
+        cookies_per_origin_[
+            CookieOrigin(po->cc().Domain(), po->cc().IsSecure())]--;
+        del_smt.Reset(true);
+        del_smt.BindInt64(0, po->cc().CreationDate().ToInternalValue());
+        if (!del_smt.Run())
+          NOTREACHED() << "Could not delete a cookie from the DB.";
+        break;
+
+      default:
+        NOTREACHED();
+        break;
+    }
+  }
+  bool succeeded = transaction.Commit();
+  UMA_HISTOGRAM_ENUMERATION("Cookie.BackingStoreUpdateResults",
+                            succeeded ? 0 : 1, 2);
+}
+
+void SQLitePersistentCookieStore::Backend::Flush(
+    const base::Closure& callback) {
+  DCHECK(!background_task_runner_->RunsTasksOnCurrentThread());
+  PostBackgroundTask(FROM_HERE, base::Bind(&Backend::Commit, this));
+
+  if (!callback.is_null()) {
+    // We want the completion task to run immediately after Commit() returns.
+    // Posting it from here means there is less chance of another task getting
+    // onto the message queue first, than if we posted it from Commit() itself.
+    PostBackgroundTask(FROM_HERE, callback);
+  }
+}
+
+// Fire off a close message to the background runner.  We could still have a
+// pending commit timer or Load operations holding references on us, but if/when
+// this fires we will already have been cleaned up and it will be ignored.
+void SQLitePersistentCookieStore::Backend::Close() {
+  if (background_task_runner_->RunsTasksOnCurrentThread()) {
+    InternalBackgroundClose();
+  } else {
+    // Must close the backend on the background runner.
+    PostBackgroundTask(FROM_HERE,
+                       base::Bind(&Backend::InternalBackgroundClose, this));
+  }
+}
+
+void SQLitePersistentCookieStore::Backend::InternalBackgroundClose() {
+  DCHECK(background_task_runner_->RunsTasksOnCurrentThread());
+  // Commit any pending operations
+  Commit();
+
+  if (!force_keep_session_state_ && special_storage_policy_.get() &&
+      special_storage_policy_->HasSessionOnlyOrigins()) {
+    DeleteSessionCookiesOnShutdown();
+  }
+
+  meta_table_.Reset();
+  db_.reset();
+}
+
+void SQLitePersistentCookieStore::Backend::DeleteSessionCookiesOnShutdown() {
+  DCHECK(background_task_runner_->RunsTasksOnCurrentThread());
+
+  if (!db_)
+    return;
+
+  if (!special_storage_policy_)
+    return;
+
+  sql::Statement del_smt(db_->GetCachedStatement(
+      SQL_FROM_HERE, "DELETE FROM cookies WHERE host_key=? AND secure=?"));
+  if (!del_smt.is_valid()) {
+    LOG(WARNING) << "Unable to delete cookies on shutdown.";
+    return;
+  }
+
+  sql::Transaction transaction(db_.get());
+  if (!transaction.Begin()) {
+    LOG(WARNING) << "Unable to delete cookies on shutdown.";
+    return;
+  }
+
+  for (CookiesPerOriginMap::iterator it = cookies_per_origin_.begin();
+       it != cookies_per_origin_.end(); ++it) {
+    if (it->second <= 0) {
+      DCHECK_EQ(0, it->second);
+      continue;
+    }
+    const GURL url(net::cookie_util::CookieOriginToURL(it->first.first,
+                                                       it->first.second));
+    if (!url.is_valid() || !special_storage_policy_->IsStorageSessionOnly(url))
+      continue;
+
+    del_smt.Reset(true);
+    del_smt.BindString(0, it->first.first);
+    del_smt.BindInt(1, it->first.second);
+    if (!del_smt.Run())
+      NOTREACHED() << "Could not delete a cookie from the DB.";
+  }
+
+  if (!transaction.Commit())
+    LOG(WARNING) << "Unable to delete cookies on shutdown.";
+}
+
+void SQLitePersistentCookieStore::Backend::ScheduleKillDatabase() {
+  DCHECK(background_task_runner_->RunsTasksOnCurrentThread());
+
+  corruption_detected_ = true;
+
+  // Don't just do the close/delete here, as we are being called by |db| and
+  // that seems dangerous.
+  PostBackgroundTask(FROM_HERE, base::Bind(&Backend::KillDatabase, this));
+}
+
+void SQLitePersistentCookieStore::Backend::KillDatabase() {
+  DCHECK(background_task_runner_->RunsTasksOnCurrentThread());
+
+  if (db_) {
+    // This Backend will now be in-memory only. In a future run we will recreate
+    // the database. Hopefully things go better then!
+    bool success = db_->RazeAndClose();
+    UMA_HISTOGRAM_BOOLEAN("Cookie.KillDatabaseResult", success);
+    meta_table_.Reset();
+    db_.reset();
+  }
+}
+
+void SQLitePersistentCookieStore::Backend::SetForceKeepSessionState() {
+  base::AutoLock locked(lock_);
+  force_keep_session_state_ = true;
+}
+
+void SQLitePersistentCookieStore::Backend::DeleteSessionCookiesOnStartup() {
+  DCHECK(background_task_runner_->RunsTasksOnCurrentThread());
+  if (!db_->Execute("DELETE FROM cookies WHERE persistent == 0"))
+    LOG(WARNING) << "Unable to delete session cookies.";
+}
+
+void SQLitePersistentCookieStore::Backend::PostBackgroundTask(
+    const tracked_objects::Location& origin, const base::Closure& task) {
+  if (!background_task_runner_->PostTask(origin, task)) {
+    LOG(WARNING) << "Failed to post task from " << origin.ToString()
+                 << " to background_task_runner_.";
+  }
+}
+
+void SQLitePersistentCookieStore::Backend::PostClientTask(
+    const tracked_objects::Location& origin, const base::Closure& task) {
+  if (!client_task_runner_->PostTask(origin, task)) {
+    LOG(WARNING) << "Failed to post task from " << origin.ToString()
+                 << " to client_task_runner_.";
+  }
+}
+
+SQLitePersistentCookieStore::SQLitePersistentCookieStore(
+    const base::FilePath& path,
+    const scoped_refptr<base::SequencedTaskRunner>& client_task_runner,
+    const scoped_refptr<base::SequencedTaskRunner>& background_task_runner,
+    bool restore_old_session_cookies,
+    quota::SpecialStoragePolicy* special_storage_policy)
+    : backend_(new Backend(path,
+                           client_task_runner,
+                           background_task_runner,
+                           restore_old_session_cookies,
+                           special_storage_policy)) {
+}
+
+void SQLitePersistentCookieStore::Load(const LoadedCallback& loaded_callback) {
+  backend_->Load(loaded_callback);
+}
+
+void SQLitePersistentCookieStore::LoadCookiesForKey(
+    const std::string& key,
+    const LoadedCallback& loaded_callback) {
+  backend_->LoadCookiesForKey(key, loaded_callback);
+}
+
+void SQLitePersistentCookieStore::AddCookie(const net::CanonicalCookie& cc) {
+  backend_->AddCookie(cc);
+}
+
+void SQLitePersistentCookieStore::UpdateCookieAccessTime(
+    const net::CanonicalCookie& cc) {
+  backend_->UpdateCookieAccessTime(cc);
+}
+
+void SQLitePersistentCookieStore::DeleteCookie(const net::CanonicalCookie& cc) {
+  backend_->DeleteCookie(cc);
+}
+
+void SQLitePersistentCookieStore::SetForceKeepSessionState() {
+  backend_->SetForceKeepSessionState();
+}
+
+void SQLitePersistentCookieStore::Flush(const base::Closure& callback) {
+  backend_->Flush(callback);
+}
+
+SQLitePersistentCookieStore::~SQLitePersistentCookieStore() {
+  backend_->Close();
+  // We release our reference to the Backend, though it will probably still have
+  // a reference if the background runner has not run Close() yet.
+}
+
+net::CookieStore* CreatePersistentCookieStore(
+    const base::FilePath& path,
+    bool restore_old_session_cookies,
+    quota::SpecialStoragePolicy* storage_policy,
+    net::CookieMonster::Delegate* cookie_monster_delegate) {
+  SQLitePersistentCookieStore* persistent_store =
+      new SQLitePersistentCookieStore(
+          path,
+          BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO),
+          BrowserThread::GetBlockingPool()->GetSequencedTaskRunner(
+              BrowserThread::GetBlockingPool()->GetSequenceToken()),
+          restore_old_session_cookies,
+          storage_policy);
+  return new net::CookieMonster(persistent_store, cookie_monster_delegate);
+}
+
+}  // namespace content
diff --git a/content/browser/net/sqlite_persistent_cookie_store.h b/content/browser/net/sqlite_persistent_cookie_store.h
new file mode 100644
index 0000000..65e3982
--- /dev/null
+++ b/content/browser/net/sqlite_persistent_cookie_store.h
@@ -0,0 +1,77 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// A sqlite implementation of a cookie monster persistent store.
+
+#ifndef CONTENT_BROWSER_NET_SQLITE_PERSISTENT_COOKIE_STORE_H_
+#define CONTENT_BROWSER_NET_SQLITE_PERSISTENT_COOKIE_STORE_H_
+
+#include <string>
+#include <vector>
+
+#include "base/callback_forward.h"
+#include "base/compiler_specific.h"
+#include "base/memory/ref_counted.h"
+#include "content/common/content_export.h"
+#include "net/cookies/cookie_monster.h"
+
+class Task;
+
+namespace base {
+class FilePath;
+class SequencedTaskRunner;
+}
+
+namespace net {
+class CanonicalCookie;
+}
+
+namespace quota {
+class SpecialStoragePolicy;
+}
+
+namespace content {
+
+// Implements the PersistentCookieStore interface in terms of a SQLite database.
+// For documentation about the actual member functions consult the documentation
+// of the parent class |net::CookieMonster::PersistentCookieStore|.
+// If provided, a |SpecialStoragePolicy| is consulted when the SQLite database
+// is closed to decide which cookies to keep.
+class CONTENT_EXPORT SQLitePersistentCookieStore
+    : public net::CookieMonster::PersistentCookieStore {
+ public:
+  // All blocking database accesses will be performed on
+  // |background_task_runner|, while |client_task_runner| is used to invoke
+  // callbacks.
+  SQLitePersistentCookieStore(
+      const base::FilePath& path,
+      const scoped_refptr<base::SequencedTaskRunner>& client_task_runner,
+      const scoped_refptr<base::SequencedTaskRunner>& background_task_runner,
+      bool restore_old_session_cookies,
+      quota::SpecialStoragePolicy* special_storage_policy);
+
+  // net::CookieMonster::PersistentCookieStore:
+  virtual void Load(const LoadedCallback& loaded_callback) OVERRIDE;
+  virtual void LoadCookiesForKey(const std::string& key,
+      const LoadedCallback& callback) OVERRIDE;
+  virtual void AddCookie(const net::CanonicalCookie& cc) OVERRIDE;
+  virtual void UpdateCookieAccessTime(const net::CanonicalCookie& cc) OVERRIDE;
+  virtual void DeleteCookie(const net::CanonicalCookie& cc) OVERRIDE;
+  virtual void SetForceKeepSessionState() OVERRIDE;
+  virtual void Flush(const base::Closure& callback) OVERRIDE;
+
+ protected:
+   virtual ~SQLitePersistentCookieStore();
+
+ private:
+  class Backend;
+
+  scoped_refptr<Backend> backend_;
+
+  DISALLOW_COPY_AND_ASSIGN(SQLitePersistentCookieStore);
+};
+
+}  // namespace content
+
+#endif  // CONTENT_BROWSER_NET_SQLITE_PERSISTENT_COOKIE_STORE_H_
diff --git a/content/browser/net/sqlite_persistent_cookie_store_perftest.cc b/content/browser/net/sqlite_persistent_cookie_store_perftest.cc
new file mode 100644
index 0000000..d43a843
--- /dev/null
+++ b/content/browser/net/sqlite_persistent_cookie_store_perftest.cc
@@ -0,0 +1,142 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/net/sqlite_persistent_cookie_store.h"
+
+#include "base/bind.h"
+#include "base/compiler_specific.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/perftimer.h"
+#include "base/sequenced_task_runner.h"
+#include "base/stringprintf.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/test/sequenced_worker_pool_owner.h"
+#include "base/threading/sequenced_worker_pool.h"
+#include "googleurl/src/gurl.h"
+#include "net/cookies/canonical_cookie.h"
+#include "net/cookies/cookie_constants.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+namespace {
+
+const base::FilePath::CharType cookie_filename[] = FILE_PATH_LITERAL("Cookies");
+
+}  // namespace
+
+class SQLitePersistentCookieStorePerfTest : public testing::Test {
+ public:
+  SQLitePersistentCookieStorePerfTest()
+      : pool_owner_(new base::SequencedWorkerPoolOwner(1, "Background Pool")),
+        loaded_event_(false, false),
+        key_loaded_event_(false, false) {
+  }
+
+  void OnLoaded(const std::vector<net::CanonicalCookie*>& cookies) {
+    cookies_ = cookies;
+    loaded_event_.Signal();
+  }
+
+  void OnKeyLoaded(const std::vector<net::CanonicalCookie*>& cookies) {
+    cookies_ = cookies;
+    key_loaded_event_.Signal();
+  }
+
+  void Load() {
+    store_->Load(base::Bind(&SQLitePersistentCookieStorePerfTest::OnLoaded,
+                                base::Unretained(this)));
+    loaded_event_.Wait();
+  }
+
+  scoped_refptr<base::SequencedTaskRunner> background_task_runner() {
+    return pool_owner_->pool()->GetSequencedTaskRunner(
+        pool_owner_->pool()->GetNamedSequenceToken("background"));
+  }
+
+  scoped_refptr<base::SequencedTaskRunner> client_task_runner() {
+    return pool_owner_->pool()->GetSequencedTaskRunner(
+        pool_owner_->pool()->GetNamedSequenceToken("client"));
+  }
+
+  virtual void SetUp() OVERRIDE {
+    ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
+    store_ = new SQLitePersistentCookieStore(
+        temp_dir_.path().Append(cookie_filename),
+        client_task_runner(),
+        background_task_runner(),
+        false, NULL);
+    std::vector<net::CanonicalCookie*> cookies;
+    Load();
+    ASSERT_EQ(0u, cookies_.size());
+    // Creates 15000 cookies from 300 eTLD+1s.
+    base::Time t = base::Time::Now();
+    for (int domain_num = 0; domain_num < 300; domain_num++) {
+      std::string domain_name(base::StringPrintf(".domain_%d.com", domain_num));
+      GURL gurl("www" + domain_name);
+      for (int cookie_num = 0; cookie_num < 50; ++cookie_num) {
+        t += base::TimeDelta::FromInternalValue(10);
+        store_->AddCookie(
+            net::CanonicalCookie(gurl,
+                base::StringPrintf("Cookie_%d", cookie_num), "1",
+                domain_name, "/", t, t, t, false, false,
+                net::COOKIE_PRIORITY_DEFAULT));
+      }
+    }
+    // Replace the store effectively destroying the current one and forcing it
+    // to write its data to disk.
+    store_ = NULL;
+
+    // Shut down the pool, causing deferred (no-op) commits to be discarded.
+    pool_owner_->pool()->Shutdown();
+    // ~SequencedWorkerPoolOwner blocks on pool shutdown.
+    pool_owner_.reset(new base::SequencedWorkerPoolOwner(1, "pool"));
+
+    store_ = new SQLitePersistentCookieStore(
+        temp_dir_.path().Append(cookie_filename),
+        client_task_runner(),
+        background_task_runner(),
+        false, NULL);
+  }
+
+  virtual void TearDown() OVERRIDE {
+    store_ = NULL;
+    pool_owner_->pool()->Shutdown();
+  }
+
+ protected:
+  scoped_ptr<base::SequencedWorkerPoolOwner> pool_owner_;
+  base::WaitableEvent loaded_event_;
+  base::WaitableEvent key_loaded_event_;
+  std::vector<net::CanonicalCookie*> cookies_;
+  base::ScopedTempDir temp_dir_;
+  scoped_refptr<SQLitePersistentCookieStore> store_;
+};
+
+// Test the performance of priority load of cookies for a specfic domain key
+TEST_F(SQLitePersistentCookieStorePerfTest, TestLoadForKeyPerformance) {
+  for (int domain_num = 0; domain_num < 3; ++domain_num) {
+    std::string domain_name(base::StringPrintf("domain_%d.com", domain_num));
+    PerfTimeLogger timer(
+      ("Load cookies for the eTLD+1 " + domain_name).c_str());
+    store_->LoadCookiesForKey(domain_name,
+      base::Bind(&SQLitePersistentCookieStorePerfTest::OnKeyLoaded,
+                 base::Unretained(this)));
+    key_loaded_event_.Wait();
+    timer.Done();
+
+    ASSERT_EQ(50U, cookies_.size());
+  }
+}
+
+// Test the performance of load
+TEST_F(SQLitePersistentCookieStorePerfTest, TestLoadPerformance) {
+  PerfTimeLogger timer("Load all cookies");
+  Load();
+  timer.Done();
+
+  ASSERT_EQ(15000U, cookies_.size());
+}
+
+}  // namespace content
diff --git a/content/browser/net/sqlite_persistent_cookie_store_unittest.cc b/content/browser/net/sqlite_persistent_cookie_store_unittest.cc
new file mode 100644
index 0000000..cd0e078
--- /dev/null
+++ b/content/browser/net/sqlite_persistent_cookie_store_unittest.cc
@@ -0,0 +1,488 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/net/sqlite_persistent_cookie_store.h"
+
+#include <map>
+#include <set>
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/file_util.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/memory/ref_counted.h"
+#include "base/message_loop.h"
+#include "base/sequenced_task_runner.h"
+#include "base/stl_util.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/test/sequenced_worker_pool_owner.h"
+#include "base/threading/sequenced_worker_pool.h"
+#include "base/time.h"
+#include "googleurl/src/gurl.h"
+#include "net/cookies/canonical_cookie.h"
+#include "net/cookies/cookie_constants.h"
+#include "sql/connection.h"
+#include "sql/meta_table.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+namespace {
+
+const base::FilePath::CharType kCookieFilename[] = FILE_PATH_LITERAL("Cookies");
+
+}  // namespace
+
+typedef std::vector<net::CanonicalCookie*> CanonicalCookieVector;
+
+class SQLitePersistentCookieStoreTest : public testing::Test {
+ public:
+  SQLitePersistentCookieStoreTest()
+      : pool_owner_(new base::SequencedWorkerPoolOwner(3, "Background Pool")),
+        loaded_event_(false, false),
+        key_loaded_event_(false, false),
+        db_thread_event_(false, false) {
+  }
+
+  void OnLoaded(const CanonicalCookieVector& cookies) {
+    cookies_ = cookies;
+    loaded_event_.Signal();
+  }
+
+  void OnKeyLoaded(const CanonicalCookieVector& cookies) {
+    cookies_ = cookies;
+    key_loaded_event_.Signal();
+  }
+
+  void Load(CanonicalCookieVector* cookies) {
+    EXPECT_FALSE(loaded_event_.IsSignaled());
+    store_->Load(base::Bind(&SQLitePersistentCookieStoreTest::OnLoaded,
+                            base::Unretained(this)));
+    loaded_event_.Wait();
+    *cookies = cookies_;
+  }
+
+  void Flush() {
+    base::WaitableEvent event(false, false);
+    store_->Flush(base::Bind(&base::WaitableEvent::Signal,
+                             base::Unretained(&event)));
+    event.Wait();
+  }
+
+  scoped_refptr<base::SequencedTaskRunner> background_task_runner() {
+    return pool_owner_->pool()->GetSequencedTaskRunner(
+        pool_owner_->pool()->GetNamedSequenceToken("background"));
+  }
+
+  scoped_refptr<base::SequencedTaskRunner> client_task_runner() {
+    return pool_owner_->pool()->GetSequencedTaskRunner(
+        pool_owner_->pool()->GetNamedSequenceToken("client"));
+  }
+
+  void DestroyStore() {
+    store_ = NULL;
+    // Make sure we wait until the destructor has run by shutting down the pool
+    // resetting the owner (whose destructor blocks on the pool completion).
+    pool_owner_->pool()->Shutdown();
+    // Create a new pool for the few tests that create multiple stores. In other
+    // cases this is wasted but harmless.
+    pool_owner_.reset(new base::SequencedWorkerPoolOwner(3, "Background Pool"));
+  }
+
+  void CreateAndLoad(bool restore_old_session_cookies,
+                     CanonicalCookieVector* cookies) {
+    store_ = new SQLitePersistentCookieStore(
+        temp_dir_.path().Append(kCookieFilename),
+        client_task_runner(),
+        background_task_runner(),
+        restore_old_session_cookies,
+        NULL);
+    Load(cookies);
+  }
+
+  void InitializeStore(bool restore_old_session_cookies) {
+    CanonicalCookieVector cookies;
+    CreateAndLoad(restore_old_session_cookies, &cookies);
+    EXPECT_EQ(0U, cookies.size());
+  }
+
+  // We have to create this method to wrap WaitableEvent::Wait, since we cannot
+  // bind a non-void returning method as a Closure.
+  void WaitOnDBEvent() {
+    db_thread_event_.Wait();
+  }
+
+  // Adds a persistent cookie to store_.
+  void AddCookie(const std::string& name,
+                 const std::string& value,
+                 const std::string& domain,
+                 const std::string& path,
+                 const base::Time& creation) {
+    store_->AddCookie(
+        net::CanonicalCookie(GURL(), name, value, domain, path, creation,
+                             creation, creation, false, false,
+                             net::COOKIE_PRIORITY_DEFAULT));
+  }
+
+  virtual void SetUp() OVERRIDE {
+    ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
+  }
+
+  virtual void TearDown() OVERRIDE {
+    DestroyStore();
+    pool_owner_->pool()->Shutdown();
+  }
+
+ protected:
+  base::MessageLoop main_loop_;
+  scoped_ptr<base::SequencedWorkerPoolOwner> pool_owner_;
+  base::WaitableEvent loaded_event_;
+  base::WaitableEvent key_loaded_event_;
+  base::WaitableEvent db_thread_event_;
+  CanonicalCookieVector cookies_;
+  base::ScopedTempDir temp_dir_;
+  scoped_refptr<SQLitePersistentCookieStore> store_;
+};
+
+TEST_F(SQLitePersistentCookieStoreTest, TestInvalidMetaTableRecovery) {
+  InitializeStore(false);
+  AddCookie("A", "B", "foo.bar", "/", base::Time::Now());
+  DestroyStore();
+
+  // Load up the store and verify that it has good data in it.
+  CanonicalCookieVector cookies;
+  CreateAndLoad(false, &cookies);
+  ASSERT_EQ(1U, cookies.size());
+  ASSERT_STREQ("foo.bar", cookies[0]->Domain().c_str());
+  ASSERT_STREQ("A", cookies[0]->Name().c_str());
+  ASSERT_STREQ("B", cookies[0]->Value().c_str());
+  DestroyStore();
+  STLDeleteElements(&cookies);
+
+  // Now corrupt the meta table.
+  {
+    sql::Connection db;
+    ASSERT_TRUE(db.Open(temp_dir_.path().Append(kCookieFilename)));
+    sql::MetaTable meta_table_;
+    meta_table_.Init(&db, 1, 1);
+    ASSERT_TRUE(db.Execute("DELETE FROM meta"));
+    db.Close();
+  }
+
+  // Upon loading, the database should be reset to a good, blank state.
+  CreateAndLoad(false, &cookies);
+  ASSERT_EQ(0U, cookies.size());
+
+  // Verify that, after, recovery, the database persists properly.
+  AddCookie("X", "Y", "foo.bar", "/", base::Time::Now());
+  DestroyStore();
+  CreateAndLoad(false, &cookies);
+  ASSERT_EQ(1U, cookies.size());
+  ASSERT_STREQ("foo.bar", cookies[0]->Domain().c_str());
+  ASSERT_STREQ("X", cookies[0]->Name().c_str());
+  ASSERT_STREQ("Y", cookies[0]->Value().c_str());
+  STLDeleteElements(&cookies);
+}
+
+// Test if data is stored as expected in the SQLite database.
+TEST_F(SQLitePersistentCookieStoreTest, TestPersistance) {
+  InitializeStore(false);
+  AddCookie("A", "B", "foo.bar", "/", base::Time::Now());
+  // Replace the store effectively destroying the current one and forcing it
+  // to write its data to disk. Then we can see if after loading it again it
+  // is still there.
+  DestroyStore();
+  // Reload and test for persistence
+  CanonicalCookieVector cookies;
+  CreateAndLoad(false, &cookies);
+  ASSERT_EQ(1U, cookies.size());
+  ASSERT_STREQ("foo.bar", cookies[0]->Domain().c_str());
+  ASSERT_STREQ("A", cookies[0]->Name().c_str());
+  ASSERT_STREQ("B", cookies[0]->Value().c_str());
+
+  // Now delete the cookie and check persistence again.
+  store_->DeleteCookie(*cookies[0]);
+  DestroyStore();
+  STLDeleteElements(&cookies);
+
+  // Reload and check if the cookie has been removed.
+  CreateAndLoad(false, &cookies);
+  ASSERT_EQ(0U, cookies.size());
+}
+
+// Test that priority load of cookies for a specfic domain key could be
+// completed before the entire store is loaded
+TEST_F(SQLitePersistentCookieStoreTest, TestLoadCookiesForKey) {
+  InitializeStore(false);
+  base::Time t = base::Time::Now();
+  AddCookie("A", "B", "foo.bar", "/", t);
+  t += base::TimeDelta::FromInternalValue(10);
+  AddCookie("A", "B", "www.aaa.com", "/", t);
+  t += base::TimeDelta::FromInternalValue(10);
+  AddCookie("A", "B", "travel.aaa.com", "/", t);
+  t += base::TimeDelta::FromInternalValue(10);
+  AddCookie("A", "B", "www.bbb.com", "/", t);
+  DestroyStore();
+
+  store_ = new SQLitePersistentCookieStore(
+      temp_dir_.path().Append(kCookieFilename),
+      client_task_runner(),
+      background_task_runner(),
+      false, NULL);
+  // Posting a blocking task to db_thread_ makes sure that the DB thread waits
+  // until both Load and LoadCookiesForKey have been posted to its task queue.
+  background_task_runner()->PostTask(
+      FROM_HERE,
+      base::Bind(&SQLitePersistentCookieStoreTest::WaitOnDBEvent,
+                 base::Unretained(this)));
+  store_->Load(base::Bind(&SQLitePersistentCookieStoreTest::OnLoaded,
+                          base::Unretained(this)));
+  store_->LoadCookiesForKey("aaa.com",
+    base::Bind(&SQLitePersistentCookieStoreTest::OnKeyLoaded,
+               base::Unretained(this)));
+  background_task_runner()->PostTask(
+      FROM_HERE,
+      base::Bind(&SQLitePersistentCookieStoreTest::WaitOnDBEvent,
+                 base::Unretained(this)));
+
+  // Now the DB-thread queue contains:
+  // (active:)
+  // 1. Wait (on db_event)
+  // (pending:)
+  // 2. "Init And Chain-Load First Domain"
+  // 3. Priority Load (aaa.com)
+  // 4. Wait (on db_event)
+  db_thread_event_.Signal();
+  key_loaded_event_.Wait();
+  ASSERT_EQ(loaded_event_.IsSignaled(), false);
+  std::set<std::string> cookies_loaded;
+  for (CanonicalCookieVector::const_iterator it = cookies_.begin();
+       it != cookies_.end();
+       ++it) {
+    cookies_loaded.insert((*it)->Domain().c_str());
+  }
+  STLDeleteElements(&cookies_);
+  ASSERT_GT(4U, cookies_loaded.size());
+  ASSERT_EQ(true, cookies_loaded.find("www.aaa.com") != cookies_loaded.end());
+  ASSERT_EQ(true,
+            cookies_loaded.find("travel.aaa.com") != cookies_loaded.end());
+
+  db_thread_event_.Signal();
+  loaded_event_.Wait();
+  for (CanonicalCookieVector::const_iterator it = cookies_.begin();
+       it != cookies_.end();
+       ++it) {
+    cookies_loaded.insert((*it)->Domain().c_str());
+  }
+  ASSERT_EQ(4U, cookies_loaded.size());
+  ASSERT_EQ(cookies_loaded.find("foo.bar") != cookies_loaded.end(),
+            true);
+  ASSERT_EQ(cookies_loaded.find("www.bbb.com") != cookies_loaded.end(), true);
+  STLDeleteElements(&cookies_);
+}
+
+// Test that we can force the database to be written by calling Flush().
+TEST_F(SQLitePersistentCookieStoreTest, TestFlush) {
+  InitializeStore(false);
+  // File timestamps don't work well on all platforms, so we'll determine
+  // whether the DB file has been modified by checking its size.
+  base::FilePath path = temp_dir_.path().Append(kCookieFilename);
+  base::PlatformFileInfo info;
+  ASSERT_TRUE(file_util::GetFileInfo(path, &info));
+  int64 base_size = info.size;
+
+  // Write some large cookies, so the DB will have to expand by several KB.
+  for (char c = 'a'; c < 'z'; ++c) {
+    // Each cookie needs a unique timestamp for creation_utc (see DB schema).
+    base::Time t = base::Time::Now() + base::TimeDelta::FromMicroseconds(c);
+    std::string name(1, c);
+    std::string value(1000, c);
+    AddCookie(name, value, "foo.bar", "/", t);
+  }
+
+  Flush();
+
+  // We forced a write, so now the file will be bigger.
+  ASSERT_TRUE(file_util::GetFileInfo(path, &info));
+  ASSERT_GT(info.size, base_size);
+}
+
+// Test loading old session cookies from the disk.
+TEST_F(SQLitePersistentCookieStoreTest, TestLoadOldSessionCookies) {
+  InitializeStore(true);
+
+  // Add a session cookie.
+  store_->AddCookie(
+      net::CanonicalCookie(
+          GURL(), "C", "D", "sessioncookie.com", "/", base::Time::Now(),
+          base::Time(), base::Time::Now(), false, false,
+          net::COOKIE_PRIORITY_DEFAULT));
+
+  // Force the store to write its data to the disk.
+  DestroyStore();
+
+  // Create a store that loads session cookies and test that the session cookie
+  // was loaded.
+  CanonicalCookieVector cookies;
+  CreateAndLoad(true, &cookies);
+
+  ASSERT_EQ(1U, cookies.size());
+  ASSERT_STREQ("sessioncookie.com", cookies[0]->Domain().c_str());
+  ASSERT_STREQ("C", cookies[0]->Name().c_str());
+  ASSERT_STREQ("D", cookies[0]->Value().c_str());
+  ASSERT_EQ(net::COOKIE_PRIORITY_DEFAULT, cookies[0]->Priority());
+
+  STLDeleteElements(&cookies);
+}
+
+// Test loading old session cookies from the disk.
+TEST_F(SQLitePersistentCookieStoreTest, TestDontLoadOldSessionCookies) {
+  InitializeStore(true);
+
+  // Add a session cookie.
+  store_->AddCookie(
+      net::CanonicalCookie(
+          GURL(), "C", "D", "sessioncookie.com", "/", base::Time::Now(),
+          base::Time(), base::Time::Now(), false, false,
+          net::COOKIE_PRIORITY_DEFAULT));
+
+  // Force the store to write its data to the disk.
+  DestroyStore();
+
+  // Create a store that doesn't load old session cookies and test that the
+  // session cookie was not loaded.
+  CanonicalCookieVector cookies;
+  CreateAndLoad(false, &cookies);
+  ASSERT_EQ(0U, cookies.size());
+
+  // The store should also delete the session cookie. Wait until that has been
+  // done.
+  DestroyStore();
+
+  // Create a store that loads old session cookies and test that the session
+  // cookie is gone.
+  CreateAndLoad(true, &cookies);
+  ASSERT_EQ(0U, cookies.size());
+}
+
+TEST_F(SQLitePersistentCookieStoreTest, PersistIsPersistent) {
+  InitializeStore(true);
+  static const char kSessionName[] = "session";
+  static const char kPersistentName[] = "persistent";
+
+  // Add a session cookie.
+  store_->AddCookie(
+      net::CanonicalCookie(
+          GURL(), kSessionName, "val", "sessioncookie.com", "/",
+          base::Time::Now(), base::Time(), base::Time::Now(), false, false,
+          net::COOKIE_PRIORITY_DEFAULT));
+  // Add a persistent cookie.
+  store_->AddCookie(
+      net::CanonicalCookie(
+          GURL(), kPersistentName, "val", "sessioncookie.com", "/",
+          base::Time::Now() - base::TimeDelta::FromDays(1),
+          base::Time::Now() + base::TimeDelta::FromDays(1),
+          base::Time::Now(), false, false,
+          net::COOKIE_PRIORITY_DEFAULT));
+
+  // Force the store to write its data to the disk.
+  DestroyStore();
+
+  // Create a store that loads session cookie and test that the IsPersistent
+  // attribute is restored.
+  CanonicalCookieVector cookies;
+  CreateAndLoad(true, &cookies);
+  ASSERT_EQ(2U, cookies.size());
+
+  std::map<std::string, net::CanonicalCookie*> cookie_map;
+  for (CanonicalCookieVector::const_iterator it = cookies.begin();
+       it != cookies.end();
+       ++it) {
+    cookie_map[(*it)->Name()] = *it;
+  }
+
+  std::map<std::string, net::CanonicalCookie*>::const_iterator it =
+      cookie_map.find(kSessionName);
+  ASSERT_TRUE(it != cookie_map.end());
+  EXPECT_FALSE(cookie_map[kSessionName]->IsPersistent());
+
+  it = cookie_map.find(kPersistentName);
+  ASSERT_TRUE(it != cookie_map.end());
+  EXPECT_TRUE(cookie_map[kPersistentName]->IsPersistent());
+
+  STLDeleteElements(&cookies);
+}
+
+TEST_F(SQLitePersistentCookieStoreTest, PriorityIsPersistent) {
+  static const char kLowName[] = "low";
+  static const char kMediumName[] = "medium";
+  static const char kHighName[] = "high";
+  static const char kCookieDomain[] = "sessioncookie.com";
+  static const char kCookieValue[] = "value";
+  static const char kCookiePath[] = "/";
+
+  InitializeStore(true);
+
+  // Add a low-priority persistent cookie.
+  store_->AddCookie(
+      net::CanonicalCookie(
+          GURL(), kLowName, kCookieValue, kCookieDomain, kCookiePath,
+          base::Time::Now() - base::TimeDelta::FromMinutes(1),
+          base::Time::Now() + base::TimeDelta::FromDays(1),
+          base::Time::Now(), false, false,
+          net::COOKIE_PRIORITY_LOW));
+
+  // Add a medium-priority persistent cookie.
+  store_->AddCookie(
+      net::CanonicalCookie(
+          GURL(), kMediumName, kCookieValue, kCookieDomain, kCookiePath,
+          base::Time::Now() - base::TimeDelta::FromMinutes(2),
+          base::Time::Now() + base::TimeDelta::FromDays(1),
+          base::Time::Now(), false, false,
+          net::COOKIE_PRIORITY_MEDIUM));
+
+  // Add a high-priority peristent cookie.
+  store_->AddCookie(
+      net::CanonicalCookie(
+          GURL(), kHighName, kCookieValue, kCookieDomain, kCookiePath,
+          base::Time::Now() - base::TimeDelta::FromMinutes(3),
+          base::Time::Now() + base::TimeDelta::FromDays(1),
+          base::Time::Now(), false, false,
+          net::COOKIE_PRIORITY_HIGH));
+
+  // Force the store to write its data to the disk.
+  DestroyStore();
+
+  // Create a store that loads session cookie and test that the priority
+  // attribute values are restored.
+  CanonicalCookieVector cookies;
+  CreateAndLoad(true, &cookies);
+  ASSERT_EQ(3U, cookies.size());
+
+  // Put the cookies into a map, by name, so we can easily find them.
+  std::map<std::string, net::CanonicalCookie*> cookie_map;
+  for (CanonicalCookieVector::const_iterator it = cookies.begin();
+       it != cookies.end();
+       ++it) {
+    cookie_map[(*it)->Name()] = *it;
+  }
+
+  // Validate that each cookie has the correct priority.
+  std::map<std::string, net::CanonicalCookie*>::const_iterator it =
+      cookie_map.find(kLowName);
+  ASSERT_TRUE(it != cookie_map.end());
+  EXPECT_EQ(net::COOKIE_PRIORITY_LOW, cookie_map[kLowName]->Priority());
+
+  it = cookie_map.find(kMediumName);
+  ASSERT_TRUE(it != cookie_map.end());
+  EXPECT_EQ(net::COOKIE_PRIORITY_MEDIUM, cookie_map[kMediumName]->Priority());
+
+  it = cookie_map.find(kHighName);
+  ASSERT_TRUE(it != cookie_map.end());
+  EXPECT_EQ(net::COOKIE_PRIORITY_HIGH, cookie_map[kHighName]->Priority());
+
+  STLDeleteElements(&cookies);
+}
+
+}  // namespace content
diff --git a/content/browser/net/view_blob_internals_job_factory.cc b/content/browser/net/view_blob_internals_job_factory.cc
index eeb87fa..1eab44b 100644
--- a/content/browser/net/view_blob_internals_job_factory.cc
+++ b/content/browser/net/view_blob_internals_job_factory.cc
@@ -14,7 +14,7 @@
 // static.
 bool ViewBlobInternalsJobFactory::IsSupportedURL(const GURL& url) {
   return url.SchemeIs(chrome::kChromeUIScheme) &&
-         url.host() == chrome::kChromeUIBlobInternalsHost;
+         url.host() == kChromeUIBlobInternalsHost;
 }
 
 // static.
diff --git a/content/browser/net/view_http_cache_job_factory.cc b/content/browser/net/view_http_cache_job_factory.cc
index a1300e6..7738f8f 100644
--- a/content/browser/net/view_http_cache_job_factory.cc
+++ b/content/browser/net/view_http_cache_job_factory.cc
@@ -28,10 +28,9 @@
                    net::NetworkDelegate* network_delegate)
       : net::URLRequestJob(request, network_delegate),
         core_(new Core),
-        ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)),
-        ALLOW_THIS_IN_INITIALIZER_LIST(
-            callback_(base::Bind(&ViewHttpCacheJob::OnStartCompleted,
-                                 base::Unretained(this)))) {
+        weak_factory_(this),
+        callback_(base::Bind(&ViewHttpCacheJob::OnStartCompleted,
+                             base::Unretained(this))) {
   }
 
   // net::URLRequestJob implementation.
@@ -53,8 +52,7 @@
    public:
     Core()
         : data_offset_(0),
-          ALLOW_THIS_IN_INITIALIZER_LIST(callback_(
-              base::Bind(&Core::OnIOComplete, this))) {
+          callback_(base::Bind(&Core::OnIOComplete, this)) {
     }
 
     int Start(const net::URLRequest& request, const base::Closure& callback);
@@ -98,7 +96,7 @@
 };
 
 void ViewHttpCacheJob::Start() {
-  MessageLoop::current()->PostTask(
+  base::MessageLoop::current()->PostTask(
       FROM_HERE,
       base::Bind(&ViewHttpCacheJob::StartAsync, weak_factory_.GetWeakPtr()));
 }
@@ -193,7 +191,7 @@
 // Static.
 bool ViewHttpCacheJobFactory::IsSupportedURL(const GURL& url) {
   return url.SchemeIs(chrome::kChromeUIScheme) &&
-         url.host() == chrome::kChromeUINetworkViewCacheHost;
+         url.host() == kChromeUINetworkViewCacheHost;
 }
 
 // Static.
diff --git a/content/browser/plugin_data_remover_impl_browsertest.cc b/content/browser/plugin_data_remover_impl_browsertest.cc
index f0b4ead..37672ee 100644
--- a/content/browser/plugin_data_remover_impl_browsertest.cc
+++ b/content/browser/plugin_data_remover_impl_browsertest.cc
@@ -25,7 +25,7 @@
   PluginDataRemoverTest() {}
 
   void OnWaitableEventSignaled(base::WaitableEvent* waitable_event) {
-    MessageLoop::current()->Quit();
+    base::MessageLoop::current()->Quit();
   }
 
   virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
diff --git a/content/browser/plugin_loader_posix_unittest.cc b/content/browser/plugin_loader_posix_unittest.cc
index 6944384..c623892 100644
--- a/content/browser/plugin_loader_posix_unittest.cc
+++ b/content/browser/plugin_loader_posix_unittest.cc
@@ -79,7 +79,7 @@
     PluginServiceImpl::GetInstance()->Init();
   }
 
-  MessageLoop* message_loop() { return &message_loop_; }
+  base::MessageLoop* message_loop() { return &message_loop_; }
   MockPluginLoaderPosix* plugin_loader() { return plugin_loader_.get(); }
 
   void AddThreePlugins() {
@@ -97,7 +97,7 @@
  private:
   base::ShadowingAtExitManager at_exit_manager_;  // Destroys PluginService.
 
-  MessageLoopForIO message_loop_;
+  base::MessageLoopForIO message_loop_;
   BrowserThreadImpl file_thread_;
   BrowserThreadImpl io_thread_;
 
diff --git a/content/browser/plugin_process_host.cc b/content/browser/plugin_process_host.cc
index e3b5ac7..cad8d18 100644
--- a/content/browser/plugin_process_host.cc
+++ b/content/browser/plugin_process_host.cc
@@ -121,32 +121,22 @@
   std::set<HWND>::iterator window_index;
   for (window_index = plugin_parent_windows_set_.begin();
        window_index != plugin_parent_windows_set_.end();
-       window_index++) {
+       ++window_index) {
     PostMessage(*window_index, WM_CLOSE, 0, 0);
   }
 #elif defined(OS_MACOSX)
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
   // If the plugin process crashed but had fullscreen windows open at the time,
   // make sure that the menu bar is visible.
-  std::set<uint32>::iterator window_index;
-  for (window_index = plugin_fullscreen_windows_set_.begin();
-       window_index != plugin_fullscreen_windows_set_.end();
-       window_index++) {
-    if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
-      base::mac::ReleaseFullScreen(base::mac::kFullScreenModeHideAll);
-    } else {
-      BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
-                              base::Bind(base::mac::ReleaseFullScreen,
-                                         base::mac::kFullScreenModeHideAll));
-    }
+  for (size_t i = 0; i < plugin_fullscreen_windows_set_.size(); ++i) {
+    BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+                            base::Bind(base::mac::ReleaseFullScreen,
+                                       base::mac::kFullScreenModeHideAll));
   }
   // If the plugin hid the cursor, reset that.
   if (!plugin_cursor_visible_) {
-    if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
-      base::mac::SetCursorVisibility(true);
-    } else {
-      BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
-                              base::Bind(base::mac::SetCursorVisibility, true));
-    }
+    BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+                            base::Bind(base::mac::SetCursorVisibility, true));
   }
 #endif
   // Cancel all pending and sent requests.
diff --git a/content/browser/plugin_service_impl.cc b/content/browser/plugin_service_impl.cc
index 4ae318a..ff8aed4 100644
--- a/content/browser/plugin_service_impl.cc
+++ b/content/browser/plugin_service_impl.cc
@@ -16,13 +16,10 @@
 #include "base/synchronization/waitable_event.h"
 #include "base/threading/thread.h"
 #include "base/utf_string_conversions.h"
-#include "base/values.h"
 #include "content/browser/ppapi_plugin_process_host.h"
 #include "content/browser/renderer_host/render_process_host_impl.h"
 #include "content/browser/renderer_host/render_view_host_impl.h"
 #include "content/common/pepper_plugin_registry.h"
-#include "content/common/plugin_messages.h"
-#include "content/common/utility_messages.h"
 #include "content/common/view_messages.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/content_browser_client.h"
@@ -152,9 +149,9 @@
   // Release the events since they're owned by RegKey, not WaitableEvent.
   hkcu_watcher_.StopWatching();
   hklm_watcher_.StopWatching();
-  if (hkcu_event_.get())
+  if (hkcu_event_)
     hkcu_event_->Release();
-  if (hklm_event_.get())
+  if (hklm_event_)
     hklm_event_->Release();
 #endif
   // Make sure no plugin channel requests have been leaked.
@@ -178,7 +175,7 @@
   if (command_line->HasSwitch(switches::kSitePerProcess)) {
     webkit::WebPluginInfo webview_plugin(
         ASCIIToUTF16("WebView Tag"),
-        base::FilePath(FILE_PATH_LITERAL("")),
+        base::FilePath(),
         ASCIIToUTF16("1.2.3.4"),
         ASCIIToUTF16("Browser Plugin."));
     webview_plugin.type = webkit::WebPluginInfo::PLUGIN_TYPE_NPAPI;
@@ -584,7 +581,7 @@
 
 void PluginServiceImpl::GetPlugins(const GetPluginsCallback& callback) {
   scoped_refptr<base::MessageLoopProxy> target_loop(
-      MessageLoop::current()->message_loop_proxy());
+      base::MessageLoop::current()->message_loop_proxy());
 
   if (LoadPluginListInProcess()) {
     BrowserThread::GetBlockingPool()->
@@ -606,7 +603,7 @@
   } else {
     // If we switch back to loading plugins in process, then we need to make
     // sure g_thread_init() gets called since plugins may call glib at load.
-    if (!plugin_loader_.get())
+    if (!plugin_loader_)
       plugin_loader_ = new PluginLoaderPosix;
     BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
         base::Bind(&PluginLoaderPosix::LoadPlugins, plugin_loader_,
@@ -633,7 +630,7 @@
 void PluginServiceImpl::OnWaitableEventSignaled(
     base::WaitableEvent* waitable_event) {
 #if defined(OS_WIN)
-  if (waitable_event == hkcu_event_.get()) {
+  if (waitable_event == hkcu_event_) {
     hkcu_key_.StartWatching();
   } else {
     hklm_key_.StartWatching();
@@ -743,10 +740,7 @@
     return false;
   }
   base::TimeDelta delta = base::Time::Now() - i->second[0];
-  if (delta.InSeconds() <= kCrashesInterval) {
-    return true;
-  }
-  return false;
+  return delta.InSeconds() <= kCrashesInterval;
 }
 
 void PluginServiceImpl::RefreshPlugins() {
diff --git a/content/browser/plugin_service_impl_browsertest.cc b/content/browser/plugin_service_impl_browsertest.cc
index eaf5b66..102c492 100644
--- a/content/browser/plugin_service_impl_browsertest.cc
+++ b/content/browser/plugin_service_impl_browsertest.cc
@@ -106,8 +106,8 @@
   }
 
   void QuitMessageLoop() {
-    BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
-                            MessageLoop::QuitClosure());
+    BrowserThread::PostTask(
+        BrowserThread::UI, FROM_HERE, base::MessageLoop::QuitClosure());
   }
 
   ResourceContext* context_;
@@ -218,8 +218,8 @@
 };
 
 void QuitUIMessageLoopFromIOThread() {
-  BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
-                          MessageLoop::QuitClosure());
+  BrowserThread::PostTask(
+      BrowserThread::UI, FROM_HERE, base::MessageLoop::QuitClosure());
 }
 
 void OpenChannelAndThenCancel(PluginProcessHost::Client* client) {
@@ -271,13 +271,13 @@
     set_host(host);
     // This gets called right before we request the plugin<=>renderer channel,
     // so we have to post a task to cancel it.
-    MessageLoop::current()->PostTask(
+    base::MessageLoop::current()->PostTask(
         FROM_HERE,
         base::Bind(&PluginProcessHost::CancelPendingRequest,
-                   base::Unretained(host), this));
-    MessageLoop::current()->PostTask(
-        FROM_HERE,
-        base::Bind(&QuitUIMessageLoopFromIOThread));
+                   base::Unretained(host),
+                   this));
+    base::MessageLoop::current()->PostTask(
+        FROM_HERE, base::Bind(&QuitUIMessageLoopFromIOThread));
   }
 
   bool set_plugin_info_called() const {
@@ -345,8 +345,8 @@
   virtual void OnSentPluginChannelRequest() OVERRIDE {
     on_sent_plugin_channel_request_called_ = true;
     host()->CancelSentRequest(this);
-    BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
-                            MessageLoop::QuitClosure());
+    BrowserThread::PostTask(
+        BrowserThread::UI, FROM_HERE, base::MessageLoop::QuitClosure());
   }
 
   bool on_sent_plugin_channel_request_called() const {
diff --git a/content/browser/power_save_blocker_chromeos.cc b/content/browser/power_save_blocker_chromeos.cc
index e19dfbc..9eda5c4 100644
--- a/content/browser/power_save_blocker_chromeos.cc
+++ b/content/browser/power_save_blocker_chromeos.cc
@@ -36,10 +36,10 @@
         chromeos::DBusThreadManager::Get()->GetPowerPolicyController();
     switch (type_) {
       case kPowerSaveBlockPreventAppSuspension:
-        block_id_ = controller->AddSuspendBlock(reason_);
+        block_id_ = controller->AddSystemWakeLock(reason_);
         break;
       case kPowerSaveBlockPreventDisplaySleep:
-        block_id_ = controller->AddScreenBlock(reason_);
+        block_id_ = controller->AddScreenWakeLock(reason_);
         break;
       default:
         NOTREACHED() << "Unhandled block type " << type_;
@@ -53,7 +53,7 @@
       return;
     }
     chromeos::DBusThreadManager::Get()->GetPowerPolicyController()->
-        RemoveBlock(block_id_);
+        RemoveWakeLock(block_id_);
   }
 
  private:
diff --git a/content/browser/power_save_blocker_mac.cc b/content/browser/power_save_blocker_mac.cc
index b5d47c0..113c4e9 100644
--- a/content/browser/power_save_blocker_mac.cc
+++ b/content/browser/power_save_blocker_mac.cc
@@ -9,7 +9,7 @@
 #include "base/bind.h"
 #include "base/lazy_instance.h"
 #include "base/mac/scoped_cftyperef.h"
-#include "base/sys_string_conversions.h"
+#include "base/strings/sys_string_conversions.h"
 #include "base/threading/platform_thread.h"
 #include "base/threading/thread.h"
 
diff --git a/content/browser/power_save_blocker_linux.cc b/content/browser/power_save_blocker_x11.cc
similarity index 99%
rename from content/browser/power_save_blocker_linux.cc
rename to content/browser/power_save_blocker_x11.cc
index a0e3764..c7dba77 100644
--- a/content/browser/power_save_blocker_linux.cc
+++ b/content/browser/power_save_blocker_x11.cc
@@ -242,7 +242,7 @@
   // We're on the FILE thread so it should be OK to block briefly here.
   scoped_ptr<dbus::Response> response(object_proxy->CallMethodAndBlock(
       method_call.get(), dbus::ObjectProxy::TIMEOUT_USE_DEFAULT));
-  if (response.get()) {
+  if (response) {
     // The method returns an inhibit_cookie, used to uniquely identify
     // this request. It should be used as an argument to Uninhibit()
     // in order to remove the request.
@@ -285,7 +285,7 @@
   message_writer.AppendUint32(inhibit_cookie_);
   scoped_ptr<dbus::Response> response(object_proxy->CallMethodAndBlock(
       method_call.get(), dbus::ObjectProxy::TIMEOUT_USE_DEFAULT));
-  if (!response.get())
+  if (!response)
     LOG(ERROR) << "No response to Uninhibit() request!";
   // We don't care about checking the result. We assume it works; we can't
   // really do anything about it anyway if it fails.
diff --git a/content/browser/ppapi_plugin_process_host.cc b/content/browser/ppapi_plugin_process_host.cc
index 2364efc..9956326 100644
--- a/content/browser/ppapi_plugin_process_host.cc
+++ b/content/browser/ppapi_plugin_process_host.cc
@@ -286,10 +286,9 @@
                              arraysize(kCommonForwardSwitches));
 
   if (!is_broker_) {
-    // TODO(vtl): Stop passing flash args in the command line, on windows is
+    // TODO(vtl): Stop passing flash args in the command line, or windows is
     // going to explode.
     static const char* kPluginForwardSwitches[] = {
-      switches::kDisablePepperThreading,
       switches::kDisableSeccompFilterSandbox,
 #if defined(OS_MACOSX)
       switches::kEnableSandboxLogging,
@@ -318,7 +317,7 @@
 #if defined(OS_POSIX)
   bool use_zygote = !is_broker_ && plugin_launcher.empty() && info.is_sandboxed;
   if (!info.is_sandboxed)
-    cmd_line->AppendSwitchASCII(switches::kNoSandbox, "");
+    cmd_line->AppendSwitchASCII(switches::kNoSandbox, std::string());
 #endif  // OS_POSIX
   process_->Launch(
 #if defined(OS_WIN)
diff --git a/content/browser/renderer_host/OWNERS b/content/browser/renderer_host/OWNERS
index 1828f18..e74505d 100644
--- a/content/browser/renderer_host/OWNERS
+++ b/content/browser/renderer_host/OWNERS
@@ -1,16 +1,18 @@
-# for *aura.*

-ben@chromium.org

-

-# for *mac*

-thakis@chromium.org

-

-# for GPU-related stuff in *mac*

-kbr@chromium.org

-

-# for *android*

-sievers@chromium.org

-aelias@chromium.org

-

-# For touch/gesture specific changes

-rjkroege@chromium.org

-sadrul@chromium.org

+# for *aura*
+per-file *aura*=ben@chromium.org
+
+# for *mac*
+thakis@chromium.org
+
+# for GPU-related stuff in *mac*
+kbr@chromium.org
+per-file compositing_iosurface*=hclam@chromium.org
+per-file compositing_iosurface*=miu@chromium.org
+
+# for *android*
+sievers@chromium.org
+aelias@chromium.org
+
+# For touch/gesture specific changes
+rjkroege@chromium.org
+sadrul@chromium.org
diff --git a/content/browser/renderer_host/basic_mouse_wheel_smooth_scroll_gesture.cc b/content/browser/renderer_host/basic_mouse_wheel_smooth_scroll_gesture.cc
index af93b7c..b4eaa49 100644
--- a/content/browser/renderer_host/basic_mouse_wheel_smooth_scroll_gesture.cc
+++ b/content/browser/renderer_host/basic_mouse_wheel_smooth_scroll_gesture.cc
@@ -26,21 +26,22 @@
   if (pixels_scrolled_ >= pixels_to_scroll_)
     return false;
 
-  double positionDelta = 10;
+  double position_delta = 10;
   if (!last_tick_time_.is_null()) {
-    RenderWidgetHostImpl* hostImpl = RenderWidgetHostImpl::From(host);
-    double desiredIntervalMs = hostImpl->SyntheticScrollMessageInterval();
-    double velocity = 10 / desiredIntervalMs;
-    double timeDelta = (now - last_tick_time_).InMillisecondsF();
-    positionDelta = velocity * timeDelta;
+    RenderWidgetHostImpl* rwhi = RenderWidgetHostImpl::From(host);
+    base::TimeDelta desired_interval =
+        rwhi->GetSyntheticScrollMessageInterval();
+    double velocity = 10 / desired_interval.InMillisecondsF();
+    double time_delta = (now - last_tick_time_).InMillisecondsF();
+    position_delta = velocity * time_delta;
   }
 
   last_tick_time_ = now;
 
   WebKit::WebMouseWheelEvent event;
   event.type = WebKit::WebInputEvent::MouseWheel;
-  event.hasPreciseScrollingDeltas = 1;
-  event.deltaY = scroll_down_ ? -positionDelta : positionDelta;
+  event.hasPreciseScrollingDeltas = 0;
+  event.deltaY = scroll_down_ ? -position_delta : position_delta;
   // TODO(vollick): find a proper way to access
   // WebCore::WheelEvent::tickMultiplier.
   event.wheelTicksY = event.deltaY / 120;
diff --git a/content/browser/renderer_host/clipboard_message_filter.cc b/content/browser/renderer_host/clipboard_message_filter.cc
index 0708971..0b9dbff 100644
--- a/content/browser/renderer_host/clipboard_message_filter.cc
+++ b/content/browser/renderer_host/clipboard_message_filter.cc
@@ -25,7 +25,7 @@
 void WriteObjectsWrapper(ui::Clipboard* clipboard,
                          const ui::Clipboard::ObjectMap& objects,
                          BrowserContext* browser_context) {
-  ui::Clipboard::SourceTag source_tag =
+  ui::SourceTag source_tag =
       BrowserContext::GetMarkerForOffTheRecordContext(browser_context);
   clipboard->WriteObjects(ui::Clipboard::BUFFER_STANDARD,
                           objects,
diff --git a/content/browser/renderer_host/clipboard_message_filter_mac.mm b/content/browser/renderer_host/clipboard_message_filter_mac.mm
index 4105458..cdeabe6 100644
--- a/content/browser/renderer_host/clipboard_message_filter_mac.mm
+++ b/content/browser/renderer_host/clipboard_message_filter_mac.mm
@@ -9,7 +9,7 @@
 #include "base/basictypes.h"
 #include "base/bind.h"
 #include "base/bind_helpers.h"
-#include "base/sys_string_conversions.h"
+#include "base/strings/sys_string_conversions.h"
 #include "content/public/browser/browser_thread.h"
 #import "ui/base/cocoa/find_pasteboard.h"
 
diff --git a/content/browser/renderer_host/compositing_iosurface_context_mac.h b/content/browser/renderer_host/compositing_iosurface_context_mac.h
new file mode 100644
index 0000000..0b67af1
--- /dev/null
+++ b/content/browser/renderer_host/compositing_iosurface_context_mac.h
@@ -0,0 +1,76 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_RENDERER_HOST_COMPOSITING_IOSURFACE_CONTEXT_MAC_H_
+#define CONTENT_BROWSER_RENDERER_HOST_COMPOSITING_IOSURFACE_CONTEXT_MAC_H_
+
+#import <AppKit/NSOpenGL.h>
+#include <OpenGL/OpenGL.h>
+#include <map>
+
+#include "base/basictypes.h"
+#include "base/lazy_instance.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_nsobject.h"
+#include "base/memory/scoped_ptr.h"
+#include "content/browser/renderer_host/compositing_iosurface_mac.h"
+
+namespace content {
+
+class CompositingIOSurfaceShaderPrograms;
+
+class CompositingIOSurfaceContext
+    : public base::RefCounted<CompositingIOSurfaceContext> {
+ public:
+  // Get or create a GL context for the specified window with the specified
+  // surface ordering. Share these GL contexts as much as possible because
+  // creating and destroying them can be expensive
+  // http://crbug.com/180463
+  static scoped_refptr<CompositingIOSurfaceContext> Get(
+      int window_number,
+      CompositingIOSurfaceMac::SurfaceOrder surface_order);
+
+  CompositingIOSurfaceShaderPrograms* shader_program_cache() const {
+    return shader_program_cache_.get();
+  }
+  NSOpenGLContext* nsgl_context() const { return nsgl_context_; }
+  CGLContextObj cgl_context() const { return cgl_context_; }
+  bool is_vsync_disabled() const { return is_vsync_disabled_; }
+  int window_number() const { return window_number_; }
+  CompositingIOSurfaceMac::SurfaceOrder surface_order() const {
+    return surface_order_;
+  }
+
+ private:
+  friend class base::RefCounted<CompositingIOSurfaceContext>;
+
+  CompositingIOSurfaceContext(
+      int window_number,
+      CompositingIOSurfaceMac::SurfaceOrder surface_order,
+      NSOpenGLContext* nsgl_context,
+      CGLContextObj clg_context,
+      bool is_vsync_disabled_,
+      scoped_ptr<CompositingIOSurfaceShaderPrograms> shader_program_cache);
+  ~CompositingIOSurfaceContext();
+
+  // The value for NSOpenGLCPSurfaceOrder for this GL context,  1 will
+  // render above the window and -1 will render below the window.
+  int window_number_;
+  CompositingIOSurfaceMac::SurfaceOrder surface_order_;
+  scoped_nsobject<NSOpenGLContext> nsgl_context_;
+  CGLContextObj cgl_context_; // weak, backed by |nsgl_context_|
+  bool is_vsync_disabled_;
+  scoped_ptr<CompositingIOSurfaceShaderPrograms> shader_program_cache_;
+
+  // The global map from window number and window ordering to
+  // context data.
+  typedef std::map<std::pair<int,GLint>, CompositingIOSurfaceContext*>
+      WindowMap;
+  static base::LazyInstance<WindowMap> window_map_;
+  static WindowMap* window_map();
+};
+
+}  // namespace content
+
+#endif  // CONTENT_BROWSER_RENDERER_HOST_COMPOSITING_IOSURFACE_CONTEXT_MAC_H_
diff --git a/content/browser/renderer_host/compositing_iosurface_context_mac.mm b/content/browser/renderer_host/compositing_iosurface_context_mac.mm
new file mode 100644
index 0000000..2974d01
--- /dev/null
+++ b/content/browser/renderer_host/compositing_iosurface_context_mac.mm
@@ -0,0 +1,146 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/compositing_iosurface_context_mac.h"
+
+#include <OpenGL/gl.h>
+#include <OpenGL/OpenGL.h>
+#include <vector>
+
+#include "base/command_line.h"
+#include "base/debug/trace_event.h"
+#include "base/logging.h"
+#include "content/browser/renderer_host/compositing_iosurface_shader_programs_mac.h"
+#include "ui/gl/gl_switches.h"
+#include "ui/gl/gpu_switching_manager.h"
+
+namespace content {
+
+scoped_refptr<CompositingIOSurfaceContext>
+    CompositingIOSurfaceContext::Get(
+        int window_number,
+        CompositingIOSurfaceMac::SurfaceOrder surface_order) {
+  TRACE_EVENT0("browser", "CompositingIOSurfaceContext::Get");
+
+  // Return the context for this window_number and order, if it exists.
+  std::pair<int, int> key = std::make_pair(
+      window_number, static_cast<int>(surface_order));
+  WindowMap::iterator found = window_map()->find(key);
+  if (found != window_map()->end())
+    return found->second;
+
+  std::vector<NSOpenGLPixelFormatAttribute> attributes;
+  attributes.push_back(NSOpenGLPFADoubleBuffer);
+  // We don't need a depth buffer - try setting its size to 0...
+  attributes.push_back(NSOpenGLPFADepthSize); attributes.push_back(0);
+  if (ui::GpuSwitchingManager::GetInstance()->SupportsDualGpus())
+    attributes.push_back(NSOpenGLPFAAllowOfflineRenderers);
+  attributes.push_back(0);
+
+  scoped_nsobject<NSOpenGLPixelFormat> glPixelFormat(
+      [[NSOpenGLPixelFormat alloc] initWithAttributes:&attributes.front()]);
+  if (!glPixelFormat) {
+    LOG(ERROR) << "NSOpenGLPixelFormat initWithAttributes failed";
+    return NULL;
+  }
+
+  // Create all contexts in the same share group so that the textures don't
+  // need to be recreated when transitioning contexts.
+  NSOpenGLContext* share_context = nil;
+  if (!window_map()->empty())
+    share_context = window_map()->begin()->second->nsgl_context();
+    scoped_nsobject<NSOpenGLContext> nsgl_context(
+        [[NSOpenGLContext alloc] initWithFormat:glPixelFormat
+                                   shareContext:share_context]);
+  if (!nsgl_context) {
+    LOG(ERROR) << "NSOpenGLContext initWithFormat failed";
+    return NULL;
+  }
+
+  // If requested, ask the WindowServer to render the OpenGL surface underneath
+  // the window. This, combined with a hole punched in the window, will allow
+  // for views to "overlap" the GL surface from the user's point of view.
+  if (surface_order == CompositingIOSurfaceMac::SURFACE_ORDER_BELOW_WINDOW) {
+    GLint gl_surface_order = -1;
+    [nsgl_context setValues:&gl_surface_order
+                  forParameter:NSOpenGLCPSurfaceOrder];
+  }
+
+  CGLContextObj cgl_context = (CGLContextObj)[nsgl_context CGLContextObj];
+  if (!cgl_context) {
+    LOG(ERROR) << "CGLContextObj failed";
+    return NULL;
+  }
+
+  // Draw at beam vsync.
+  bool is_vsync_disabled =
+      CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableGpuVsync);
+  GLint swapInterval = is_vsync_disabled ? 0 : 1;
+  [nsgl_context setValues:&swapInterval forParameter:NSOpenGLCPSwapInterval];
+
+  // Prepare the shader program cache.  Precompile only the shader programs
+  // needed to draw the IO Surface.
+  CGLSetCurrentContext(cgl_context);
+  scoped_ptr<CompositingIOSurfaceShaderPrograms> shader_program_cache(
+      new CompositingIOSurfaceShaderPrograms());
+  const bool prepared = (
+      shader_program_cache->UseBlitProgram() &&
+      shader_program_cache->UseSolidWhiteProgram());
+  glUseProgram(0u);
+  CGLSetCurrentContext(0);
+  if (!prepared) {
+    LOG(ERROR) << "IOSurface failed to compile/link required shader programs.";
+    return NULL;
+  }
+
+  return new CompositingIOSurfaceContext(
+      window_number,
+      surface_order,
+      nsgl_context.release(),
+      cgl_context,
+      is_vsync_disabled,
+      shader_program_cache.Pass());
+}
+
+CompositingIOSurfaceContext::CompositingIOSurfaceContext(
+    int window_number,
+    CompositingIOSurfaceMac::SurfaceOrder surface_order,
+    NSOpenGLContext* nsgl_context,
+    CGLContextObj cgl_context,
+    bool is_vsync_disabled,
+    scoped_ptr<CompositingIOSurfaceShaderPrograms> shader_program_cache)
+    : window_number_(window_number),
+      surface_order_(surface_order),
+      nsgl_context_(nsgl_context),
+      cgl_context_(cgl_context),
+      is_vsync_disabled_(is_vsync_disabled),
+      shader_program_cache_(shader_program_cache.Pass()) {
+  std::pair<int, int> key = std::make_pair(
+      window_number_, static_cast<int>(surface_order_));
+  DCHECK(window_map()->find(key) == window_map()->end());
+  window_map()->insert(std::make_pair(key, this));
+}
+
+CompositingIOSurfaceContext::~CompositingIOSurfaceContext() {
+  CGLSetCurrentContext(cgl_context_);
+  shader_program_cache_->Reset();
+  CGLSetCurrentContext(0);
+  std::pair<int, int> key = std::make_pair(
+      window_number_, static_cast<int>(surface_order_));
+  DCHECK(window_map()->find(key) != window_map()->end());
+  DCHECK(window_map()->find(key)->second == this);
+  window_map()->erase(key);
+}
+
+// static
+CompositingIOSurfaceContext::WindowMap*
+    CompositingIOSurfaceContext::window_map() {
+  return window_map_.Pointer();
+}
+
+// static
+base::LazyInstance<CompositingIOSurfaceContext::WindowMap>
+    CompositingIOSurfaceContext::window_map_;
+
+}  // namespace content
diff --git a/content/browser/renderer_host/compositing_iosurface_mac.h b/content/browser/renderer_host/compositing_iosurface_mac.h
index 4dcaac5..b6f734b 100644
--- a/content/browser/renderer_host/compositing_iosurface_mac.h
+++ b/content/browser/renderer_host/compositing_iosurface_mac.h
@@ -6,6 +6,7 @@
 #define CONTENT_BROWSER_RENDERER_HOST_COMPOSITING_IOSURFACE_MAC_H_
 
 #include <deque>
+#include <vector>
 
 #import <Cocoa/Cocoa.h>
 #import <QuartzCore/CVDisplayLink.h>
@@ -13,7 +14,6 @@
 
 #include "base/callback.h"
 #include "base/mac/scoped_cftyperef.h"
-#include "base/memory/scoped_nsobject.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/synchronization/lock.h"
 #include "base/time.h"
@@ -33,6 +33,7 @@
 
 namespace content {
 
+class CompositingIOSurfaceContext;
 class CompositingIOSurfaceShaderPrograms;
 class CompositingIOSurfaceTransformer;
 class RenderWidgetHostViewFrameSubscriber;
@@ -45,14 +46,15 @@
   // Passed to Create() to specify the ordering of the surface relative to the
   // containing window.
   enum SurfaceOrder {
-    SURFACE_ORDER_ABOVE_WINDOW,
-    SURFACE_ORDER_BELOW_WINDOW
+    SURFACE_ORDER_ABOVE_WINDOW = 0,
+    SURFACE_ORDER_BELOW_WINDOW = 1,
   };
 
   // Returns NULL if IOSurface support is missing or GL APIs fail. Specify in
   // |order| the desired ordering relationship of the surface to the containing
   // window.
-  static CompositingIOSurfaceMac* Create(SurfaceOrder order);
+  static CompositingIOSurfaceMac* Create(int window_number,
+                                  SurfaceOrder order);
   ~CompositingIOSurfaceMac();
 
   // Set IOSurface that will be drawn on the next NSView drawRect.
@@ -67,7 +69,9 @@
   // will be white. |scaleFactor| is 1 in normal views, 2 in HiDPI views.
   // |frame_subscriber| listens to this draw event and provides output buffer
   // for copying this frame into.
-  void DrawIOSurface(NSView* view, float scale_factor,
+  void DrawIOSurface(NSView* view,
+                     float scale_factor,
+                     int window_number,
                      RenderWidgetHostViewFrameSubscriber* frame_subscriber);
 
   // Copy the data of the "live" OpenGL texture referring to this IOSurfaceRef
@@ -110,7 +114,7 @@
   // In cocoa view units / DIPs.
   const gfx::Size& io_surface_size() const { return io_surface_size_; }
 
-  bool is_vsync_disabled() const { return is_vsync_disabled_; }
+  bool is_vsync_disabled() const;
 
   // Get vsync scheduling parameters.
   // |interval_numerator/interval_denominator| equates to fractional number of
@@ -185,13 +189,26 @@
   };
 
   // Keeps track of states and buffers for readback of IOSurface.
+  //
+  // TODO(miu): Major code refactoring is badly needed!  To be done in a
+  // soon-upcoming change.  For now, we blatantly violate the style guide with
+  // respect to struct vs. class usage:
   struct CopyContext {
-    CopyContext();
+    explicit CopyContext(const scoped_refptr<CompositingIOSurfaceContext>& ctx);
     ~CopyContext();
-    void CleanUp();
 
+    // Delete any references to owned OpenGL objects.  This must be called
+    // within the OpenGL context just before destruction.
+    void ReleaseCachedGLObjects();
+
+    // The following two methods assume |num_outputs| has been set, and are
+    // being called within the OpenGL context.
+    void PrepareReadbackFramebuffers();
+    void PrepareForAsynchronousReadback();
+
+    const scoped_ptr<CompositingIOSurfaceTransformer> transformer;
     int num_outputs;
-    GLuint output_textures[3];
+    GLuint output_textures[3];  // Not owned.
     // Note: For YUV, the |output_texture_sizes| widths are in terms of 4-byte
     // quads, not pixels.
     gfx::Size output_texture_sizes[3];
@@ -205,12 +222,14 @@
 
   CompositingIOSurfaceMac(
       IOSurfaceSupport* io_surface_support,
-      NSOpenGLContext* glContext,
-      CGLContextObj cglContext,
-      scoped_ptr<CompositingIOSurfaceShaderPrograms> shader_program_cache,
-      bool is_vsync_disabled,
+      scoped_refptr<CompositingIOSurfaceContext> context,
       CVDisplayLinkRef display_link);
 
+  // If this IOSurface has moved to a different window, use that window's
+  // GL context (if multiple visible windows are using the same GL context
+  // then call to setView call can stall and prevent reaching 60fps).
+  void SwitchToContextOnNewWindow(NSView* view, int window_number);
+
   bool IsVendorIntel();
 
   // Returns true if IOSurface is ready to render. False otherwise.
@@ -276,8 +295,8 @@
   void FinishAllCopiesWithinContext(
       std::vector<base::Closure>* done_callbacks);
 
-  void CleanupAllCopiesWithinContext();
   void FailAllCopies();
+  void DestroyAllCopyContextsWithinContext();
 
   gfx::Rect IntersectWithIOSurface(const gfx::Rect& rect,
                                    float scale_factor) const;
@@ -285,9 +304,9 @@
   // Cached pointer to IOSurfaceSupport Singleton.
   IOSurfaceSupport* io_surface_support_;
 
-  // GL context
-  scoped_nsobject<NSOpenGLContext> glContext_;
-  CGLContextObj cglContext_;  // weak, backed by |glContext_|.
+  // GL context, and parameters for context sharing. This may change when
+  // moving between windows, but will never be NULL.
+  scoped_refptr<CompositingIOSurfaceContext> context_;
 
   // IOSurface data.
   uint64 io_surface_handle_;
@@ -304,18 +323,18 @@
   // with it.
   GLuint texture_;
 
-  std::deque<CopyContext> copy_requests_;
+  // A pool of CopyContexts with OpenGL objects ready for re-use.  Prefer to
+  // pull one from the pool before creating a new CopyContext.
+  std::vector<CopyContext*> copy_context_pool_;
+
+  // CopyContexts being used for in-flight copy operations.
+  std::deque<CopyContext*> copy_requests_;
 
   // Timer for finishing a copy operation.
   base::Timer finish_copy_timer_;
 
-  scoped_ptr<CompositingIOSurfaceShaderPrograms> shader_program_cache_;
-  scoped_ptr<CompositingIOSurfaceTransformer> transformer_;
-
   SurfaceQuad quad_;
 
-  bool is_vsync_disabled_;
-
   // CVDisplayLink for querying Vsync timing info and throttling swaps.
   CVDisplayLinkRef display_link_;
 
diff --git a/content/browser/renderer_host/compositing_iosurface_mac.mm b/content/browser/renderer_host/compositing_iosurface_mac.mm
index c433286..510e479 100644
--- a/content/browser/renderer_host/compositing_iosurface_mac.mm
+++ b/content/browser/renderer_host/compositing_iosurface_mac.mm
@@ -6,7 +6,6 @@
 
 #include <OpenGL/CGLRenderers.h>
 #include <OpenGL/OpenGL.h>
-#include <vector>
 
 #include "base/bind.h"
 #include "base/bind_helpers.h"
@@ -16,6 +15,7 @@
 #include "base/mac/mac_util.h"
 #include "base/message_loop.h"
 #include "base/threading/platform_thread.h"
+#include "content/browser/renderer_host/compositing_iosurface_context_mac.h"
 #include "content/browser/renderer_host/compositing_iosurface_shader_programs_mac.h"
 #include "content/browser/renderer_host/compositing_iosurface_transformer_mac.h"
 #include "content/common/content_constants_internal.h"
@@ -26,8 +26,6 @@
 #include "ui/gfx/rect.h"
 #include "ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h"
 #include "ui/gl/gl_context.h"
-#include "ui/gl/gl_switches.h"
-#include "ui/gl/gpu_switching_manager.h"
 #include "ui/gfx/size_conversions.h"
 #include "ui/surface/io_surface_support_mac.h"
 
@@ -51,9 +49,6 @@
 // This value is shorter than 16ms such that copy can complete within a vsync.
 const int kFinishCopyPollingPeriodMs = 10;
 
-// Everything uses only the GL_TEXTURE0 texture unit.
-const int kTextureUnit = 0;
-
 bool HasAppleFenceExtension() {
   static bool initialized_has_fence = false;
   static bool has_fence = false;
@@ -92,7 +87,7 @@
 // the snapshot path, we just memcpy the data into our output bitmap since the
 // width, height, and stride should all be equal.
 bool MapBufferToSkBitmap(const SkBitmap* output, const void* buf, int ignored) {
-  TRACE_EVENT0("browser", "MapBufferToSkBitmap()");
+  TRACE_EVENT0("browser", "MapBufferToSkBitmap");
 
   if (buf) {
     SkAutoLockPixels output_lock(*output);
@@ -116,7 +111,7 @@
   COMPILE_ASSERT(media::VideoFrame::kUPlane == 1, VideoFrame_kUPlane_mismatch);
   COMPILE_ASSERT(media::VideoFrame::kVPlane == 2, VideoFrame_kVPlane_mismatch);
 
-  TRACE_EVENT1("browser", "MapBufferToVideoFrame()", "plane", plane);
+  TRACE_EVENT1("browser", "MapBufferToVideoFrame", "plane", plane);
 
   // Apply black-out in the regions surrounding the view area (for
   // letterboxing/pillarboxing).  Only do this once, since this is performed on
@@ -167,8 +162,11 @@
   return kCVReturnSuccess;
 }
 
-CompositingIOSurfaceMac::CopyContext::CopyContext()
-  : num_outputs(0),
+CompositingIOSurfaceMac::CopyContext::CopyContext(
+    const scoped_refptr<CompositingIOSurfaceContext>& context)
+  : transformer(new CompositingIOSurfaceTransformer(
+        GL_TEXTURE_RECTANGLE_ARB, true, context->shader_program_cache())),
+    num_outputs(0),
     fence(0),
     cycles_elapsed(0) {
   memset(output_textures, 0, sizeof(output_textures));
@@ -177,23 +175,56 @@
 }
 
 CompositingIOSurfaceMac::CopyContext::~CopyContext() {
+  DCHECK_EQ(frame_buffers[0], 0u) << "Failed to call ReleaseCachedGLObjects().";
 }
 
-void CompositingIOSurfaceMac::CopyContext::CleanUp() {
-  glDeleteFramebuffersEXT(num_outputs, frame_buffers); CHECK_GL_ERROR();
-  glDeleteTextures(num_outputs, output_textures);
-  CHECK_GL_ERROR();
+void CompositingIOSurfaceMac::CopyContext::ReleaseCachedGLObjects() {
+  // No outstanding callbacks should be pending.
+  DCHECK(map_buffer_callback.is_null());
+  DCHECK(done_callback.is_null());
 
   // For an asynchronous read-back, there are more objects to delete:
   if (fence) {
-    glDeleteBuffers(num_outputs, pixel_buffers);
-    CHECK_GL_ERROR();
+    glDeleteBuffers(arraysize(pixel_buffers), pixel_buffers); CHECK_GL_ERROR();
+    memset(pixel_buffers, 0, sizeof(pixel_buffers));
     glDeleteFencesAPPLE(1, &fence); CHECK_GL_ERROR();
+    fence = 0;
+  }
+
+  glDeleteFramebuffersEXT(arraysize(frame_buffers), frame_buffers);
+  CHECK_GL_ERROR();
+  memset(frame_buffers, 0, sizeof(frame_buffers));
+
+  // Note: |output_textures| are owned by the transformer.
+  if (transformer)
+    transformer->ReleaseCachedGLObjects();
+}
+
+void CompositingIOSurfaceMac::CopyContext::PrepareReadbackFramebuffers() {
+  for (int i = 0; i < num_outputs; ++i) {
+    if (!frame_buffers[i]) {
+      glGenFramebuffersEXT(1, &frame_buffers[i]); CHECK_GL_ERROR();
+    }
   }
 }
 
+void CompositingIOSurfaceMac::CopyContext::PrepareForAsynchronousReadback() {
+  PrepareReadbackFramebuffers();
+  if (!fence) {
+    glGenFencesAPPLE(1, &fence); CHECK_GL_ERROR();
+  }
+  for (int i = 0; i < num_outputs; ++i) {
+    if (!pixel_buffers[i]) {
+      glGenBuffersARB(1, &pixel_buffers[i]); CHECK_GL_ERROR();
+    }
+  }
+}
+
+
 // static
-CompositingIOSurfaceMac* CompositingIOSurfaceMac::Create(SurfaceOrder order) {
+CompositingIOSurfaceMac* CompositingIOSurfaceMac::Create(
+    int window_number,
+    SurfaceOrder surface_order) {
   TRACE_EVENT0("browser", "CompositingIOSurfaceMac::Create");
   IOSurfaceSupport* io_surface_support = IOSurfaceSupport::Initialize();
   if (!io_surface_support) {
@@ -201,62 +232,8 @@
     return NULL;
   }
 
-  std::vector<NSOpenGLPixelFormatAttribute> attributes;
-  attributes.push_back(NSOpenGLPFADoubleBuffer);
-  // We don't need a depth buffer - try setting its size to 0...
-  attributes.push_back(NSOpenGLPFADepthSize); attributes.push_back(0);
-  if (ui::GpuSwitchingManager::GetInstance()->SupportsDualGpus())
-    attributes.push_back(NSOpenGLPFAAllowOfflineRenderers);
-  attributes.push_back(0);
-
-  scoped_nsobject<NSOpenGLPixelFormat> glPixelFormat(
-      [[NSOpenGLPixelFormat alloc] initWithAttributes:&attributes.front()]);
-  if (!glPixelFormat) {
-    LOG(ERROR) << "NSOpenGLPixelFormat initWithAttributes failed";
-    return NULL;
-  }
-
-  scoped_nsobject<NSOpenGLContext> glContext(
-      [[NSOpenGLContext alloc] initWithFormat:glPixelFormat
-                                 shareContext:nil]);
-  if (!glContext) {
-    LOG(ERROR) << "NSOpenGLContext initWithFormat failed";
-    return NULL;
-  }
-
-  // If requested, ask the WindowServer to render the OpenGL surface underneath
-  // the window. This, combined with a hole punched in the window, will allow
-  // for views to "overlap" the GL surface from the user's point of view.
-  if (order == SURFACE_ORDER_BELOW_WINDOW) {
-    GLint belowWindow = -1;
-    [glContext setValues:&belowWindow forParameter:NSOpenGLCPSurfaceOrder];
-  }
-
-  CGLContextObj cglContext = (CGLContextObj)[glContext CGLContextObj];
-  if (!cglContext) {
-    LOG(ERROR) << "CGLContextObj failed";
-    return NULL;
-  }
-
-  // Draw at beam vsync.
-  bool is_vsync_disabled =
-      CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableGpuVsync);
-  GLint swapInterval = is_vsync_disabled ? 0 : 1;
-  [glContext setValues:&swapInterval forParameter:NSOpenGLCPSwapInterval];
-
-  // Prepare the shader program cache.  Precompile only the shader programs
-  // needed to draw the IO Surface.
-  CGLSetCurrentContext(cglContext);
-  scoped_ptr<CompositingIOSurfaceShaderPrograms> shader_program_cache(
-      new CompositingIOSurfaceShaderPrograms());
-  const bool prepared = (shader_program_cache->UseBlitProgram(kTextureUnit) &&
-                         shader_program_cache->UseSolidWhiteProgram());
-  glUseProgram(0u);
-  CGLSetCurrentContext(0);
-  if (!prepared) {
-    LOG(ERROR) << "IOSurface failed to compile/link required shader programs.";
-    return NULL;
-  }
+  scoped_refptr<CompositingIOSurfaceContext> context =
+      CompositingIOSurfaceContext::Get(window_number, surface_order);
 
   CVDisplayLinkRef display_link;
   CVReturn ret = CVDisplayLinkCreateWithActiveCGDisplays(&display_link);
@@ -265,23 +242,17 @@
     return NULL;
   }
 
-  return new CompositingIOSurfaceMac(io_surface_support, glContext.release(),
-                                     cglContext,
-                                     shader_program_cache.Pass(),
-                                     is_vsync_disabled,
+  return new CompositingIOSurfaceMac(io_surface_support,
+                                     context,
                                      display_link);
 }
 
 CompositingIOSurfaceMac::CompositingIOSurfaceMac(
     IOSurfaceSupport* io_surface_support,
-    NSOpenGLContext* glContext,
-    CGLContextObj cglContext,
-    scoped_ptr<CompositingIOSurfaceShaderPrograms> shader_program_cache,
-    bool is_vsync_disabled,
+    scoped_refptr<CompositingIOSurfaceContext> context,
     CVDisplayLinkRef display_link)
     : io_surface_support_(io_surface_support),
-      glContext_(glContext),
-      cglContext_(cglContext),
+      context_(context),
       io_surface_handle_(0),
       texture_(0),
       finish_copy_timer_(
@@ -290,8 +261,6 @@
           base::Bind(&CompositingIOSurfaceMac::FinishAllCopies,
                      base::Unretained(this)),
           true),
-      shader_program_cache_(shader_program_cache.Pass()),
-      is_vsync_disabled_(is_vsync_disabled),
       display_link_(display_link),
       display_link_stop_timer_(FROM_HERE, base::TimeDelta::FromSeconds(1),
                                this, &CompositingIOSurfaceMac::StopDisplayLink),
@@ -323,6 +292,42 @@
   StopDisplayLink();
 }
 
+void CompositingIOSurfaceMac::SwitchToContextOnNewWindow(
+    NSView* view, int window_number) {
+  if (window_number == context_->window_number())
+    return;
+
+  // Asynchronous copies must complete in the same context they started in,
+  // defer updating the GL context to the new window until the copy finishes and
+  // all outstanding CopyContexts are destroyed.
+  if (!copy_requests_.empty())
+    return;
+  if (!copy_context_pool_.empty()) {
+    CGLSetCurrentContext(context_->cgl_context());
+    DestroyAllCopyContextsWithinContext();
+    CGLSetCurrentContext(0);
+  }
+
+  scoped_refptr<CompositingIOSurfaceContext> new_context =
+      CompositingIOSurfaceContext::Get(window_number,
+                                       context_->surface_order());
+  if (!new_context)
+    return;
+
+  // Having two NSOpenGLContexts bound to an NSView concurrently will cause
+  // artifacts and crashes. If |context_| is bound to |view|, then unbind
+  // |context_| before |new_context| gets bound to |view|.
+  // http://crbug.com/230883
+  if ([context_->nsgl_context() view] == view)
+    [context_->nsgl_context() clearDrawable];
+
+  context_ = new_context;
+}
+
+bool CompositingIOSurfaceMac::is_vsync_disabled() const {
+  return context_->is_vsync_disabled();
+}
+
 void CompositingIOSurfaceMac::GetVSyncParameters(base::TimeTicks* timebase,
                                                  uint32* interval_numerator,
                                                  uint32* interval_denominator) {
@@ -335,24 +340,24 @@
 CompositingIOSurfaceMac::~CompositingIOSurfaceMac() {
   FailAllCopies();
   CVDisplayLinkRelease(display_link_);
-  CGLSetCurrentContext(cglContext_);
-  CleanupAllCopiesWithinContext();
+  CGLSetCurrentContext(context_->cgl_context());
+  DestroyAllCopyContextsWithinContext();
   UnrefIOSurfaceWithContextCurrent();
-  shader_program_cache_->Reset();
   CGLSetCurrentContext(0);
+  context_ = nil;
 }
 
 void CompositingIOSurfaceMac::SetIOSurface(uint64 io_surface_handle,
                                            const gfx::Size& size) {
   pixel_io_surface_size_ = size;
-  CGLSetCurrentContext(cglContext_);
+  CGLSetCurrentContext(context_->cgl_context());
   MapIOSurfaceToTexture(io_surface_handle);
   CGLSetCurrentContext(0);
 }
 
 int CompositingIOSurfaceMac::GetRendererID() {
   GLint current_renderer_id = -1;
-  if (CGLGetParameter(cglContext_,
+  if (CGLGetParameter(context_->cgl_context(),
                       kCGLCPCurrentRendererID,
                       &current_renderer_id) == kCGLNoError)
     return current_renderer_id & kCGLRendererIDMatchingMask;
@@ -360,16 +365,20 @@
 }
 
 void CompositingIOSurfaceMac::DrawIOSurface(
-    NSView* view, float scale_factor,
+    NSView* view,
+    float scale_factor,
+    int window_number,
     RenderWidgetHostViewFrameSubscriber* frame_subscriber) {
-  CGLSetCurrentContext(cglContext_);
+  SwitchToContextOnNewWindow(view, window_number);
+
+  CGLSetCurrentContext(context_->cgl_context());
 
   bool has_io_surface = MapIOSurfaceToTexture(io_surface_handle_);
 
   TRACE_EVENT1("browser", "CompositingIOSurfaceMac::DrawIOSurface",
                "has_io_surface", has_io_surface);
 
-  [glContext_ setView:view];
+  [context_->nsgl_context() setView:view];
   gfx::Size window_size(NSSizeToCGSize([view frame].size));
   gfx::Size pixel_window_size = gfx::ToFlooredSize(
       gfx::ScaleSize(window_size, scale_factor));
@@ -395,8 +404,8 @@
   glDisable(GL_BLEND);
 
   if (has_io_surface) {
-    shader_program_cache_->UseBlitProgram(kTextureUnit);
-    glActiveTexture(GL_TEXTURE0 + kTextureUnit);
+    context_->shader_program_cache()->UseBlitProgram();
+    glActiveTexture(GL_TEXTURE0);
     glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture_);
 
     DrawQuad(quad_);
@@ -406,7 +415,7 @@
     // Fill the resize gutters with white.
     if (window_size.width() > io_surface_size_.width() ||
         window_size.height() > io_surface_size_.height()) {
-      shader_program_cache_->UseSolidWhiteProgram();
+      context_->shader_program_cache()->UseSolidWhiteProgram();
       SurfaceQuad filler_quad;
       if (window_size.width() > io_surface_size_.width()) {
         // Draw right-side gutter down to the bottom of the window.
@@ -464,19 +473,21 @@
 
   base::Closure copy_done_callback;
   if (frame_subscriber) {
+    const base::Time present_time = base::Time::Now();
     scoped_refptr<media::VideoFrame> frame;
     RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback callback;
-    if (frame_subscriber->ShouldCaptureFrame(&frame, &callback)) {
+    if (frame_subscriber->ShouldCaptureFrame(present_time, &frame, &callback)) {
       copy_done_callback = CopyToVideoFrameWithinContext(
-          gfx::Rect(io_surface_size_), scale_factor, true, frame,
-          base::Bind(callback, base::Time::Now()));
+          gfx::Rect(pixel_io_surface_size_), scale_factor, true, frame,
+          base::Bind(callback, present_time));
     }
   }
 
-  CGLFlushDrawable(cglContext_);
+  CGLFlushDrawable(context_->cgl_context());
 
   // For latency_tests.cc:
-  UNSHIPPED_TRACE_EVENT_INSTANT0("test_gpu", "CompositorSwapBuffersComplete");
+  UNSHIPPED_TRACE_EVENT_INSTANT0("test_gpu", "CompositorSwapBuffersComplete",
+                                 TRACE_EVENT_SCOPE_THREAD);
 
   // Try to finish previous copy requests after flush to get better pipelining.
   std::vector<base::Closure> copy_done_callbacks;
@@ -491,7 +502,7 @@
 
   StartOrContinueDisplayLink();
 
-  if (!is_vsync_disabled_)
+  if (!is_vsync_disabled())
     RateLimitDraws();
 }
 
@@ -512,7 +523,7 @@
       << "Stride is required to be equal to width for GPU readback.";
   output->setIsOpaque(true);
 
-  CGLSetCurrentContext(cglContext_);
+  CGLSetCurrentContext(context_->cgl_context());
   const base::Closure copy_done_callback = CopyToSelectedOutputWithinContext(
       src_pixel_subrect, src_scale_factor, gfx::Rect(dst_pixel_size), false,
       output.get(), NULL,
@@ -527,7 +538,7 @@
     float src_scale_factor,
     const scoped_refptr<media::VideoFrame>& target,
     const base::Callback<void(bool)>& callback) {
-  CGLSetCurrentContext(cglContext_);
+  CGLSetCurrentContext(context_->cgl_context());
   const base::Closure copy_done_callback = CopyToVideoFrameWithinContext(
       src_pixel_subrect, src_scale_factor, false, target, callback);
   CGLSetCurrentContext(0);
@@ -571,7 +582,7 @@
       static_cast<uint32>(io_surface_handle)));
   // Can fail if IOSurface with that ID was already released by the gpu
   // process.
-  if (!io_surface_.get()) {
+  if (!io_surface_) {
     io_surface_handle_ = 0;
     return false;
   }
@@ -595,7 +606,7 @@
   glTexParameterf(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); CHECK_GL_ERROR();
   GLuint plane = 0;
   CGLError cglerror = io_surface_support_->CGLTexImageIOSurface2D(
-      cglContext_,
+      context_->cgl_context(),
       target,
       GL_RGBA,
       rounded_size.width(),
@@ -614,7 +625,7 @@
 }
 
 void CompositingIOSurfaceMac::UnrefIOSurface() {
-  CGLSetCurrentContext(cglContext_);
+  CGLSetCurrentContext(context_->cgl_context());
   UnrefIOSurfaceWithContextCurrent();
   CGLSetCurrentContext(0);
 }
@@ -633,7 +644,7 @@
 
 bool CompositingIOSurfaceMac::IsVendorIntel() {
   GLint screen;
-  CGLGetVirtualScreen(cglContext_, &screen);
+  CGLGetVirtualScreen(context_->cgl_context(), &screen);
   if (screen != screen_)
     initialized_is_intel_ = false;
   screen_ = screen;
@@ -660,11 +671,11 @@
 }
 
 void CompositingIOSurfaceMac::GlobalFrameDidChange() {
-  [glContext_ update];
+  [context_->nsgl_context() update];
 }
 
 void CompositingIOSurfaceMac::ClearDrawable() {
-  [glContext_ clearDrawable];
+  [context_->nsgl_context() clearDrawable];
   UnrefIOSurface();
 }
 
@@ -733,7 +744,10 @@
 bool CompositingIOSurfaceMac::IsAsynchronousReadbackSupported() {
   // Using PBO crashes on Intel drivers but not on newer Mountain Lion
   // systems. See bug http://crbug.com/152225.
-  return (HasAppleFenceExtension() &&
+  const bool forced_synchronous = CommandLine::ForCurrentProcess()->HasSwitch(
+                                      switches::kForceSynchronousGLReadPixels);
+  return (!forced_synchronous &&
+          HasAppleFenceExtension() &&
           HasPixelBufferObjectExtension() &&
           (base::mac::IsOSMountainLionOrLater() || !IsVendorIntel()));
 }
@@ -751,54 +765,65 @@
 
   const bool async_copy = IsAsynchronousReadbackSupported();
   TRACE_EVENT2(
-      "browser", "CompositingIOSurfaceMac::CopyToSelectedOutputWithinContext()",
+      "browser", "CompositingIOSurfaceMac::CopyToSelectedOutputWithinContext",
       "output", bitmap_output ? "SkBitmap (ARGB)" : "VideoFrame (YV12)",
       "async_readback", async_copy);
 
+  CopyContext* copy_context;
+  if (copy_context_pool_.empty()) {
+    // Limit the maximum number of simultaneous copies to two.  Rationale:
+    // Really, only one should ever be in-progress at a time, as we should
+    // depend on the speed of the hardware to rate-limit the copying naturally.
+    // In the asynchronous read-back case, the one currently in-flight copy is
+    // highly likely to have finished by this point (i.e., it's just waiting for
+    // us to make a glMapBuffer() call).  Therefore, we allow a second copy to
+    // be started here.
+    if (copy_requests_.size() >= 2)
+      return base::Bind(done_callback, false);
+    copy_context = new CopyContext(context_);
+  } else {
+    copy_context = copy_context_pool_.back();
+    copy_context_pool_.pop_back();
+  }
+
   // Set up source texture, bound to the GL_TEXTURE_RECTANGLE_ARB target.
   if (!MapIOSurfaceToTexture(io_surface_handle_))
     return base::Bind(done_callback, false);
 
-  // Create the transformer_ on first use.
-  if (!transformer_) {
-    transformer_.reset(new CompositingIOSurfaceTransformer(
-        GL_TEXTURE_RECTANGLE_ARB, kTextureUnit, true,
-        shader_program_cache_.get()));
-  }
-
   // Send transform commands to the GPU.
   const gfx::Rect src_rect = IntersectWithIOSurface(src_pixel_subrect,
                                                     src_scale_factor);
-  CopyContext copy_context;
+  copy_context->num_outputs = 0;
   if (bitmap_output) {
-    if (transformer_->ResizeBilinear(texture_, src_rect, dst_pixel_rect.size(),
-                                     &copy_context.output_textures[0])) {
-      copy_context.num_outputs = 1;
-      copy_context.output_texture_sizes[0] = dst_pixel_rect.size();
+    if (copy_context->transformer->ResizeBilinear(
+            texture_, src_rect, dst_pixel_rect.size(),
+            &copy_context->output_textures[0])) {
+      copy_context->num_outputs = 1;
+      copy_context->output_texture_sizes[0] = dst_pixel_rect.size();
     }
   } else {
-    if (transformer_->TransformRGBToYV12(
+    if (copy_context->transformer->TransformRGBToYV12(
             texture_, src_rect, dst_pixel_rect.size(),
-            &copy_context.output_textures[0],
-            &copy_context.output_textures[1],
-            &copy_context.output_textures[2],
-            &copy_context.output_texture_sizes[0],
-            &copy_context.output_texture_sizes[1])) {
-      copy_context.num_outputs = 3;
-      copy_context.output_texture_sizes[2] =
-          copy_context.output_texture_sizes[1];
+            &copy_context->output_textures[0],
+            &copy_context->output_textures[1],
+            &copy_context->output_textures[2],
+            &copy_context->output_texture_sizes[0],
+            &copy_context->output_texture_sizes[1])) {
+      copy_context->num_outputs = 3;
+      copy_context->output_texture_sizes[2] =
+          copy_context->output_texture_sizes[1];
     }
   }
-  if (!copy_context.num_outputs)
+  if (!copy_context->num_outputs)
     return base::Bind(done_callback, false);
 
   // In the asynchronous case, issue commands to the GPU and return a null
   // closure here.  In the synchronous case, perform a blocking readback and
   // return a callback to be run outside the CGL context to indicate success.
   if (async_copy) {
-    copy_context.done_callback = done_callback;
+    copy_context->done_callback = done_callback;
     AsynchronousReadbackForCopy(
-        dst_pixel_rect, called_within_draw, &copy_context, bitmap_output,
+        dst_pixel_rect, called_within_draw, copy_context, bitmap_output,
         video_frame_output);
     copy_requests_.push_back(copy_context);
     if (!finish_copy_timer_.IsRunning())
@@ -806,7 +831,7 @@
     return base::Closure();
   } else {
     const bool success = SynchronousReadbackForCopy(
-        dst_pixel_rect, &copy_context, bitmap_output, video_frame_output);
+        dst_pixel_rect, copy_context, bitmap_output, video_frame_output);
     return base::Bind(done_callback, success);
   }
 }
@@ -817,16 +842,12 @@
     CopyContext* copy_context,
     const SkBitmap* bitmap_output,
     const scoped_refptr<media::VideoFrame>& video_frame_output) {
-  glGenFencesAPPLE(1, &copy_context->fence); CHECK_GL_ERROR();
+  copy_context->PrepareForAsynchronousReadback();
 
-  // Copy the textures to a PBO.
-  glGenFramebuffersEXT(copy_context->num_outputs, copy_context->frame_buffers);
-  CHECK_GL_ERROR();
-  glGenBuffersARB(copy_context->num_outputs, copy_context->pixel_buffers);
-  CHECK_GL_ERROR();
+  // Copy the textures to their corresponding PBO.
   for (int i = 0; i < copy_context->num_outputs; ++i) {
     TRACE_EVENT1(
-        "browser", "CompositingIOSurfaceMac::AsynchronousReadbackForCopy()",
+        "browser", "CompositingIOSurfaceMac::AsynchronousReadbackForCopy",
         "plane", i);
 
     // Attach the output texture to the FBO.
@@ -854,8 +875,9 @@
   glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); CHECK_GL_ERROR();
 
   glSetFenceAPPLE(copy_context->fence); CHECK_GL_ERROR();
+  copy_context->cycles_elapsed = 0;
 
-  // When this asynchronous copy happens in a draw operaton there is not need
+  // When this asynchronous copy happens in a draw operaton there is no need
   // to explicitly flush because there will be a swap buffer and this flush
   // hurts performance.
   if (!called_within_draw) {
@@ -869,7 +891,7 @@
 
 void CompositingIOSurfaceMac::FinishAllCopies() {
   std::vector<base::Closure> done_callbacks;
-  CGLSetCurrentContext(cglContext_);
+  CGLSetCurrentContext(context_->cgl_context());
   FinishAllCopiesWithinContext(&done_callbacks);
   CGLSetCurrentContext(0);
   for (size_t i = 0; i < done_callbacks.size(); ++i)
@@ -879,15 +901,15 @@
 void CompositingIOSurfaceMac::FinishAllCopiesWithinContext(
     std::vector<base::Closure>* done_callbacks) {
   while (!copy_requests_.empty()) {
-    CopyContext& copy_context = copy_requests_.front();
+    CopyContext* const copy_context = copy_requests_.front();
 
-    if (copy_context.fence) {
-      const bool copy_completed = glTestFenceAPPLE(copy_context.fence);
+    if (copy_context->fence) {
+      const bool copy_completed = glTestFenceAPPLE(copy_context->fence);
       CHECK_GL_ERROR();
 
       if (!copy_completed &&
-        copy_context.cycles_elapsed < kFinishCopyRetryCycles) {
-        ++copy_context.cycles_elapsed;
+        copy_context->cycles_elapsed < kFinishCopyRetryCycles) {
+        ++copy_context->cycles_elapsed;
         // This copy has not completed there is no need to test subsequent
         // requests.
         break;
@@ -895,24 +917,26 @@
     }
 
     bool success = true;
-    for (int i = 0; success && i < copy_context.num_outputs; ++i) {
+    for (int i = 0; success && i < copy_context->num_outputs; ++i) {
       TRACE_EVENT1(
-        "browser", "CompositingIOSurfaceMac::FinishAllCopyWithinContext()",
+        "browser", "CompositingIOSurfaceMac::FinishAllCopiesWithinContext",
         "plane", i);
 
-      glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, copy_context.pixel_buffers[i]);
+      glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, copy_context->pixel_buffers[i]);
       CHECK_GL_ERROR();
 
       void* buf = glMapBuffer(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY_ARB);
       CHECK_GL_ERROR();
-      success &= copy_context.map_buffer_callback.Run(buf, i);
+      success &= copy_context->map_buffer_callback.Run(buf, i);
       glUnmapBufferARB(GL_PIXEL_PACK_BUFFER_ARB); CHECK_GL_ERROR();
     }
-
+    copy_context->map_buffer_callback.Reset();
     glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0); CHECK_GL_ERROR();
-    copy_context.CleanUp();
-    done_callbacks->push_back(base::Bind(copy_context.done_callback, success));
+
     copy_requests_.pop_front();
+    done_callbacks->push_back(base::Bind(copy_context->done_callback, success));
+    copy_context->done_callback.Reset();
+    copy_context_pool_.push_back(copy_context);
   }
   if (copy_requests_.empty())
     finish_copy_timer_.Stop();
@@ -924,11 +948,10 @@
     const SkBitmap* bitmap_output,
     const scoped_refptr<media::VideoFrame>& video_frame_output) {
   bool success = true;
-  glGenFramebuffersEXT(copy_context->num_outputs, copy_context->frame_buffers);
-  CHECK_GL_ERROR();
+  copy_context->PrepareReadbackFramebuffers();
   for (int i = 0; i < copy_context->num_outputs; ++i) {
     TRACE_EVENT1(
-        "browser", "CompositingIOSurfaceMac::SynchronousReadbackForCopy()",
+        "browser", "CompositingIOSurfaceMac::SynchronousReadbackForCopy",
         "plane", i);
 
     // Attach the output texture to the FBO.
@@ -992,19 +1015,34 @@
   }
 
   glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0); CHECK_GL_ERROR();
-  copy_context->CleanUp();
+  copy_context_pool_.push_back(copy_context);
   return success;
 }
 
-void CompositingIOSurfaceMac::CleanupAllCopiesWithinContext() {
-  for (size_t i = 0; i < copy_requests_.size(); ++i)
-    copy_requests_[i].CleanUp();
-  copy_requests_.clear();
+void CompositingIOSurfaceMac::FailAllCopies() {
+  for (size_t i = 0; i < copy_requests_.size(); ++i) {
+    copy_requests_[i]->map_buffer_callback.Reset();
+
+    base::Callback<void(bool)>& done_callback =
+        copy_requests_[i]->done_callback;
+    if (!done_callback.is_null()) {
+      done_callback.Run(false);
+      done_callback.Reset();
+    }
+  }
 }
 
-void CompositingIOSurfaceMac::FailAllCopies() {
-  for (size_t i = 0; i < copy_requests_.size(); ++i)
-    copy_requests_[i].done_callback.Run(false);
+void CompositingIOSurfaceMac::DestroyAllCopyContextsWithinContext() {
+  // Move all in-flight copies, if any, back into the pool.  Then, destroy all
+  // the CopyContexts in the pool.
+  copy_context_pool_.insert(copy_context_pool_.end(),
+                            copy_requests_.begin(), copy_requests_.end());
+  copy_requests_.clear();
+  while (!copy_context_pool_.empty()) {
+    scoped_ptr<CopyContext> copy_context(copy_context_pool_.back());
+    copy_context_pool_.pop_back();
+    copy_context->ReleaseCachedGLObjects();
+  }
 }
 
 gfx::Rect CompositingIOSurfaceMac::IntersectWithIOSurface(
diff --git a/content/browser/renderer_host/compositing_iosurface_shader_programs_mac.cc b/content/browser/renderer_host/compositing_iosurface_shader_programs_mac.cc
index 40575df..12988a1 100644
--- a/content/browser/renderer_host/compositing_iosurface_shader_programs_mac.cc
+++ b/content/browser/renderer_host/compositing_iosurface_shader_programs_mac.cc
@@ -332,13 +332,12 @@
     texel_scale_x_var_locations_[i] = -1;
 }
 
-bool CompositingIOSurfaceShaderPrograms::UseBlitProgram(
-    int texture_unit_offset) {
+bool CompositingIOSurfaceShaderPrograms::UseBlitProgram() {
   const GLuint program = GetShaderProgram(SHADER_PROGRAM_BLIT);
   if (program == 0u)
     return false;
   glUseProgram(program);
-  BindUniformTextureVariable(SHADER_PROGRAM_BLIT, texture_unit_offset);
+  BindUniformTextureVariable(SHADER_PROGRAM_BLIT, 0);
   return true;
 }
 
@@ -351,7 +350,7 @@
 }
 
 bool CompositingIOSurfaceShaderPrograms::UseRGBToYV12Program(
-    int pass_number, int texture_unit_offset, float texel_scale_x) {
+    int pass_number, float texel_scale_x) {
   const int which = SHADER_PROGRAM_RGB_TO_YV12__1_OF_2 + pass_number - 1;
   DCHECK_GE(which, SHADER_PROGRAM_RGB_TO_YV12__1_OF_2);
   DCHECK_LE(which, SHADER_PROGRAM_RGB_TO_YV12__2_OF_2);
@@ -360,7 +359,7 @@
   if (program == 0u)
     return false;
   glUseProgram(program);
-  BindUniformTextureVariable(which, texture_unit_offset);
+  BindUniformTextureVariable(which, 0);
   if (which == SHADER_PROGRAM_RGB_TO_YV12__1_OF_2) {
     BindUniformTexelScaleXVariable(which, texel_scale_x);
   } else {
diff --git a/content/browser/renderer_host/compositing_iosurface_shader_programs_mac.h b/content/browser/renderer_host/compositing_iosurface_shader_programs_mac.h
index ce6bfa9..152858c 100644
--- a/content/browser/renderer_host/compositing_iosurface_shader_programs_mac.h
+++ b/content/browser/renderer_host/compositing_iosurface_shader_programs_mac.h
@@ -26,8 +26,8 @@
   void Reset();
 
   // Begin using the "blit" program, which is set up to sample the texture at
-  // GL_TEXTURE_0 + |texture_unit_offset|.  Returns false on error.
-  bool UseBlitProgram(int texture_unit_offset);
+  // GL_TEXTURE_0.  Returns false on error.
+  bool UseBlitProgram();
 
   // Begin using the program that just draws solid white very efficiently.
   // Returns false on error.
@@ -35,10 +35,9 @@
 
   // Begin using one of the two RGB-to-YV12 color conversion programs, as
   // specified by |pass_number| 1 or 2.  The programs will sample the texture at
-  // GL_TEXTURE0 + |texture_unit_offset|, and account for scaling in the X
-  // direction by |texel_scale_x|.  Returns false on error.
-  bool UseRGBToYV12Program(
-      int pass_number, int texture_unit_offset, float texel_scale_x);
+  // GL_TEXTURE0, and account for scaling in the X direction by |texel_scale_x|.
+  // Returns false on error.
+  bool UseRGBToYV12Program(int pass_number, float texel_scale_x);
 
  private:
   enum { kNumShaderPrograms = 4 };
diff --git a/content/browser/renderer_host/compositing_iosurface_transformer_mac.cc b/content/browser/renderer_host/compositing_iosurface_transformer_mac.cc
index be9d264..2e0401f 100644
--- a/content/browser/renderer_host/compositing_iosurface_transformer_mac.cc
+++ b/content/browser/renderer_host/compositing_iosurface_transformer_mac.cc
@@ -17,68 +17,11 @@
 
 namespace {
 
-// Simple auto-delete scoping support for an owned Framebuffer object.
-class ScopedFramebuffer {
- public:
-  ScopedFramebuffer() {
-    glGenFramebuffersEXT(1, &name_);
-  }
-
-  ~ScopedFramebuffer() {
-    if (name_ != 0u)
-      glDeleteFramebuffersEXT(1, &name_);
-  }
-
-  bool is_valid() const { return name_ != 0u; }
-  GLuint name() const { return name_; }
-
- private:
-  GLuint name_;
-
-  DISALLOW_COPY_AND_ASSIGN(ScopedFramebuffer);
+const GLenum kColorAttachments[] = {
+  GL_COLOR_ATTACHMENT0_EXT,
+  GL_COLOR_ATTACHMENT1_EXT
 };
 
-// Simple auto-delete scoping support for an owned texture object.
-class ScopedTexture {
- public:
-  ScopedTexture() : name_(0u) {}
-  ScopedTexture(GLenum target, const gfx::Size& size);
-
-  ~ScopedTexture() {
-    if (name_ != 0u)
-      glDeleteTextures(1, &name_);
-  }
-
-  bool is_valid() const { return name_ != 0u; }
-  GLuint name() const { return name_; }
-
-  void Reset(GLuint texture) {
-    if (name_ != 0u)
-      glDeleteTextures(1, &name_);
-    name_ = texture;
-  }
-
-  GLuint Release() {
-    GLuint ret = name_;
-    name_ = 0u;
-    return ret;
-  }
-
- private:
-  GLuint name_;
-
-  DISALLOW_COPY_AND_ASSIGN(ScopedTexture);
-};
-
-ScopedTexture::ScopedTexture(GLenum target, const gfx::Size& size) {
-  glGenTextures(1, &name_);
-  glBindTexture(target, name_);
-  glTexImage2D(target, 0, GL_RGBA, size.width(), size.height(), 0, GL_BGRA,
-               GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
-  DCHECK(glGetError() == GL_NO_ERROR);
-  glBindTexture(target, 0u);
-}
-
 // Set viewport and model/projection matrices for drawing to a framebuffer of
 // size dst_size, with coordinates starting at (0, 0).
 void SetTransformationsForOffScreenRendering(const gfx::Size& dst_size) {
@@ -142,16 +85,18 @@
 }  // namespace
 
 CompositingIOSurfaceTransformer::CompositingIOSurfaceTransformer(
-    GLenum texture_target, GLint texture_unit, bool src_texture_needs_y_flip,
+    GLenum texture_target, bool src_texture_needs_y_flip,
     CompositingIOSurfaceShaderPrograms* shader_program_cache)
     : texture_target_(texture_target),
-      texture_unit_(texture_unit),
       src_texture_needs_y_flip_(src_texture_needs_y_flip),
-      shader_program_cache_(shader_program_cache) {
+      shader_program_cache_(shader_program_cache),
+      frame_buffer_(0) {
   DCHECK(texture_target_ == GL_TEXTURE_RECTANGLE_ARB)
       << "Fragment shaders currently only support RECTANGLE textures.";
   DCHECK(shader_program_cache_);
 
+  memset(textures_, 0, sizeof(textures_));
+
   // The RGB-to-YV12 transform requires that the driver/hardware supports
   // multiple draw buffers.
   GLint max_draw_buffers = 1;
@@ -160,6 +105,23 @@
 }
 
 CompositingIOSurfaceTransformer::~CompositingIOSurfaceTransformer() {
+  for (int i = 0; i < NUM_CACHED_TEXTURES; ++i)
+    DCHECK_EQ(textures_[i], 0u) << "Failed to call ReleaseCachedGLObjects().";
+  DCHECK_EQ(frame_buffer_, 0u) << "Failed to call ReleaseCachedGLObjects().";
+}
+
+void CompositingIOSurfaceTransformer::ReleaseCachedGLObjects() {
+  for (int i = 0; i < NUM_CACHED_TEXTURES; ++i) {
+    if (textures_[i]) {
+      glDeleteTextures(1, &textures_[i]);
+      textures_[i] = 0;
+      texture_sizes_[i] = gfx::Size();
+    }
+  }
+  if (frame_buffer_) {
+    glDeleteFramebuffersEXT(1, &frame_buffer_);
+    frame_buffer_ = 0;
+  }
 }
 
 bool CompositingIOSurfaceTransformer::ResizeBilinear(
@@ -168,18 +130,15 @@
   if (src_subrect.IsEmpty() || dst_size.IsEmpty())
     return false;
 
-  glActiveTexture(GL_TEXTURE0 + texture_unit_);
+  glActiveTexture(GL_TEXTURE0);
   glDisable(GL_DEPTH_TEST);
   glDisable(GL_BLEND);
 
-  ScopedTexture dst_texture(texture_target_, dst_size);
-  if (!dst_texture.is_valid())
-    return false;
-
-  ScopedFramebuffer temp_frame_buffer;
-  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, temp_frame_buffer.name());
+  PrepareTexture(RGBA_OUTPUT, dst_size);
+  PrepareFramebuffer();
+  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, frame_buffer_);
   glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
-                            texture_target_, dst_texture.name(), 0);
+                            texture_target_, textures_[RGBA_OUTPUT], 0);
   DCHECK(glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) ==
              GL_FRAMEBUFFER_COMPLETE_EXT);
 
@@ -188,7 +147,7 @@
       texture_target_, src_subrect.size() == dst_size ? GL_NEAREST : GL_LINEAR,
       GL_CLAMP_TO_EDGE);
 
-  const bool prepared = shader_program_cache_->UseBlitProgram(texture_unit_);
+  const bool prepared = shader_program_cache_->UseBlitProgram();
   DCHECK(prepared);
   SetTransformationsForOffScreenRendering(dst_size);
   DrawQuad(src_subrect.x(), src_subrect.y(),
@@ -196,9 +155,11 @@
            src_texture_needs_y_flip_,
            dst_size.width(), dst_size.height());
   glUseProgram(0);
-  glBindTexture(texture_target_, 0u);
 
-  *texture = dst_texture.Release();
+  glBindTexture(texture_target_, 0);
+  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+
+  *texture = textures_[RGBA_OUTPUT];
   return true;
 }
 
@@ -218,11 +179,11 @@
 
   TRACE_EVENT0("gpu", "TransformRGBToYV12");
 
-  glActiveTexture(GL_TEXTURE0 + texture_unit_);
+  glActiveTexture(GL_TEXTURE0);
   glDisable(GL_DEPTH_TEST);
   glDisable(GL_BLEND);
 
-  // Allocate output textures for each plane, and the temporary one for the UUVV
+  // Resize output textures for each plane, and for the intermediate UUVV one
   // that becomes an input into pass #2.  |packed_y_size| is the size of the Y
   // output texture, where its width is 1/4 the number of Y pixels because 4 Y
   // pixels are packed into a single quad.  |packed_uv_size| is half the size of
@@ -230,36 +191,22 @@
   *packed_y_size = gfx::Size((dst_size.width() + 3) / 4, dst_size.height());
   *packed_uv_size = gfx::Size((packed_y_size->width() + 1) / 2,
                               (packed_y_size->height() + 1) / 2);
-  ScopedTexture temp_texture_y(texture_target_, *packed_y_size);
-  if (!temp_texture_y.is_valid())
-    return false;
-  ScopedTexture temp_texture_u(texture_target_, *packed_uv_size);
-  if (!temp_texture_u.is_valid())
-    return false;
-  ScopedTexture temp_texture_v(texture_target_, *packed_uv_size);
-  if (!temp_texture_v.is_valid())
-    return false;
-
-  // Create a temporary texture for the UUVV that becomes an input into pass #2.
-  ScopedTexture temp_texture_uuvv(texture_target_, *packed_y_size);
-  if (!temp_texture_uuvv.is_valid())
-    return false;
-
-  // Create a temporary FBO for writing to the textures off-screen.
-  ScopedFramebuffer temp_frame_buffer;
-  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, temp_frame_buffer.name());
+  PrepareTexture(Y_PLANE_OUTPUT, *packed_y_size);
+  PrepareTexture(UUVV_INTERMEDIATE, *packed_y_size);
+  PrepareTexture(U_PLANE_OUTPUT, *packed_uv_size);
+  PrepareTexture(V_PLANE_OUTPUT, *packed_uv_size);
 
   /////////////////////////////////////////
   // Pass 1: RGB --(scaled)--> YYYY + UUVV
+  PrepareFramebuffer();
+  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, frame_buffer_);
   glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
-                            texture_target_, temp_texture_y.name(), 0);
+                            texture_target_, textures_[Y_PLANE_OUTPUT], 0);
   glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT,
-                            texture_target_, temp_texture_uuvv.name(), 0);
+                            texture_target_, textures_[UUVV_INTERMEDIATE], 0);
   DCHECK(glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) ==
              GL_FRAMEBUFFER_COMPLETE_EXT);
-  static const GLenum kAttachments[] =
-      { GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT };
-  glDrawBuffers(2, kAttachments);
+  glDrawBuffers(2, kColorAttachments);
 
   // Read from |src_texture|.  Enable bilinear filtering only if scaling is
   // required.  The filtering will take place entirely in the first pass.
@@ -270,7 +217,7 @@
 
   // Use the first-pass shader program and draw the scene.
   const bool prepared_pass_1 = shader_program_cache_->UseRGBToYV12Program(
-      1, texture_unit_,
+      1,
       static_cast<float>(src_subrect.width()) / dst_size.width());
   DCHECK(prepared_pass_1);
   SetTransformationsForOffScreenRendering(*packed_y_size);
@@ -284,20 +231,20 @@
   /////////////////////////////////////////
   // Pass 2: UUVV -> UUUU + VVVV
   glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
-                            texture_target_, temp_texture_u.name(), 0);
+                            texture_target_, textures_[U_PLANE_OUTPUT], 0);
   glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT,
-                            texture_target_, temp_texture_v.name(), 0);
+                            texture_target_, textures_[V_PLANE_OUTPUT], 0);
   DCHECK(glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) ==
              GL_FRAMEBUFFER_COMPLETE_EXT);
 
-  // Read from texture_uuvv.  The second pass uses bilinear minification to
-  // achieve vertical scaling, so enable it always.
-  glBindTexture(texture_target_, temp_texture_uuvv.name());
+  // Read from the intermediate UUVV texture.  The second pass uses bilinear
+  // minification to achieve vertical scaling, so enable it always.
+  glBindTexture(texture_target_, textures_[UUVV_INTERMEDIATE]);
   SetTextureParameters(texture_target_, GL_LINEAR, GL_CLAMP_TO_EDGE);
 
   // Use the second-pass shader program and draw the scene.
   const bool prepared_pass_2 =
-      shader_program_cache_->UseRGBToYV12Program(2, texture_unit_, 1.0f);
+      shader_program_cache_->UseRGBToYV12Program(2, 1.0f);
   DCHECK(prepared_pass_2);
   SetTransformationsForOffScreenRendering(*packed_uv_size);
   DrawQuad(0.0f, 0.0f,
@@ -306,15 +253,48 @@
            false,
            packed_uv_size->width(), packed_uv_size->height());
   glUseProgram(0);
-  glBindTexture(texture_target_, 0);
 
   // Before leaving, put back to drawing to a single rendering output.
-  glDrawBuffers(1, kAttachments);
+  glDrawBuffers(1, kColorAttachments);
 
-  *texture_y = temp_texture_y.Release();
-  *texture_u = temp_texture_u.Release();
-  *texture_v = temp_texture_v.Release();
+  glBindTexture(texture_target_, 0);
+  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+
+  *texture_y = textures_[Y_PLANE_OUTPUT];
+  *texture_u = textures_[U_PLANE_OUTPUT];
+  *texture_v = textures_[V_PLANE_OUTPUT];
   return true;
 }
 
+void CompositingIOSurfaceTransformer::PrepareTexture(
+    CachedTexture which, const gfx::Size& size) {
+  DCHECK_GE(which, 0);
+  DCHECK_LT(which, NUM_CACHED_TEXTURES);
+  DCHECK(!size.IsEmpty());
+
+  if (!textures_[which]) {
+    glGenTextures(1, &textures_[which]);
+    DCHECK_NE(textures_[which], 0u);
+    texture_sizes_[which] = gfx::Size();
+  }
+
+  // Re-allocate the texture if its size has changed since last use.
+  if (texture_sizes_[which] != size) {
+    TRACE_EVENT2("gpu", "Resize Texture",
+                 "which", which,
+                 "new_size", size.ToString());
+    glBindTexture(texture_target_, textures_[which]);
+    glTexImage2D(texture_target_, 0, GL_RGBA, size.width(), size.height(), 0,
+                 GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
+    texture_sizes_[which] = size;
+  }
+}
+
+void CompositingIOSurfaceTransformer::PrepareFramebuffer() {
+  if (!frame_buffer_) {
+    glGenFramebuffersEXT(1, &frame_buffer_);
+    DCHECK_NE(frame_buffer_, 0u);
+  }
+}
+
 }  // namespace content
diff --git a/content/browser/renderer_host/compositing_iosurface_transformer_mac.h b/content/browser/renderer_host/compositing_iosurface_transformer_mac.h
index c38c0e0..4890074 100644
--- a/content/browser/renderer_host/compositing_iosurface_transformer_mac.h
+++ b/content/browser/renderer_host/compositing_iosurface_transformer_mac.h
@@ -9,10 +9,10 @@
 
 #include "base/basictypes.h"
 #include "content/browser/renderer_host/compositing_iosurface_shader_programs_mac.h"
+#include "ui/gfx/size.h"
 
 namespace gfx {
 class Rect;
-class Size;
 }  // namespace gfx
 
 namespace content {
@@ -25,20 +25,25 @@
  public:
   // Construct a transformer that always uses the given parameters for texture
   // bindings.  |texture_target| is one of the valid enums to use with
-  // glBindTexture().  |texture_unit| selects the texture unit to be used when
-  // running the shader programs (i.e., specify 0 for GL_TEXTURE0).
+  // glBindTexture().
   // |src_texture_needs_y_flip| is true when the |src_texture| argument to any
   // of the methods below uses upside-down Y coordinates.
   // |shader_program_cache| is not owned by this instance.
   CompositingIOSurfaceTransformer(
-      GLenum texture_target, int texture_unit, bool src_texture_needs_y_flip,
+      GLenum texture_target, bool src_texture_needs_y_flip,
       CompositingIOSurfaceShaderPrograms* shader_program_cache);
 
   ~CompositingIOSurfaceTransformer();
 
+  // Delete any references to currently-cached OpenGL objects.  This must be
+  // called within the OpenGL context just before destruction.
+  void ReleaseCachedGLObjects();
+
   // Resize using bilinear interpolation.  Returns false on error.  Otherwise,
-  // the |texture| argument will point to the result and the caller is
-  // responsible for calling glDeleteTexture(*texture).
+  // the |texture| argument will point to the result.  Ownership of the returned
+  // |texture| remains with CompositingIOSurfaceTransformer (i.e., the caller
+  // must not delete this texture).  The |texture| remains valid until the next
+  // call to ResizeBilinear() or ReleaseCachedGLObjects().
   //
   // If the src and dst sizes are identical, this becomes a simple copy into a
   // new texture.
@@ -52,15 +57,20 @@
   //
   // YV12 is effectively a twelve bit per pixel format consisting of a full-
   // size y (luminance) plane and half-width, half-height u and v (blue and
-  // red chrominance) planes.  This method will allocate three off-screen
-  // textures, one for each plane, and return them via the output arguments
-  // |texture_y|, |texture_u|, and |texture_v|.  While the textures are in
-  // GL_RGBA format, they should be interpreted as the appropriate single-byte,
-  // planar format after reading the pixel data.  The output arguments
-  // |packed_y_size| and |packed_uv_size| follow from these special semantics:
-  // They represent the size of their corresponding texture, if it was to be
-  // treated like RGBA pixel data.  That means their widths are in terms of
-  // "quads," where one quad contains 4 Y (or U or V) pixels.
+  // red chrominance) planes.  This method will return three off-screen
+  // textures, one for each plane, via the output arguments |texture_y|,
+  // |texture_u|, and |texture_v|.  While the textures are in GL_RGBA format,
+  // they should be interpreted as the appropriate single-byte, planar format
+  // after reading the pixel data.  The output arguments |packed_y_size| and
+  // |packed_uv_size| follow from these special semantics: They represent the
+  // size of their corresponding texture, if it was to be treated like RGBA
+  // pixel data.  That means their widths are in terms of "quads," where one
+  // quad contains 4 Y (or U or V) pixels.
+  //
+  // Ownership of the returned textures remains with
+  // CompositingIOSurfaceTransformer (i.e., the caller must not delete the
+  // textures).  The textures remain valid until the next call to
+  // TransformRGBToYV12() or ReleaseCachedGLObjects().
   //
   // If |src_subrect|'s size does not match |dst_size|, the source will be
   // bilinearly interpolated during conversion.
@@ -74,14 +84,34 @@
       gfx::Size* packed_y_size, gfx::Size* packed_uv_size);
 
  private:
+  enum CachedTexture {
+    RGBA_OUTPUT = 0,
+    Y_PLANE_OUTPUT,
+    UUVV_INTERMEDIATE,
+    U_PLANE_OUTPUT,
+    V_PLANE_OUTPUT,
+    NUM_CACHED_TEXTURES
+  };
+
+  // If necessary, generate the texture and/or resize it to the given |size|.
+  void PrepareTexture(CachedTexture which, const gfx::Size& size);
+
+  // If necessary, generate a framebuffer object to be used as an intermediate
+  // destination for drawing.
+  void PrepareFramebuffer();
+
   // Target to bind all input and output textures to (which defines the type of
   // textures being created and read).  Generally, this is
   // GL_TEXTURE_RECTANGLE_ARB.
   const GLenum texture_target_;
-  const int texture_unit_;
   const bool src_texture_needs_y_flip_;
   CompositingIOSurfaceShaderPrograms* const shader_program_cache_;
 
+  // Cached OpenGL objects.
+  GLuint textures_[NUM_CACHED_TEXTURES];
+  gfx::Size texture_sizes_[NUM_CACHED_TEXTURES];
+  GLuint frame_buffer_;
+
   // Auto-detected and set once in the constructor.
   bool system_supports_multiple_draw_buffers_;
 
diff --git a/content/browser/renderer_host/compositing_iosurface_transformer_mac_unittest.cc b/content/browser/renderer_host/compositing_iosurface_transformer_mac_unittest.cc
index 110d79a..6f2562c 100644
--- a/content/browser/renderer_host/compositing_iosurface_transformer_mac_unittest.cc
+++ b/content/browser/renderer_host/compositing_iosurface_transformer_mac_unittest.cc
@@ -276,10 +276,11 @@
     CGLSetCurrentContext(context_);
     shader_program_cache_.reset(new CompositingIOSurfaceShaderPrograms());
     transformer_.reset(new CompositingIOSurfaceTransformer(
-        kGLTextureTarget, 0, false, shader_program_cache_.get()));
+        kGLTextureTarget, false, shader_program_cache_.get()));
   }
 
   virtual ~CompositingIOSurfaceTransformerTest() {
+    transformer_->ReleaseCachedGLObjects();
     shader_program_cache_->Reset();
     CGLSetCurrentContext(NULL);
     CGLDestroyContext(context_);
@@ -289,25 +290,21 @@
   void RunResizeTest(const SkBitmap& src_bitmap, const gfx::Rect& src_rect,
                      const gfx::Size& dst_size) {
     SCOPED_TRACE(::testing::Message()
-                 << "src_rect=" << src_rect.x() << ',' << src_rect.y()
+                 << "src_rect=(" << src_rect.x() << ',' << src_rect.y()
                  << ")x[" << src_rect.width() << 'x' << src_rect.height()
                  << "]; dst_size=[" << dst_size.width() << 'x'
                  << dst_size.height() << ']');
 
-    const GLuint original_texture = CreateTextureWithImage(src_bitmap);
-    EXPECT_NE(0u, original_texture);
-
     // Do the scale operation on the GPU.
+    const GLuint original_texture = CreateTextureWithImage(src_bitmap);
+    ASSERT_NE(0u, original_texture);
     GLuint scaled_texture = 0u;
-    EXPECT_TRUE(transformer_->ResizeBilinear(
+    ASSERT_TRUE(transformer_->ResizeBilinear(
         original_texture, src_rect, dst_size, &scaled_texture));
     EXPECT_NE(0u, scaled_texture);
     CGLFlushDrawable(context_);  // Account for some buggy driver impls.
     const SkBitmap result_bitmap = ReadBackTexture(scaled_texture, dst_size);
-
-    // Delete the textures.
     EXPECT_NO_GL_ERROR(glDeleteTextures(1, &original_texture));
-    EXPECT_NO_GL_ERROR(glDeleteTextures(1, &scaled_texture));
 
     // Compare the image read back to the version produced by a known-working
     // software implementation.  Allow up to 2 lines of mismatch due to how
@@ -322,21 +319,20 @@
       const SkBitmap& src_bitmap, const gfx::Rect& src_rect,
       const gfx::Size& dst_size) {
     SCOPED_TRACE(::testing::Message()
-                 << "src_rect=" << src_rect.x() << ',' << src_rect.y()
+                 << "src_rect=(" << src_rect.x() << ',' << src_rect.y()
                  << ")x[" << src_rect.width() << 'x' << src_rect.height()
                  << "]; dst_size=[" << dst_size.width() << 'x'
                  << dst_size.height() << ']');
 
-    const GLuint original_texture = CreateTextureWithImage(src_bitmap);
-    EXPECT_NE(0u, original_texture);
-
     // Perform the RGB to YV12 conversion.
+    const GLuint original_texture = CreateTextureWithImage(src_bitmap);
+    ASSERT_NE(0u, original_texture);
     GLuint texture_y = 0u;
     GLuint texture_u = 0u;
     GLuint texture_v = 0u;
     gfx::Size packed_y_size;
     gfx::Size packed_uv_size;
-    EXPECT_TRUE(transformer_->TransformRGBToYV12(
+    ASSERT_TRUE(transformer_->TransformRGBToYV12(
         original_texture, src_rect, dst_size,
         &texture_y, &texture_u, &texture_v, &packed_y_size, &packed_uv_size));
     EXPECT_NE(0u, texture_y);
@@ -344,6 +340,7 @@
     EXPECT_NE(0u, texture_v);
     EXPECT_FALSE(packed_y_size.IsEmpty());
     EXPECT_FALSE(packed_uv_size.IsEmpty());
+    EXPECT_NO_GL_ERROR(glDeleteTextures(1, &original_texture));
 
     // Read-back the texture for each plane.
     CGLFlushDrawable(context_);  // Account for some buggy driver impls.
@@ -351,12 +348,6 @@
     const SkBitmap result_u_bitmap = ReadBackTexture(texture_u, packed_uv_size);
     const SkBitmap result_v_bitmap = ReadBackTexture(texture_v, packed_uv_size);
 
-    // Delete the textures.
-    EXPECT_NO_GL_ERROR(glDeleteTextures(1, &original_texture));
-    EXPECT_NO_GL_ERROR(glDeleteTextures(1, &texture_y));
-    EXPECT_NO_GL_ERROR(glDeleteTextures(1, &texture_u));
-    EXPECT_NO_GL_ERROR(glDeleteTextures(1, &texture_v));
-
     // Compare the Y, U, and V planes read-back to the version produced by a
     // known-working software implementation.  Allow up to 2 lines of mismatch
     // due to how implementations disagree on resolving the processing of edges.
@@ -409,16 +400,12 @@
   DISALLOW_COPY_AND_ASSIGN(CompositingIOSurfaceTransformerTest);
 };
 
-// TODO(miu): Enable ALL the tests after the initial change lands.  These were
-// started out DISABLED since unit tests executing on GPUs have been known to
-// sometimes cause messy flakiness problems.
-TEST_F(CompositingIOSurfaceTransformerTest,
-       DISABLED_ShaderProgramsCompileAndLink) {
+TEST_F(CompositingIOSurfaceTransformerTest, ShaderProgramsCompileAndLink) {
   // Attempt to use each program, binding its required uniform variables.
-  EXPECT_NO_GL_ERROR(shader_program_cache()->UseBlitProgram(0));
+  EXPECT_NO_GL_ERROR(shader_program_cache()->UseBlitProgram());
   EXPECT_NO_GL_ERROR(shader_program_cache()->UseSolidWhiteProgram());
-  EXPECT_NO_GL_ERROR(shader_program_cache()->UseRGBToYV12Program(1, 0, 1.0f));
-  EXPECT_NO_GL_ERROR(shader_program_cache()->UseRGBToYV12Program(2, 0, 1.0f));
+  EXPECT_NO_GL_ERROR(shader_program_cache()->UseRGBToYV12Program(1, 1.0f));
+  EXPECT_NO_GL_ERROR(shader_program_cache()->UseRGBToYV12Program(2, 1.0f));
 
   EXPECT_NO_GL_ERROR(glUseProgram(0));
 }
@@ -467,7 +454,7 @@
 
 }  // namespace
 
-TEST_F(CompositingIOSurfaceTransformerTest, DISABLED_ResizesTexturesCorrectly) {
+TEST_F(CompositingIOSurfaceTransformerTest, ResizesTexturesCorrectly) {
   for (size_t i = 0; i < arraysize(kTestParameters); ++i) {
     SCOPED_TRACE(::testing::Message() << "kTestParameters[" << i << ']');
 
@@ -497,7 +484,7 @@
   }
 }
 
-TEST_F(CompositingIOSurfaceTransformerTest, DISABLED_TransformsRGBToYV12) {
+TEST_F(CompositingIOSurfaceTransformerTest, TransformsRGBToYV12) {
   for (size_t i = 0; i < arraysize(kTestParameters); ++i) {
     SCOPED_TRACE(::testing::Message() << "kTestParameters[" << i << ']');
 
diff --git a/content/browser/renderer_host/compositor_impl_android.cc b/content/browser/renderer_host/compositor_impl_android.cc
index f81a876..6d4aba1 100644
--- a/content/browser/renderer_host/compositor_impl_android.cc
+++ b/content/browser/renderer_host/compositor_impl_android.cc
@@ -49,8 +49,8 @@
       : cc::OutputSurface(context3d.Pass()) {}
 
   virtual void Reshape(gfx::Size size) OVERRIDE {}
-  virtual void PostSubBuffer(gfx::Rect rect) OVERRIDE {}
-  virtual void SwapBuffers() OVERRIDE {}
+  virtual void PostSubBuffer(gfx::Rect rect, const cc::LatencyInfo&) OVERRIDE {}
+  virtual void SwapBuffers(const cc::LatencyInfo&) OVERRIDE {}
 };
 
 static bool g_initialized = false;
@@ -82,7 +82,8 @@
 void Compositor::InitializeWithFlags(uint32 flags) {
   g_use_direct_gl = flags & DIRECT_CONTEXT_ON_DRAW_THREAD;
   if (flags & ENABLE_COMPOSITOR_THREAD) {
-    TRACE_EVENT_INSTANT0("test_gpu", "ThreadedCompositingInitialization");
+    TRACE_EVENT_INSTANT0("test_gpu", "ThreadedCompositingInitialization",
+                         TRACE_EVENT_SCOPE_THREAD);
     g_impl_thread = new webkit_glue::WebThreadImpl("Browser Compositor");
   }
   Compositor::Initialize();
@@ -120,15 +121,22 @@
       window_(NULL),
       surface_id_(0),
       client_(client),
-      weak_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
+      weak_factory_(this) {
   DCHECK(client);
 }
 
 CompositorImpl::~CompositorImpl() {
+  // Clean-up any surface references.
+  SetSurface(NULL);
+}
+
+void CompositorImpl::SetNeedsRedraw() {
+  if (host_)
+    host_->SetNeedsRedraw();
 }
 
 void CompositorImpl::Composite() {
-  if (host_.get())
+  if (host_)
     host_->Composite(base::TimeTicks::Now());
 }
 
@@ -162,33 +170,41 @@
 void CompositorImpl::SetSurface(jobject surface) {
   JNIEnv* env = base::android::AttachCurrentThread();
   base::android::ScopedJavaLocalRef<jobject> j_surface(env, surface);
-  if (surface) {
-    ANativeWindow* window = ANativeWindow_fromSurface(env, surface);
+
+  // First, cleanup any existing surface references.
+  if (surface_id_) {
+    DCHECK(g_surface_map.Get().find(surface_id_) !=
+           g_surface_map.Get().end());
+    base::AutoLock lock(g_surface_map_lock.Get());
+    g_surface_map.Get().erase(surface_id_);
+  }
+  SetWindowSurface(NULL);
+
+  // Now, set the new surface if we have one.
+  ANativeWindow* window = NULL;
+  if (surface)
+    window = ANativeWindow_fromSurface(env, surface);
+  if (window) {
     SetWindowSurface(window);
     ANativeWindow_release(window);
     {
       base::AutoLock lock(g_surface_map_lock.Get());
       g_surface_map.Get().insert(std::make_pair(surface_id_, j_surface));
     }
-  } else {
-    {
-      base::AutoLock lock(g_surface_map_lock.Get());
-      g_surface_map.Get().erase(surface_id_);
-    }
-    SetWindowSurface(NULL);
   }
 }
 
 void CompositorImpl::SetVisible(bool visible) {
   if (!visible) {
     host_.reset();
-  } else if (!host_.get()) {
+  } else if (!host_) {
     cc::LayerTreeSettings settings;
     settings.refresh_rate = 60.0;
     settings.impl_side_painting = false;
     settings.calculate_top_controls_position = false;
     settings.top_controls_height = 0.f;
     settings.use_memory_management = false;
+    settings.highp_threshold_min = 2048;
 
     // Do not clear the framebuffer when rendering into external GL contexts
     // like Android View System's.
@@ -205,7 +221,7 @@
 
     host_->SetVisible(true);
     host_->SetSurfaceReady();
-    host_->SetViewportSize(size_, size_);
+    host_->SetViewportSize(size_);
     host_->set_has_transparent_background(has_transparent_background_);
   }
 }
@@ -221,18 +237,18 @@
 
   size_ = size;
   if (host_)
-    host_->SetViewportSize(size, size);
+    host_->SetViewportSize(size);
   root_layer_->SetBounds(size);
 }
 
 void CompositorImpl::SetHasTransparentBackground(bool flag) {
   has_transparent_background_ = flag;
-  if (host_.get())
+  if (host_)
     host_->set_has_transparent_background(flag);
 }
 
 bool CompositorImpl::CompositeAndReadback(void *pixels, const gfx::Rect& rect) {
-  if (host_.get())
+  if (host_)
     return host_->CompositeAndReadback(pixels, rect);
   else
     return false;
@@ -354,8 +370,8 @@
   }
 }
 
-scoped_ptr<cc::InputHandler> CompositorImpl::CreateInputHandler() {
-  return scoped_ptr<cc::InputHandler>();
+scoped_ptr<cc::InputHandlerClient> CompositorImpl::CreateInputHandlerClient() {
+  return scoped_ptr<cc::InputHandlerClient>();
 }
 
 void CompositorImpl::DidCompleteSwapBuffers() {
@@ -386,6 +402,7 @@
 
 void CompositorImpl::OnViewContextSwapBuffersPosted() {
   TRACE_EVENT0("compositor", "CompositorImpl::OnViewContextSwapBuffersPosted");
+  client_->OnSwapBuffersPosted();
 }
 
 void CompositorImpl::OnViewContextSwapBuffersComplete() {
diff --git a/content/browser/renderer_host/compositor_impl_android.h b/content/browser/renderer_host/compositor_impl_android.h
index d984547..fc5361a 100644
--- a/content/browser/renderer_host/compositor_impl_android.h
+++ b/content/browser/renderer_host/compositor_impl_android.h
@@ -17,7 +17,7 @@
 struct ANativeWindow;
 
 namespace cc {
-class InputHandler;
+class InputHandlerClient;
 class Layer;
 class LayerTreeHost;
 }
@@ -55,6 +55,7 @@
   virtual void SetHasTransparentBackground(bool flag) OVERRIDE;
   virtual bool CompositeAndReadback(
       void *pixels, const gfx::Rect& rect) OVERRIDE;
+  virtual void SetNeedsRedraw() OVERRIDE;
   virtual void Composite() OVERRIDE;
   virtual WebKit::WebGLId GenerateTexture(gfx::JavaBitmap& bitmap) OVERRIDE;
   virtual WebKit::WebGLId GenerateCompressedTexture(
@@ -74,7 +75,8 @@
   virtual void ApplyScrollAndScale(gfx::Vector2d scroll_delta,
                                    float page_scale) OVERRIDE {}
   virtual scoped_ptr<cc::OutputSurface> CreateOutputSurface() OVERRIDE;
-  virtual scoped_ptr<cc::InputHandler> CreateInputHandler() OVERRIDE;
+  virtual scoped_ptr<cc::InputHandlerClient> CreateInputHandlerClient()
+      OVERRIDE;
   virtual void DidRecreateOutputSurface(bool success) OVERRIDE {}
   virtual void WillCommit() OVERRIDE {}
   virtual void DidCommit() OVERRIDE {}
diff --git a/content/browser/renderer_host/database_message_filter.cc b/content/browser/renderer_host/database_message_filter.cc
index f364ce2..da667ea 100644
--- a/content/browser/renderer_host/database_message_filter.cc
+++ b/content/browser/renderer_host/database_message_filter.cc
@@ -15,7 +15,6 @@
 #include "content/public/browser/user_metrics.h"
 #include "content/public/common/result_codes.h"
 #include "googleurl/src/gurl.h"
-#include "third_party/WebKit/Source/WebKit/chromium/public/WebSecurityOrigin.h"
 #include "third_party/sqlite/sqlite3.h"
 #include "webkit/database/database_util.h"
 #include "webkit/database/vfs_backend.h"
@@ -28,7 +27,6 @@
 using quota::QuotaManager;
 using quota::QuotaManagerProxy;
 using quota::QuotaStatusCode;
-using WebKit::WebSecurityOrigin;
 using webkit_database::DatabaseTracker;
 using webkit_database::DatabaseUtil;
 using webkit_database::VfsBackend;
diff --git a/content/browser/renderer_host/gtk_im_context_wrapper.cc b/content/browser/renderer_host/gtk_im_context_wrapper.cc
index fb5669a..e3fa26f 100644
--- a/content/browser/renderer_host/gtk_im_context_wrapper.cc
+++ b/content/browser/renderer_host/gtk_im_context_wrapper.cc
@@ -484,10 +484,8 @@
 }
 
 void GtkIMContextWrapper::HandleCommit(const string16& text) {
-  if (suppress_next_commit_) {
-    suppress_next_commit_ = false;
+  if (suppress_next_commit_)
     return;
-  }
 
   // Append the text to the buffer, because commit signal might be fired
   // multiple times when processing a key event.
diff --git a/content/browser/renderer_host/gtk_key_bindings_handler.cc b/content/browser/renderer_host/gtk_key_bindings_handler.cc
index 756bcc3..e86ea60 100644
--- a/content/browser/renderer_host/gtk_key_bindings_handler.cc
+++ b/content/browser/renderer_host/gtk_key_bindings_handler.cc
@@ -132,15 +132,16 @@
 }
 
 void GtkKeyBindingsHandler::BackSpace(GtkTextView* text_view) {
-  GetHandlerOwner(text_view)->EditCommandMatched("DeleteBackward", "");
+  GetHandlerOwner(text_view)
+      ->EditCommandMatched("DeleteBackward", std::string());
 }
 
 void GtkKeyBindingsHandler::CopyClipboard(GtkTextView* text_view) {
-  GetHandlerOwner(text_view)->EditCommandMatched("Copy", "");
+  GetHandlerOwner(text_view)->EditCommandMatched("Copy", std::string());
 }
 
 void GtkKeyBindingsHandler::CutClipboard(GtkTextView* text_view) {
-  GetHandlerOwner(text_view)->EditCommandMatched("Cut", "");
+  GetHandlerOwner(text_view)->EditCommandMatched("Cut", std::string());
 }
 
 void GtkKeyBindingsHandler::DeleteFromCursor(
@@ -191,7 +192,7 @@
     count = -count;
   for (; count > 0; --count) {
     for (const char* const* p = commands; *p; ++p)
-      owner->EditCommandMatched(*p, "");
+      owner->EditCommandMatched(*p, std::string());
   }
 }
 
@@ -247,7 +248,7 @@
   if (count < 0)
     count = -count;
   for (; count > 0; --count)
-    owner->EditCommandMatched(command, "");
+    owner->EditCommandMatched(command, std::string());
 }
 
 void GtkKeyBindingsHandler::MoveViewport(
@@ -256,18 +257,18 @@
 }
 
 void GtkKeyBindingsHandler::PasteClipboard(GtkTextView* text_view) {
-  GetHandlerOwner(text_view)->EditCommandMatched("Paste", "");
+  GetHandlerOwner(text_view)->EditCommandMatched("Paste", std::string());
 }
 
 void GtkKeyBindingsHandler::SelectAll(GtkTextView* text_view, gboolean select) {
   if (select)
-    GetHandlerOwner(text_view)->EditCommandMatched("SelectAll", "");
+    GetHandlerOwner(text_view)->EditCommandMatched("SelectAll", std::string());
   else
-    GetHandlerOwner(text_view)->EditCommandMatched("Unselect", "");
+    GetHandlerOwner(text_view)->EditCommandMatched("Unselect", std::string());
 }
 
 void GtkKeyBindingsHandler::SetAnchor(GtkTextView* text_view) {
-  GetHandlerOwner(text_view)->EditCommandMatched("SetMark", "");
+  GetHandlerOwner(text_view)->EditCommandMatched("SetMark", std::string());
 }
 
 void GtkKeyBindingsHandler::ToggleCursorVisible(GtkTextView* text_view) {
diff --git a/content/browser/renderer_host/image_transport_factory.cc b/content/browser/renderer_host/image_transport_factory.cc
index be01420..1e566ac 100644
--- a/content/browser/renderer_host/image_transport_factory.cc
+++ b/content/browser/renderer_host/image_transport_factory.cc
@@ -231,7 +231,8 @@
     // Recreating contexts directly from here causes issues, so post a task
     // instead.
     // TODO(piman): Fix the underlying issues.
-    MessageLoop::current()->PostTask(FROM_HERE,
+    base::MessageLoop::current()->PostTask(
+        FROM_HERE,
         base::Bind(&CompositorSwapClient::OnLostContext, this->AsWeakPtr()));
   }
 
@@ -261,7 +262,7 @@
           arraysize(messages_to_filter),
           base::Bind(&BrowserCompositorOutputSurfaceProxy::OnMessageReceived,
                      this),
-          MessageLoop::current()->message_loop_proxy());
+          base::MessageLoop::current()->message_loop_proxy());
       message_handler_set_ = true;
     }
     surface_map_.AddWithID(surface, surface_id);
@@ -372,7 +373,7 @@
       public ImageTransportFactory {
  public:
   GpuProcessTransportFactory()
-      : ALLOW_THIS_IN_INITIALIZER_LIST(callback_factory_(this)) {
+      : callback_factory_(this) {
     output_surface_proxy_ = new BrowserCompositorOutputSurfaceProxy();
   }
 
@@ -462,17 +463,11 @@
   }
 
   virtual GLHelper* GetGLHelper() OVERRIDE {
-    if (!gl_helper_.get()) {
+    if (!gl_helper_) {
       CreateSharedContextLazy();
-      WebKit::WebGraphicsContext3D* context_for_main_thread =
+      WebGraphicsContext3DCommandBufferImpl* context_for_main_thread =
           shared_contexts_main_thread_->Context3d();
-      WebKit::WebGraphicsContext3D* context_for_thread =
-          CreateOffscreenContext();
-      if (!context_for_thread)
-        return NULL;
-
-      gl_helper_.reset(new GLHelper(context_for_main_thread,
-                                    context_for_thread));
+      gl_helper_.reset(new GLHelper(context_for_main_thread));
     }
     return gl_helper_.get();
   }
@@ -601,7 +596,7 @@
     }
 
     virtual void OnLostContext() OVERRIDE {
-      MessageLoop::current()->PostTask(
+      base::MessageLoop::current()->PostTask(
           FROM_HERE,
           base::Bind(&GpuProcessTransportFactory::OnLostMainThreadSharedContext,
                      factory_->callback_factory_.GetWeakPtr()));
diff --git a/content/browser/renderer_host/image_transport_factory_android.cc b/content/browser/renderer_host/image_transport_factory_android.cc
index 9648970..bfb6dbb 100644
--- a/content/browser/renderer_host/image_transport_factory_android.cc
+++ b/content/browser/renderer_host/image_transport_factory_android.cc
@@ -160,8 +160,8 @@
 }
 
 GLHelper* CmdBufferImageTransportFactory::GetGLHelper() {
-  if (!gl_helper_.get())
-    gl_helper_.reset(new GLHelper(GetContext3D(), NULL));
+  if (!gl_helper_)
+    gl_helper_.reset(new GLHelper(context_.get()));
 
   return gl_helper_.get();
 }
diff --git a/content/browser/renderer_host/ime_adapter_android.cc b/content/browser/renderer_host/ime_adapter_android.cc
index 3eab2b0..6de2598 100644
--- a/content/browser/renderer_host/ime_adapter_android.cc
+++ b/content/browser/renderer_host/ime_adapter_android.cc
@@ -13,6 +13,7 @@
 #include "base/utf_string_conversions.h"
 #include "content/browser/renderer_host/render_widget_host_impl.h"
 #include "content/browser/renderer_host/render_widget_host_view_android.h"
+#include "content/common/input_messages.h"
 #include "content/common/view_messages.h"
 #include "content/public/browser/native_web_keyboard_event.h"
 #include "jni/ImeAdapter_jni.h"
@@ -227,7 +228,7 @@
   if (!rwhi)
     return;
 
-  rwhi->Send(new ViewMsg_Unselect(rwhi->GetRoutingID()));
+  rwhi->Send(new InputMsg_Unselect(rwhi->GetRoutingID()));
 }
 
 void ImeAdapterAndroid::SelectAll(JNIEnv* env, jobject) {
@@ -236,7 +237,7 @@
   if (!rwhi)
     return;
 
-  rwhi->Send(new ViewMsg_SelectAll(rwhi->GetRoutingID()));
+  rwhi->Send(new InputMsg_SelectAll(rwhi->GetRoutingID()));
 }
 
 void ImeAdapterAndroid::Cut(JNIEnv* env, jobject) {
@@ -245,7 +246,7 @@
   if (!rwhi)
     return;
 
-  rwhi->Send(new ViewMsg_Cut(rwhi->GetRoutingID()));
+  rwhi->Send(new InputMsg_Cut(rwhi->GetRoutingID()));
 }
 
 void ImeAdapterAndroid::Copy(JNIEnv* env, jobject) {
@@ -254,7 +255,7 @@
   if (!rwhi)
     return;
 
-  rwhi->Send(new ViewMsg_Copy(rwhi->GetRoutingID()));
+  rwhi->Send(new InputMsg_Copy(rwhi->GetRoutingID()));
 }
 
 void ImeAdapterAndroid::Paste(JNIEnv* env, jobject) {
@@ -263,7 +264,11 @@
   if (!rwhi)
     return;
 
-  rwhi->Send(new ViewMsg_Paste(rwhi->GetRoutingID()));
+  rwhi->Send(new InputMsg_Paste(rwhi->GetRoutingID()));
+}
+
+void ImeAdapterAndroid::ResetImeAdapter(JNIEnv* env, jobject) {
+  java_ime_adapter_.reset();
 }
 
 }  // namespace content
diff --git a/content/browser/renderer_host/ime_adapter_android.h b/content/browser/renderer_host/ime_adapter_android.h
index f990498..1c1669e 100644
--- a/content/browser/renderer_host/ime_adapter_android.h
+++ b/content/browser/renderer_host/ime_adapter_android.h
@@ -51,6 +51,7 @@
   void Cut(JNIEnv*, jobject);
   void Copy(JNIEnv*, jobject);
   void Paste(JNIEnv*, jobject);
+  void ResetImeAdapter(JNIEnv*, jobject);
 
   // Called from native -> java
   void CancelComposition();
diff --git a/content/browser/renderer_host/java/java_bound_object.cc b/content/browser/renderer_host/java/java_bound_object.cc
index 4a239a5..008cee1 100644
--- a/content/browser/renderer_host/java/java_bound_object.cc
+++ b/content/browser/renderer_host/java/java_bound_object.cc
@@ -223,35 +223,79 @@
   return !base::android::ClearException(env);
 }
 
+double RoundDoubleTowardsZero(const double& x) {
+  if (std::isnan(x)) {
+    return 0.0;
+  }
+  return x > 0.0 ? floor(x) : ceil(x);
+}
+
+// Rounds to jlong using Java's type conversion rules.
+jlong RoundDoubleToLong(const double& x) {
+  double intermediate = RoundDoubleTowardsZero(x);
+  // The int64 limits can not be converted exactly to double values, so we
+  // compare to custom constants. kint64max is 2^63 - 1, but the spacing
+  // between double values in the the range 2^62 to 2^63 is 2^10. The cast is
+  // required to silence a spurious gcc warning for integer overflow.
+  const int64 limit = (GG_INT64_C(1) << 63) - static_cast<uint64>(1 << 10);
+  DCHECK(limit > 0);
+  const double kLargestDoubleLessThanInt64Max = limit;
+  const double kSmallestDoubleGreaterThanInt64Min = -limit;
+  if (intermediate > kLargestDoubleLessThanInt64Max) {
+    return kint64max;
+  }
+  if (intermediate < kSmallestDoubleGreaterThanInt64Min) {
+    return kint64min;
+  }
+  return static_cast<jlong>(intermediate);
+}
+
+// Rounds to jint using Java's type conversion rules.
+jint RoundDoubleToInt(const double& x) {
+  double intermediate = RoundDoubleTowardsZero(x);
+  // The int32 limits cast exactly to double values.
+  intermediate = std::min(intermediate, static_cast<double>(kint32max));
+  intermediate = std::max(intermediate, static_cast<double>(kint32min));
+  return static_cast<jint>(intermediate);
+}
+
 jvalue CoerceJavaScriptNumberToJavaValue(const NPVariant& variant,
                                          const JavaType& target_type,
                                          bool coerce_to_string) {
   // See http://jdk6.java.net/plugin2/liveconnect/#JS_NUMBER_VALUES.
+
+  // For conversion to numeric types, we need to replicate Java's type
+  // conversion rules. This requires that for integer values, we simply discard
+  // all but the lowest n buts, where n is the number of bits in the target
+  // type. For double values, the logic is more involved.
   jvalue result;
   DCHECK(variant.type == NPVariantType_Int32 ||
          variant.type == NPVariantType_Double);
   bool is_double = variant.type == NPVariantType_Double;
   switch (target_type.type) {
     case JavaType::TypeByte:
-      result.b = is_double ? static_cast<jbyte>(NPVARIANT_TO_DOUBLE(variant)) :
-                             static_cast<jbyte>(NPVARIANT_TO_INT32(variant));
+      result.b = is_double ?
+          static_cast<jbyte>(RoundDoubleToInt(NPVARIANT_TO_DOUBLE(variant))) :
+          static_cast<jbyte>(NPVARIANT_TO_INT32(variant));
       break;
     case JavaType::TypeChar:
       // LIVECONNECT_COMPLIANCE: Existing behavior is to convert double to 0.
-      // Spec requires converting doubles the same as int32.
+      // Spec requires converting doubles similarly to how we convert doubles to
+      // other numeric types.
       result.c = is_double ? 0 :
                              static_cast<jchar>(NPVARIANT_TO_INT32(variant));
       break;
     case JavaType::TypeShort:
-      result.s = is_double ? static_cast<jshort>(NPVARIANT_TO_DOUBLE(variant)) :
-                             static_cast<jshort>(NPVARIANT_TO_INT32(variant));
+      result.s = is_double ?
+          static_cast<jshort>(RoundDoubleToInt(NPVARIANT_TO_DOUBLE(variant))) :
+          static_cast<jshort>(NPVARIANT_TO_INT32(variant));
       break;
     case JavaType::TypeInt:
-      result.i = is_double ? static_cast<jint>(NPVARIANT_TO_DOUBLE(variant)) :
+      result.i = is_double ? RoundDoubleToInt(NPVARIANT_TO_DOUBLE(variant)) :
                              NPVARIANT_TO_INT32(variant);
       break;
     case JavaType::TypeLong:
-      result.j = is_double ? static_cast<jlong>(NPVARIANT_TO_DOUBLE(variant)) :
+      result.j = is_double ? RoundDoubleToLong(NPVARIANT_TO_DOUBLE(variant)) :
                              NPVARIANT_TO_INT32(variant);
       break;
     case JavaType::TypeFloat:
diff --git a/content/browser/renderer_host/java/java_bridge_dispatcher_host.cc b/content/browser/renderer_host/java/java_bridge_dispatcher_host.cc
index 9285007..e3d2cd2 100644
--- a/content/browser/renderer_host/java/java_bridge_dispatcher_host.cc
+++ b/content/browser/renderer_host/java/java_bridge_dispatcher_host.cc
@@ -138,7 +138,8 @@
 
 void JavaBridgeDispatcherHost::CreateObjectStub(NPObject* object,
                                                 int route_id) {
-  DCHECK_EQ(g_background_thread.Get().message_loop(), MessageLoop::current());
+  DCHECK_EQ(g_background_thread.Get().message_loop(),
+            base::MessageLoop::current());
   if (!channel_) {
     channel_ = JavaBridgeChannelHost::GetJavaBridgeChannelHost(
         render_view_host()->GetProcess()->GetID(),
diff --git a/content/browser/renderer_host/java/java_type.cc b/content/browser/renderer_host/java/java_type.cc
index e68f6db..b590e77 100644
--- a/content/browser/renderer_host/java/java_type.cc
+++ b/content/browser/renderer_host/java/java_type.cc
@@ -68,7 +68,7 @@
 
 JavaType& JavaType::operator=(const JavaType& other) {
   type = other.type;
-  if (other.inner_type.get()) {
+  if (other.inner_type) {
     DCHECK_EQ(JavaType::TypeArray, type);
     inner_type.reset(new JavaType(*other.inner_type));
   } else {
diff --git a/content/browser/renderer_host/media/audio_input_device_manager_unittest.cc b/content/browser/renderer_host/media/audio_input_device_manager_unittest.cc
index c5294dc..decc71a 100644
--- a/content/browser/renderer_host/media/audio_input_device_manager_unittest.cc
+++ b/content/browser/renderer_host/media/audio_input_device_manager_unittest.cc
@@ -15,11 +15,6 @@
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-#if defined(OS_ANDROID)
-#include "base/android/jni_android.h"
-#include "media/audio/audio_manager_base.h"
-#endif
-
 using testing::_;
 using testing::InSequence;
 using testing::SaveArg;
@@ -57,15 +52,9 @@
  protected:
   virtual void SetUp() OVERRIDE {
     // The test must run on Browser::IO.
-    message_loop_.reset(new MessageLoop(MessageLoop::TYPE_IO));
+    message_loop_.reset(new base::MessageLoop(base::MessageLoop::TYPE_IO));
     io_thread_.reset(new BrowserThreadImpl(BrowserThread::IO,
                                            message_loop_.get()));
-
-#if defined(OS_ANDROID)
-    media::AudioManagerBase::RegisterAudioManager(
-        base::android::AttachCurrentThread());
-#endif
-
     audio_manager_.reset(media::AudioManager::Create());
     manager_ = new AudioInputDeviceManager(audio_manager_.get());
     audio_input_listener_.reset(new MockAudioInputDeviceManagerListener());
@@ -88,7 +77,7 @@
     io_thread_.reset();
   }
 
-  scoped_ptr<MessageLoop> message_loop_;
+  scoped_ptr<base::MessageLoop> message_loop_;
   scoped_ptr<BrowserThreadImpl> io_thread_;
   scoped_refptr<AudioInputDeviceManager> manager_;
   scoped_ptr<MockAudioInputDeviceManagerListener> audio_input_listener_;
@@ -140,7 +129,7 @@
   InSequence s;
 
   int index = 0;
-  scoped_array<int> session_id(new int[devices_.size()]);
+  scoped_ptr<int[]> session_id(new int[devices_.size()]);
 
   // Opens the devices in a loop.
   for (StreamDeviceInfoArray::const_iterator iter = devices_.begin();
@@ -245,7 +234,7 @@
   InSequence s;
 
   int index = 0;
-  scoped_array<int> session_id(new int[devices_.size()]);
+  scoped_ptr<int[]> session_id(new int[devices_.size()]);
 
   // Loops through the devices and calls Open()/Close()/GetOpenedDeviceInfoById
   // for each device.
diff --git a/content/browser/renderer_host/media/audio_input_renderer_host.cc b/content/browser/renderer_host/media/audio_input_renderer_host.cc
index 750661c..38a45f2 100644
--- a/content/browser/renderer_host/media/audio_input_renderer_host.cc
+++ b/content/browser/renderer_host/media/audio_input_renderer_host.cc
@@ -13,7 +13,6 @@
 #include "content/browser/renderer_host/media/media_stream_manager.h"
 #include "content/browser/renderer_host/media/web_contents_audio_input_stream.h"
 #include "content/browser/renderer_host/media/web_contents_capture_util.h"
-#include "content/common/media/audio_messages.h"
 #include "media/audio/audio_manager_base.h"
 
 namespace content {
@@ -159,7 +158,7 @@
 
   Send(new AudioInputMsg_NotifyStreamCreated(entry->stream_id,
       foreign_memory_handle, foreign_socket_handle,
-      entry->shared_memory.created_size(),
+      entry->shared_memory.requested_size(),
       entry->shared_memory_segment_count));
 }
 
@@ -186,8 +185,6 @@
   bool handled = true;
   IPC_BEGIN_MESSAGE_MAP_EX(AudioInputRendererHost, message, *message_was_ok)
     IPC_MESSAGE_HANDLER(AudioInputHostMsg_CreateStream, OnCreateStream)
-    IPC_MESSAGE_HANDLER(AudioInputHostMsg_AssociateStreamWithConsumer,
-                        OnAssociateStreamWithConsumer)
     IPC_MESSAGE_HANDLER(AudioInputHostMsg_RecordStream, OnRecordStream)
     IPC_MESSAGE_HANDLER(AudioInputHostMsg_CloseStream, OnCloseStream)
     IPC_MESSAGE_HANDLER(AudioInputHostMsg_SetVolume, OnSetVolume)
@@ -199,13 +196,17 @@
 
 void AudioInputRendererHost::OnCreateStream(
     int stream_id,
+    int render_view_id,
     int session_id,
-    const media::AudioParameters& params,
-    bool automatic_gain_control,
-    int shared_memory_count) {
-  VLOG(1) << "AudioInputRendererHost::OnCreateStream(stream_id="
-          << stream_id << ", session_id=" << session_id << ")";
+    const AudioInputHostMsg_CreateStream_Config& config) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+  DVLOG(1) << "AudioInputRendererHost@" << this
+           << "::OnCreateStream(stream_id=" << stream_id
+           << ", render_view_id=" << render_view_id
+           << ", session_id=" << session_id << ")";
+  DCHECK_GT(render_view_id, 0);
+
   // media::AudioParameters is validated in the deserializer.
   if (LookupById(stream_id) != NULL) {
     SendErrorMessage(stream_id);
@@ -227,23 +228,22 @@
     device_id = info->device.id;
   }
 
-  media::AudioParameters audio_params(params);
+  media::AudioParameters audio_params(config.params);
   if (media_stream_manager_->audio_input_device_manager()->
       ShouldUseFakeDevice()) {
-    audio_params.Reset(media::AudioParameters::AUDIO_FAKE,
-                       params.channel_layout(), params.channels(), 0,
-                       params.sample_rate(),
-                       params.bits_per_sample(), params.frames_per_buffer());
+    audio_params.Reset(
+        media::AudioParameters::AUDIO_FAKE,
+        config.params.channel_layout(), config.params.channels(), 0,
+        config.params.sample_rate(), config.params.bits_per_sample(),
+        config.params.frames_per_buffer());
   }
 
-  uint32 buffer_size = audio_params.GetBytesPerBuffer();
-
   // Create a new AudioEntry structure.
   scoped_ptr<AudioEntry> entry(new AudioEntry());
 
-  uint32 segment_size =
-      sizeof(media::AudioInputBufferParameters) + buffer_size;
-  entry->shared_memory_segment_count = shared_memory_count;
+  const uint32 segment_size = (sizeof(media::AudioInputBufferParameters) +
+                               audio_params.GetBytesPerBuffer());
+  entry->shared_memory_segment_count = config.shared_memory_count;
 
   // Create the shared memory and share it with the renderer process
   // using a new SyncWriter object.
@@ -292,24 +292,15 @@
 
   // Set the initial AGC state for the audio input stream. Note that, the AGC
   // is only supported in AUDIO_PCM_LOW_LATENCY mode.
-  if (params.format() == media::AudioParameters::AUDIO_PCM_LOW_LATENCY)
-    entry->controller->SetAutomaticGainControl(automatic_gain_control);
+  if (config.params.format() == media::AudioParameters::AUDIO_PCM_LOW_LATENCY)
+    entry->controller->SetAutomaticGainControl(config.automatic_gain_control);
 
-  // If we have created the controller successfully create a entry and add it
+  // Since the controller was created successfully, create an entry and add it
   // to the map.
   entry->stream_id = stream_id;
-
   audio_entries_.insert(std::make_pair(stream_id, entry.release()));
 }
 
-void AudioInputRendererHost::OnAssociateStreamWithConsumer(int stream_id,
-                                                           int render_view_id) {
-  // TODO(miu): Will use render_view_id in upcoming change.
-  DVLOG(1) << "AudioInputRendererHost@" << this
-           << "::OnAssociateStreamWithConsumer(stream_id=" << stream_id
-           << ", render_view_id=" << render_view_id << ")";
-}
-
 void AudioInputRendererHost::OnRecordStream(int stream_id) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
 
@@ -404,7 +395,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 (controller == i->second->controller)
       return i->second;
   }
   return NULL;
diff --git a/content/browser/renderer_host/media/audio_input_renderer_host.h b/content/browser/renderer_host/media/audio_input_renderer_host.h
index e3b0453..077a1cc 100644
--- a/content/browser/renderer_host/media/audio_input_renderer_host.h
+++ b/content/browser/renderer_host/media/audio_input_renderer_host.h
@@ -34,6 +34,7 @@
 #include "base/process.h"
 #include "base/sequenced_task_runner_helpers.h"
 #include "base/shared_memory.h"
+#include "content/common/media/audio_messages.h"
 #include "content/public/browser/browser_message_filter.h"
 #include "content/public/browser/browser_thread.h"
 #include "media/audio/audio_input_controller.h"
@@ -84,20 +85,17 @@
   // Methods called on IO thread ----------------------------------------------
 
   // Audio related IPC message handlers.
-  // Creates an audio input stream with the specified session id and format.
-  // |session_id| is used to find out which device to be used for the stream,
-  // when it is AudioInputDeviceManager::kFakeOpenSessionId, it uses the
-  // the default device. If this call is successful this object would keep an
-  // internal entry of the stream for the required properties.
-  void OnCreateStream(int stream_id,
-                      int session_id,
-                      const media::AudioParameters& params,
-                      bool automatic_gain_control,
-                      int shared_memory_count);
 
-  // Track that the data for the audio stream referenced by |stream_id| is
+  // Creates an audio input stream with the specified format whose data is
   // consumed by an entity in the render view referenced by |render_view_id|.
-  void OnAssociateStreamWithConsumer(int stream_id, int render_view_id);
+  // |session_id| is used to find out which device to be used for the stream.
+  // When it is AudioInputDeviceManager::kFakeOpenSessionId, it uses the the
+  // default device.  Upon success/failure, the peer is notified via the
+  // NotifyStreamCreated message.
+  void OnCreateStream(int stream_id,
+                      int render_view_id,
+                      int session_id,
+                      const AudioInputHostMsg_CreateStream_Config& config);
 
   // Record the audio input stream referenced by |stream_id|.
   void OnRecordStream(int stream_id);
@@ -109,7 +107,8 @@
   void OnSetVolume(int stream_id, double volume);
 
   // Complete the process of creating an audio input stream. This will set up
-  // the shared memory or shared socket in low latency mode.
+  // the shared memory or shared socket in low latency mode and send the
+  // NotifyStreamCreated message to the peer.
   void DoCompleteCreation(media::AudioInputController* controller);
 
   // Send a state change message to the renderer.
diff --git a/content/browser/renderer_host/media/audio_input_sync_writer.cc b/content/browser/renderer_host/media/audio_input_sync_writer.cc
index 2af937d..18a85ab 100644
--- a/content/browser/renderer_host/media/audio_input_sync_writer.cc
+++ b/content/browser/renderer_host/media/audio_input_sync_writer.cc
@@ -18,9 +18,9 @@
       shared_memory_segment_count_(shared_memory_segment_count),
       current_segment_id_(0) {
   DCHECK_GT(shared_memory_segment_count, 0);
-  DCHECK_EQ(shared_memory->created_size() % shared_memory_segment_count, 0u);
+  DCHECK_EQ(shared_memory->requested_size() % shared_memory_segment_count, 0u);
   shared_memory_segment_size_ =
-      shared_memory->created_size() / shared_memory_segment_count;
+      shared_memory->requested_size() / shared_memory_segment_count;
 }
 
 AudioInputSyncWriter::~AudioInputSyncWriter() {}
diff --git a/content/browser/renderer_host/media/audio_mirroring_manager_unittest.cc b/content/browser/renderer_host/media/audio_mirroring_manager_unittest.cc
index 3cf38ed..b05fd71 100644
--- a/content/browser/renderer_host/media/audio_mirroring_manager_unittest.cc
+++ b/content/browser/renderer_host/media/audio_mirroring_manager_unittest.cc
@@ -46,7 +46,7 @@
 class AudioMirroringManagerTest : public testing::Test {
  public:
   AudioMirroringManagerTest()
-      : message_loop_(MessageLoop::TYPE_IO),
+      : message_loop_(base::MessageLoop::TYPE_IO),
         io_thread_(BrowserThread::IO, &message_loop_),
         params_(AudioParameters::AUDIO_FAKE, media::CHANNEL_LAYOUT_STEREO,
                 AudioParameters::kAudioCDSampleRate, 16,
@@ -102,7 +102,7 @@
 }
 
  private:
-  MessageLoop message_loop_;
+  base::MessageLoop message_loop_;
   BrowserThreadImpl io_thread_;
   AudioParameters params_;
   AudioMirroringManager mirroring_manager_;
diff --git a/content/browser/renderer_host/media/audio_renderer_host.cc b/content/browser/renderer_host/media/audio_renderer_host.cc
index b652183..3b21720 100644
--- a/content/browser/renderer_host/media/audio_renderer_host.cc
+++ b/content/browser/renderer_host/media/audio_renderer_host.cc
@@ -5,6 +5,8 @@
 #include "content/browser/renderer_host/media/audio_renderer_host.h"
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/command_line.h"
 #include "base/metrics/histogram.h"
 #include "base/process.h"
 #include "base/shared_memory.h"
@@ -15,46 +17,85 @@
 #include "content/common/media/audio_messages.h"
 #include "content/public/browser/content_browser_client.h"
 #include "content/public/browser/media_observer.h"
+#include "content/public/common/content_switches.h"
 #include "media/audio/shared_memory_util.h"
 #include "media/base/audio_bus.h"
 #include "media/base/limits.h"
 
-// TODO(miu): Re-enable after M27 branch cut.  This feature is scheduled for
-// release in M28.
-#define DISABLED_AUDIO_INDICATOR_TRIGGERS_FOR_M27_ONLY
-
 using media::AudioBus;
 
 namespace content {
 
-struct AudioRendererHost::AudioEntry {
-  AudioEntry();
-  ~AudioEntry();
+class AudioRendererHost::AudioEntry
+    : public media::AudioOutputController::EventHandler {
+ public:
+  AudioEntry(AudioRendererHost* host,
+             int stream_id,
+             int render_view_id,
+             const media::AudioParameters& params,
+             scoped_ptr<base::SharedMemory> shared_memory,
+             scoped_ptr<media::AudioOutputController::SyncReader> reader);
+  virtual ~AudioEntry();
 
-  // The AudioOutputController that manages the audio stream.
-  scoped_refptr<media::AudioOutputController> controller;
+  int stream_id() const {
+    return stream_id_;
+  }
 
-  // The audio stream ID.
-  int stream_id;
+  int render_view_id() const {
+    return render_view_id_;
+  }
+
+  media::AudioOutputController* controller() const {
+    return controller_;
+  }
+
+  base::SharedMemory* shared_memory() {
+    return shared_memory_.get();
+  }
+
+  media::AudioOutputController::SyncReader* reader() const {
+    return reader_.get();
+  }
+
+ private:
+  // media::AudioOutputController::EventHandler implementation.
+  virtual void OnCreated() OVERRIDE;
+  virtual void OnPlaying() OVERRIDE;
+  virtual void OnAudible(bool is_audible) OVERRIDE;
+  virtual void OnPaused() OVERRIDE;
+  virtual void OnError() OVERRIDE;
+  virtual void OnDeviceChange(int new_buffer_size, int new_sample_rate)
+      OVERRIDE;
+
+  AudioRendererHost* const host_;
+  const int stream_id_;
 
   // The routing ID of the source render view.
-  int render_view_id;
+  const int render_view_id_;
+
+  // The AudioOutputController that manages the audio stream.
+  const scoped_refptr<media::AudioOutputController> controller_;
 
   // Shared memory for transmission of the audio data.
-  base::SharedMemory shared_memory;
+  const scoped_ptr<base::SharedMemory> shared_memory_;
 
-  // The synchronous reader to be used by the controller. We have the
-  // ownership of the reader.
-  scoped_ptr<media::AudioOutputController::SyncReader> reader;
-
-  // Set to true after we called Close() for the controller.
-  bool pending_close;
+  // The synchronous reader to be used by the controller.
+  const scoped_ptr<media::AudioOutputController::SyncReader> reader_;
 };
 
-AudioRendererHost::AudioEntry::AudioEntry()
-    : stream_id(0),
-      render_view_id(MSG_ROUTING_NONE),
-      pending_close(false) {
+AudioRendererHost::AudioEntry::AudioEntry(
+    AudioRendererHost* host, int stream_id, int render_view_id,
+    const media::AudioParameters& params,
+    scoped_ptr<base::SharedMemory> shared_memory,
+    scoped_ptr<media::AudioOutputController::SyncReader> reader)
+    : host_(host),
+      stream_id_(stream_id),
+      render_view_id_(render_view_id),
+      controller_(media::AudioOutputController::Create(
+          host->audio_manager_, this, params, reader.get())),
+      shared_memory_(shared_memory.Pass()),
+      reader_(reader.Pass()) {
+  DCHECK(controller_);
 }
 
 AudioRendererHost::AudioEntry::~AudioEntry() {}
@@ -78,96 +119,94 @@
 }
 
 void AudioRendererHost::OnChannelClosing() {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
   BrowserMessageFilter::OnChannelClosing();
 
   // Since the IPC channel is gone, close all requested audio streams.
-  DeleteEntries();
+  while (!audio_entries_.empty()) {
+    // Note: OnCloseStream() removes the entries from audio_entries_.
+    OnCloseStream(audio_entries_.begin()->first);
+  }
 }
 
 void AudioRendererHost::OnDestruct() const {
   BrowserThread::DeleteOnIOThread::Destruct(this);
 }
 
-///////////////////////////////////////////////////////////////////////////////
-// media::AudioOutputController::EventHandler implementations.
-void AudioRendererHost::OnCreated(media::AudioOutputController* controller) {
+void AudioRendererHost::AudioEntry::OnCreated() {
+  BrowserThread::PostTask(
+      BrowserThread::IO,
+      FROM_HERE,
+      base::Bind(&AudioRendererHost::DoCompleteCreation, host_, this));
+}
+
+void AudioRendererHost::AudioEntry::OnPlaying() {
   BrowserThread::PostTask(
       BrowserThread::IO,
       FROM_HERE,
       base::Bind(
-          &AudioRendererHost::DoCompleteCreation,
-          this,
-          make_scoped_refptr(controller)));
+          base::IgnoreResult(&AudioRendererHost::Send), host_,
+          new AudioMsg_NotifyStreamStateChanged(
+              stream_id_, media::AudioOutputIPCDelegate::kPlaying)));
 }
 
-void AudioRendererHost::OnPlaying(media::AudioOutputController* controller) {
+void AudioRendererHost::AudioEntry::OnAudible(bool is_audible) {
+  BrowserThread::PostTask(
+      BrowserThread::IO,
+      FROM_HERE,
+      base::Bind(&AudioRendererHost::DoNotifyAudibleState, host_,
+                 this, is_audible));
+}
+
+void AudioRendererHost::AudioEntry::OnPaused() {
   BrowserThread::PostTask(
       BrowserThread::IO,
       FROM_HERE,
       base::Bind(
-          &AudioRendererHost::DoSendPlayingMessage,
-          this,
-          make_scoped_refptr(controller)));
+          base::IgnoreResult(&AudioRendererHost::Send), host_,
+          new AudioMsg_NotifyStreamStateChanged(
+              stream_id_, media::AudioOutputIPCDelegate::kPaused)));
 }
 
-void AudioRendererHost::OnPaused(media::AudioOutputController* controller) {
+void AudioRendererHost::AudioEntry::OnError() {
   BrowserThread::PostTask(
       BrowserThread::IO,
       FROM_HERE,
-      base::Bind(
-          &AudioRendererHost::DoSendPausedMessage,
-          this,
-          make_scoped_refptr(controller)));
+      base::Bind(&AudioRendererHost::ReportErrorAndClose, host_, stream_id_));
 }
 
-void AudioRendererHost::OnError(media::AudioOutputController* controller) {
+void AudioRendererHost::AudioEntry::OnDeviceChange(int new_buffer_size,
+                                                   int new_sample_rate) {
   BrowserThread::PostTask(
       BrowserThread::IO,
       FROM_HERE,
-      base::Bind(
-          &AudioRendererHost::DoHandleError,
-          this,
-          make_scoped_refptr(controller)));
+      base::Bind(base::IgnoreResult(&AudioRendererHost::Send), host_,
+                 new AudioMsg_NotifyDeviceChanged(
+                     stream_id_, new_buffer_size, new_sample_rate)));
 }
 
-void AudioRendererHost::OnDeviceChange(media::AudioOutputController* controller,
-                                       int new_buffer_size,
-                                       int new_sample_rate) {
-  BrowserThread::PostTask(
-      BrowserThread::IO,
-      FROM_HERE,
-      base::Bind(&AudioRendererHost::DoSendDeviceChangeMessage,
-                 this, make_scoped_refptr(controller), new_buffer_size,
-                 new_sample_rate));
-}
-
-void AudioRendererHost::DoCompleteCreation(
-    media::AudioOutputController* controller) {
+void AudioRendererHost::DoCompleteCreation(AudioEntry* entry) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
 
-  AudioEntry* entry = LookupByController(controller);
-  if (!entry)
-    return;
-
   if (!peer_handle()) {
     NOTREACHED() << "Renderer process handle is invalid.";
-    DeleteEntryOnError(entry);
+    ReportErrorAndClose(entry->stream_id());
     return;
   }
 
   // Once the audio stream is created then complete the creation process by
   // mapping shared memory and sharing with the renderer process.
   base::SharedMemoryHandle foreign_memory_handle;
-  if (!entry->shared_memory.ShareToProcess(peer_handle(),
-                                           &foreign_memory_handle)) {
+  if (!entry->shared_memory()->ShareToProcess(peer_handle(),
+                                              &foreign_memory_handle)) {
     // If we failed to map and share the shared memory then close the audio
     // stream and send an error message.
-    DeleteEntryOnError(entry);
+    ReportErrorAndClose(entry->stream_id());
     return;
   }
 
-  AudioSyncReader* reader =
-      static_cast<AudioSyncReader*>(entry->reader.get());
+  AudioSyncReader* reader = static_cast<AudioSyncReader*>(entry->reader());
 
 #if defined(OS_WIN)
   base::SyncSocket::Handle foreign_socket_handle;
@@ -179,63 +218,35 @@
   // the construction of audio stream.
   if (!reader->PrepareForeignSocketHandle(peer_handle(),
                                           &foreign_socket_handle)) {
-    DeleteEntryOnError(entry);
+    ReportErrorAndClose(entry->stream_id());
     return;
   }
 
   Send(new AudioMsg_NotifyStreamCreated(
-      entry->stream_id,
+      entry->stream_id(),
       foreign_memory_handle,
       foreign_socket_handle,
-      media::PacketSizeInBytes(entry->shared_memory.created_size())));
+      media::PacketSizeInBytes(entry->shared_memory()->requested_size())));
 }
 
-void AudioRendererHost::DoSendPlayingMessage(
-    media::AudioOutputController* controller) {
+void AudioRendererHost::DoNotifyAudibleState(AudioEntry* entry,
+                                             bool is_audible) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
 
-  AudioEntry* entry = LookupByController(controller);
-  if (!entry)
-    return;
+  MediaObserver* const media_observer =
+      GetContentClient()->browser()->GetMediaObserver();
+  if (media_observer) {
+    DVLOG(1) << "AudioRendererHost@" << this
+             << "::DoNotifyAudibleState(is_audible=" << is_audible
+             << ") for stream_id=" << entry->stream_id();
 
-  Send(new AudioMsg_NotifyStreamStateChanged(
-      entry->stream_id, media::AudioOutputIPCDelegate::kPlaying));
-}
-
-void AudioRendererHost::DoSendPausedMessage(
-    media::AudioOutputController* controller) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-
-  AudioEntry* entry = LookupByController(controller);
-  if (!entry)
-    return;
-
-  Send(new AudioMsg_NotifyStreamStateChanged(
-      entry->stream_id, media::AudioOutputIPCDelegate::kPaused));
-}
-
-void AudioRendererHost::DoSendDeviceChangeMessage(
-    media::AudioOutputController* controller, int new_buffer_size,
-    int new_sample_rate) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-
-  AudioEntry* entry = LookupByController(controller);
-  if (!entry)
-    return;
-
-  Send(new AudioMsg_NotifyDeviceChanged(
-      entry->stream_id, new_buffer_size, new_sample_rate));
-}
-
-void AudioRendererHost::DoHandleError(
-    media::AudioOutputController* controller) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-
-  AudioEntry* entry = LookupByController(controller);
-  if (!entry)
-    return;
-
-  DeleteEntryOnError(entry);
+    if (CommandLine::ForCurrentProcess()->HasSwitch(
+            switches::kEnableAudibleNotifications)) {
+      media_observer->OnAudioStreamPlayingChanged(
+          render_process_id_, entry->render_view_id(), entry->stream_id(),
+          is_audible);
+    }
+  }
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -245,11 +256,8 @@
   bool handled = true;
   IPC_BEGIN_MESSAGE_MAP_EX(AudioRendererHost, message, *message_was_ok)
     IPC_MESSAGE_HANDLER(AudioHostMsg_CreateStream, OnCreateStream)
-    IPC_MESSAGE_HANDLER(AudioHostMsg_AssociateStreamWithProducer,
-                        OnAssociateStreamWithProducer)
     IPC_MESSAGE_HANDLER(AudioHostMsg_PlayStream, OnPlayStream)
     IPC_MESSAGE_HANDLER(AudioHostMsg_PauseStream, OnPauseStream)
-    IPC_MESSAGE_HANDLER(AudioHostMsg_FlushStream, OnFlushStream)
     IPC_MESSAGE_HANDLER(AudioHostMsg_CloseStream, OnCloseStream)
     IPC_MESSAGE_HANDLER(AudioHostMsg_SetVolume, OnSetVolume)
     IPC_MESSAGE_UNHANDLED(handled = false)
@@ -259,8 +267,14 @@
 }
 
 void AudioRendererHost::OnCreateStream(
-    int stream_id, const media::AudioParameters& params) {
+    int stream_id, int render_view_id, const media::AudioParameters& params) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+  DVLOG(1) << "AudioRendererHost@" << this
+           << "::OnCreateStream(stream_id=" << stream_id
+           << ", render_view_id=" << render_view_id << ")";
+  DCHECK_GT(render_view_id, 0);
+
   // media::AudioParameters is validated in the deserializer.
   int input_channels = params.input_channels();
   if (input_channels < 0 ||
@@ -270,89 +284,43 @@
     return;
   }
 
-  media::AudioParameters audio_params(params);
-
   // Calculate output and input memory size.
-  int output_memory_size = AudioBus::CalculateMemorySize(audio_params);
-
-  int frames = audio_params.frames_per_buffer();
+  int output_memory_size = AudioBus::CalculateMemorySize(params);
+  int frames = params.frames_per_buffer();
   int input_memory_size =
       AudioBus::CalculateMemorySize(input_channels, frames);
 
-  scoped_ptr<AudioEntry> entry(new AudioEntry());
-
   // Create the shared memory and share with the renderer process.
   // For synchronized I/O (if input_channels > 0) then we allocate
   // extra memory after the output data for the input data.
   uint32 io_buffer_size = output_memory_size + input_memory_size;
-
   uint32 shared_memory_size =
       media::TotalSharedMemorySizeInBytes(io_buffer_size);
-  if (!entry->shared_memory.CreateAndMapAnonymous(shared_memory_size)) {
-    // If creation of shared memory failed then send an error message.
+  scoped_ptr<base::SharedMemory> shared_memory(new base::SharedMemory());
+  if (!shared_memory->CreateAndMapAnonymous(shared_memory_size)) {
     SendErrorMessage(stream_id);
     return;
   }
 
-  // Create sync reader and try to initialize it.
   scoped_ptr<AudioSyncReader> reader(
-      new AudioSyncReader(&entry->shared_memory, params, input_channels));
-
+      new AudioSyncReader(shared_memory.get(), params, input_channels));
   if (!reader->Init()) {
     SendErrorMessage(stream_id);
     return;
   }
 
-  // If we have successfully created the SyncReader then assign it to the
-  // entry and construct an AudioOutputController.
-  entry->reader.reset(reader.release());
-  entry->controller = media::AudioOutputController::Create(
-      audio_manager_, this, audio_params, entry->reader.get());
-
-  if (!entry->controller) {
-    SendErrorMessage(stream_id);
-    return;
+  scoped_ptr<AudioEntry> entry(new AudioEntry(
+      this, stream_id, render_view_id, params, shared_memory.Pass(),
+      reader.PassAs<media::AudioOutputController::SyncReader>()));
+  if (mirroring_manager_) {
+    mirroring_manager_->AddDiverter(
+        render_process_id_, entry->render_view_id(), entry->controller());
   }
-
-  // If we have created the controller successfully, create an entry and add it
-  // to the map.
-  entry->stream_id = stream_id;
   audio_entries_.insert(std::make_pair(stream_id, entry.release()));
   if (media_internals_)
     media_internals_->OnSetAudioStreamStatus(this, stream_id, "created");
 }
 
-void AudioRendererHost::OnAssociateStreamWithProducer(int stream_id,
-                                                      int render_view_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-
-  DVLOG(1) << "AudioRendererHost@" << this
-           << "::OnAssociateStreamWithProducer(stream_id=" << stream_id
-           << ", render_view_id=" << render_view_id << ")";
-
-  AudioEntry* const entry = LookupById(stream_id);
-  if (!entry) {
-    SendErrorMessage(stream_id);
-    return;
-  }
-
-  if (entry->render_view_id == render_view_id)
-    return;
-
-  // TODO(miu): Merge "AssociateWithProducer" message into "CreateStream"
-  // message so AudioRendererHost can assume a simpler "render_view_id is set
-  // once" scheme. http://crbug.com/166779
-  if (mirroring_manager_) {
-    mirroring_manager_->RemoveDiverter(
-        render_process_id_, entry->render_view_id, entry->controller);
-  }
-  entry->render_view_id = render_view_id;
-  if (mirroring_manager_) {
-    mirroring_manager_->AddDiverter(
-        render_process_id_, entry->render_view_id, entry->controller);
-  }
-}
-
 void AudioRendererHost::OnPlayStream(int stream_id) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
 
@@ -362,18 +330,9 @@
     return;
   }
 
-  entry->controller->Play();
+  entry->controller()->Play();
   if (media_internals_)
     media_internals_->OnSetAudioStreamPlaying(this, stream_id, true);
-
-#ifndef DISABLED_AUDIO_INDICATOR_TRIGGERS_FOR_M27_ONLY
-  MediaObserver* media_observer =
-      GetContentClient()->browser()->GetMediaObserver();
-  if (media_observer) {
-    media_observer->OnAudioStreamPlayingChanged(
-        render_process_id_, entry->render_view_id, stream_id, true);
-  }
-#endif
 }
 
 void AudioRendererHost::OnPauseStream(int stream_id) {
@@ -385,46 +344,9 @@
     return;
   }
 
-  entry->controller->Pause();
+  entry->controller()->Pause();
   if (media_internals_)
     media_internals_->OnSetAudioStreamPlaying(this, stream_id, false);
-
-#ifndef DISABLED_AUDIO_INDICATOR_TRIGGERS_FOR_M27_ONLY
-  MediaObserver* media_observer =
-      GetContentClient()->browser()->GetMediaObserver();
-  if (media_observer) {
-    media_observer->OnAudioStreamPlayingChanged(
-        render_process_id_, entry->render_view_id, stream_id, false);
-  }
-#endif
-}
-
-void AudioRendererHost::OnFlushStream(int stream_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-
-  AudioEntry* entry = LookupById(stream_id);
-  if (!entry) {
-    SendErrorMessage(stream_id);
-    return;
-  }
-
-  entry->controller->Flush();
-  if (media_internals_)
-    media_internals_->OnSetAudioStreamStatus(this, stream_id, "flushed");
-}
-
-void AudioRendererHost::OnCloseStream(int stream_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-
-  if (media_internals_)
-    media_internals_->OnSetAudioStreamStatus(this, stream_id, "closed");
-
-  AudioEntry* entry = LookupById(stream_id);
-
-  if (!entry)
-    return;
-
-  CloseAndDeleteStream(entry);
 }
 
 void AudioRendererHost::OnSetVolume(int stream_id, double volume) {
@@ -439,110 +361,79 @@
   // Make sure the volume is valid.
   if (volume < 0 || volume > 1.0)
     return;
-  entry->controller->SetVolume(volume);
+  entry->controller()->SetVolume(volume);
   if (media_internals_)
     media_internals_->OnSetAudioStreamVolume(this, stream_id, volume);
-
-#ifndef DISABLED_AUDIO_INDICATOR_TRIGGERS_FOR_M27_ONLY
-  MediaObserver* media_observer =
-      GetContentClient()->browser()->GetMediaObserver();
-  if (media_observer) {
-    bool playing = volume > 0;
-    media_observer->OnAudioStreamPlayingChanged(
-        render_process_id_, entry->render_view_id, stream_id, playing);
-  }
-#endif
 }
 
-void AudioRendererHost::SendErrorMessage(int32 stream_id) {
+void AudioRendererHost::SendErrorMessage(int stream_id) {
   Send(new AudioMsg_NotifyStreamStateChanged(
       stream_id, media::AudioOutputIPCDelegate::kError));
 }
 
-void AudioRendererHost::DeleteEntries() {
+void AudioRendererHost::OnCloseStream(int stream_id) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
 
-  for (AudioEntryMap::iterator i = audio_entries_.begin();
-       i != audio_entries_.end(); ++i) {
-    CloseAndDeleteStream(i->second);
+  // Prevent oustanding callbacks from attempting to close/delete the same
+  // AudioEntry twice.
+  AudioEntryMap::iterator i = audio_entries_.find(stream_id);
+  if (i == audio_entries_.end())
+    return;
+  scoped_ptr<AudioEntry> entry(i->second);
+  audio_entries_.erase(i);
+
+  media::AudioOutputController* const controller = entry->controller();
+  if (mirroring_manager_) {
+    mirroring_manager_->RemoveDiverter(
+        render_process_id_, entry->render_view_id(), controller);
   }
+  controller->Close(
+      base::Bind(&AudioRendererHost::DeleteEntry, this, base::Passed(&entry)));
+
+  if (media_internals_)
+    media_internals_->OnSetAudioStreamStatus(this, stream_id, "closed");
 }
 
-void AudioRendererHost::CloseAndDeleteStream(AudioEntry* entry) {
+void AudioRendererHost::DeleteEntry(scoped_ptr<AudioEntry> entry) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
 
-#ifndef DISABLED_AUDIO_INDICATOR_TRIGGERS_FOR_M27_ONLY
-  MediaObserver* media_observer =
+  // At this point, make the final "say" in audio playback state.
+  MediaObserver* const media_observer =
       GetContentClient()->browser()->GetMediaObserver();
   if (media_observer) {
     media_observer->OnAudioStreamPlayingChanged(
-        render_process_id_, entry->render_view_id, entry->stream_id, false);
+        render_process_id_, entry->render_view_id(), entry->stream_id(), false);
   }
-#endif
-  if (!entry->pending_close) {
-    if (mirroring_manager_) {
-      mirroring_manager_->RemoveDiverter(
-          render_process_id_, entry->render_view_id, entry->controller);
-    }
-    entry->controller->Close(
-        base::Bind(&AudioRendererHost::DeleteEntry, this, entry));
-    entry->pending_close = true;
-  }
-}
-
-void AudioRendererHost::DeleteEntry(AudioEntry* entry) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-
-  // Delete the entry when this method goes out of scope.
-  scoped_ptr<AudioEntry> entry_deleter(entry);
-
-  // Erase the entry identified by |stream_id| from the map.
-  audio_entries_.erase(entry->stream_id);
 
   // Notify the media observer.
   if (media_internals_)
-    media_internals_->OnDeleteAudioStream(this, entry->stream_id);
+    media_internals_->OnDeleteAudioStream(this, entry->stream_id());
+
+  // Note: |entry| will be deleted upon leaving this scope.
 }
 
-void AudioRendererHost::DeleteEntryOnError(AudioEntry* entry) {
+void AudioRendererHost::ReportErrorAndClose(int stream_id) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
 
-  // Sends the error message first before we close the stream because
-  // |entry| is destroyed in DeleteEntry().
-  SendErrorMessage(entry->stream_id);
+  // Make sure this isn't a stray callback executing after the stream has been
+  // closed, so error notifications aren't sent after clients believe the stream
+  // is closed.
+  if (!LookupById(stream_id))
+    return;
+
+  SendErrorMessage(stream_id);
 
   if (media_internals_)
-    media_internals_->OnSetAudioStreamStatus(this, entry->stream_id, "error");
-  CloseAndDeleteStream(entry);
+    media_internals_->OnSetAudioStreamStatus(this, stream_id, "error");
+
+  OnCloseStream(stream_id);
 }
 
 AudioRendererHost::AudioEntry* AudioRendererHost::LookupById(int stream_id) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
 
-  AudioEntryMap::iterator i = audio_entries_.find(stream_id);
-  if (i != audio_entries_.end() && !i->second->pending_close)
-    return i->second;
-  return NULL;
-}
-
-AudioRendererHost::AudioEntry* AudioRendererHost::LookupByController(
-    media::AudioOutputController* controller) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-
-  // Iterate the map of entries.
-  // TODO(hclam): Implement a faster look up method.
-  for (AudioEntryMap::iterator i = audio_entries_.begin();
-       i != audio_entries_.end(); ++i) {
-    if (!i->second->pending_close && controller == i->second->controller.get())
-      return i->second;
-  }
-  return NULL;
-}
-
-media::AudioOutputController* AudioRendererHost::LookupControllerByIdForTesting(
-    int stream_id) {
-  AudioEntry* const entry = LookupById(stream_id);
-  return entry ? entry->controller : NULL;
+  AudioEntryMap::const_iterator i = audio_entries_.find(stream_id);
+  return i != audio_entries_.end() ? i->second : NULL;
 }
 
 }  // namespace content
diff --git a/content/browser/renderer_host/media/audio_renderer_host.h b/content/browser/renderer_host/media/audio_renderer_host.h
index de5944e..803539c 100644
--- a/content/browser/renderer_host/media/audio_renderer_host.h
+++ b/content/browser/renderer_host/media/audio_renderer_host.h
@@ -63,9 +63,7 @@
 class MediaInternals;
 class ResourceContext;
 
-class CONTENT_EXPORT AudioRendererHost
-    : public BrowserMessageFilter,
-      public media::AudioOutputController::EventHandler {
+class CONTENT_EXPORT AudioRendererHost : public BrowserMessageFilter {
  public:
   // Called from UI thread from the owner of this object.
   AudioRendererHost(int render_process_id,
@@ -79,15 +77,6 @@
   virtual bool OnMessageReceived(const IPC::Message& message,
                                  bool* message_was_ok) OVERRIDE;
 
-  // AudioOutputController::EventHandler implementations.
-  virtual void OnCreated(media::AudioOutputController* controller) OVERRIDE;
-  virtual void OnPlaying(media::AudioOutputController* controller) OVERRIDE;
-  virtual void OnPaused(media::AudioOutputController* controller) OVERRIDE;
-  virtual void OnError(media::AudioOutputController* controller) OVERRIDE;
-  virtual void OnDeviceChange(media::AudioOutputController* controller,
-                              int new_buffer_size,
-                              int new_sample_rate) OVERRIDE;
-
  private:
   friend class AudioRendererHostTest;
   friend class BrowserThread;
@@ -96,7 +85,7 @@
   FRIEND_TEST_ALL_PREFIXES(AudioRendererHostTest, CreateMockStream);
   FRIEND_TEST_ALL_PREFIXES(AudioRendererHostTest, MockStreamDataConversation);
 
-  struct AudioEntry;
+  class AudioEntry;
   typedef std::map<int, AudioEntry*> AudioEntryMap;
 
   virtual ~AudioRendererHost();
@@ -104,15 +93,14 @@
   // Methods called on IO thread ----------------------------------------------
 
   // Audio related IPC message handlers.
-  // Creates an audio output stream with the specified format. If this call is
-  // successful this object would keep an internal entry of the stream for the
-  // required properties.
-  void OnCreateStream(int stream_id,
-                      const media::AudioParameters& params);
 
-  // Track that the data for the audio stream referenced by |stream_id| is
+  // Creates an audio output stream with the specified format whose data is
   // produced by an entity in the render view referenced by |render_view_id|.
-  void OnAssociateStreamWithProducer(int stream_id, int render_view_id);
+  // Upon success/failure, the peer is notified via the NotifyStreamCreated
+  // message.
+  void OnCreateStream(int stream_id,
+                      int render_view_id,
+                      const media::AudioParameters& params);
 
   // Play the audio stream referenced by |stream_id|.
   void OnPlayStream(int stream_id);
@@ -120,9 +108,6 @@
   // Pause the audio stream referenced by |stream_id|.
   void OnPauseStream(int stream_id);
 
-  // Discard all audio data in stream referenced by |stream_id|.
-  void OnFlushStream(int stream_id);
-
   // Close the audio stream referenced by |stream_id|.
   void OnCloseStream(int stream_id);
 
@@ -130,46 +115,27 @@
   void OnSetVolume(int stream_id, double volume);
 
   // Complete the process of creating an audio stream. This will set up the
-  // shared memory or shared socket in low latency mode.
-  void DoCompleteCreation(media::AudioOutputController* controller);
+  // shared memory or shared socket in low latency mode and send the
+  // NotifyStreamCreated message to the peer.
+  void DoCompleteCreation(AudioEntry* entry);
 
-  // Send a state change message to the renderer.
-  void DoSendPlayingMessage(media::AudioOutputController* controller);
-  void DoSendPausedMessage(media::AudioOutputController* controller);
-  void DoSendDeviceChangeMessage(media::AudioOutputController* controller,
-                                 int new_buffer_size, int new_sample_rate);
-
-  // Handle error coming from audio stream.
-  void DoHandleError(media::AudioOutputController* controller);
+  // Propagate audible signal to MediaObserver.
+  void DoNotifyAudibleState(AudioEntry* entry, bool is_audible);
 
   // Send an error message to the renderer.
   void SendErrorMessage(int stream_id);
 
-  // Delete all audio entry and all audio streams
-  void DeleteEntries();
+  // Delete an audio entry, notifying observers first.  This is called by
+  // AudioOutputController after it has closed.
+  void DeleteEntry(scoped_ptr<AudioEntry> entry);
 
-  // Closes the stream. The stream is then deleted in DeleteEntry() after it
-  // is closed.
-  void CloseAndDeleteStream(AudioEntry* entry);
-
-  // Delete an audio entry and close the related audio stream.
-  void DeleteEntry(AudioEntry* entry);
-
-  // Delete audio entry and close the related audio stream due to an error,
-  // and error message is send to the renderer.
-  void DeleteEntryOnError(AudioEntry* entry);
+  // Send an error message to the renderer, then close the stream.
+  void ReportErrorAndClose(int stream_id);
 
   // A helper method to look up a AudioEntry identified by |stream_id|.
   // Returns NULL if not found.
   AudioEntry* LookupById(int stream_id);
 
-  // Search for a AudioEntry having the reference to |controller|.
-  // This method is used to look up an AudioEntry after a controller
-  // event is received.
-  AudioEntry* LookupByController(media::AudioOutputController* controller);
-
-  media::AudioOutputController* LookupControllerByIdForTesting(int stream_id);
-
   // ID of the RenderProcessHost that owns this instance.
   const int render_process_id_;
 
diff --git a/content/browser/renderer_host/media/audio_renderer_host_unittest.cc b/content/browser/renderer_host/media/audio_renderer_host_unittest.cc
index 4e9aaaa..6a674a4 100644
--- a/content/browser/renderer_host/media/audio_renderer_host_unittest.cc
+++ b/content/browser/renderer_host/media/audio_renderer_host_unittest.cc
@@ -70,7 +70,6 @@
   MOCK_METHOD1(OnStreamPlaying, void(int stream_id));
   MOCK_METHOD1(OnStreamPaused, void(int stream_id));
   MOCK_METHOD1(OnStreamError, void(int stream_id));
-  MOCK_METHOD2(OnStreamVolume, void(int stream_id, double volume));
 
  private:
   virtual ~MockAudioRendererHost() {
@@ -101,13 +100,13 @@
   }
 
   void OnStreamCreated(const IPC::Message& msg, int stream_id,
-                                 base::SharedMemoryHandle handle,
+                       base::SharedMemoryHandle handle,
 #if defined(OS_WIN)
-                                 base::SyncSocket::Handle socket_handle,
+                       base::SyncSocket::Handle socket_handle,
 #else
-                                 base::FileDescriptor socket_descriptor,
+                       base::FileDescriptor socket_descriptor,
 #endif
-                                 uint32 length) {
+                       uint32 length) {
     // Maps the shared memory.
     shared_memory_.reset(new base::SharedMemory(handle, false));
     CHECK(shared_memory_->Map(length));
@@ -153,7 +152,7 @@
 };
 
 ACTION_P(QuitMessageLoop, message_loop) {
-  message_loop->PostTask(FROM_HERE, MessageLoop::QuitClosure());
+  message_loop->PostTask(FROM_HERE, base::MessageLoop::QuitClosure());
 }
 
 class AudioRendererHostTest : public testing::Test {
@@ -163,7 +162,7 @@
  protected:
   virtual void SetUp() {
     // Create a message loop so AudioRendererHost can use it.
-    message_loop_.reset(new MessageLoop(MessageLoop::TYPE_IO));
+    message_loop_.reset(new base::MessageLoop(base::MessageLoop::TYPE_IO));
 
     // Claim to be on both the UI and IO threads to pass all the DCHECKS.
     io_thread_.reset(new BrowserThreadImpl(BrowserThread::IO,
@@ -199,15 +198,16 @@
   void Create() {
     EXPECT_CALL(*observer_,
                 OnSetAudioStreamStatus(_, kStreamId, "created"));
-
-    InSequence s;
-    // We will first receive an OnStreamCreated() signal.
     EXPECT_CALL(*host_, OnStreamCreated(kStreamId, _))
         .WillOnce(QuitMessageLoop(message_loop_.get()));
+    EXPECT_CALL(mirroring_manager_,
+                AddDiverter(kRenderProcessId, kRenderViewId, NotNull()))
+        .RetiresOnSaturation();
 
     // Send a create stream message to the audio output stream and wait until
     // we receive the created message.
     host_->OnCreateStream(kStreamId,
+                          kRenderViewId,
                           media::AudioParameters(
                               media::AudioParameters::AUDIO_FAKE,
                               media::CHANNEL_LAYOUT_STEREO,
@@ -215,29 +215,21 @@
                               media::AudioParameters::kAudioCDSampleRate / 10));
     message_loop_->Run();
 
-    // Simulate the renderer process associating a stream with a render view.
-    EXPECT_CALL(mirroring_manager_,
-                RemoveDiverter(kRenderProcessId, MSG_ROUTING_NONE, _))
-        .RetiresOnSaturation();
-    EXPECT_CALL(mirroring_manager_,
-                AddDiverter(kRenderProcessId, kRenderViewId, NotNull()))
-        .RetiresOnSaturation();
-    host_->OnAssociateStreamWithProducer(kStreamId, kRenderViewId);
-    message_loop_->RunUntilIdle();
     // At some point in the future, a corresponding RemoveDiverter() call must
     // be made.
     EXPECT_CALL(mirroring_manager_,
                 RemoveDiverter(kRenderProcessId, kRenderViewId, NotNull()))
         .RetiresOnSaturation();
 
+    // All created streams should ultimately be closed.
+    EXPECT_CALL(*observer_,
+                OnSetAudioStreamStatus(_, kStreamId, "closed"));
+
     // Expect the audio stream will be deleted at some later point.
     EXPECT_CALL(*observer_, OnDeleteAudioStream(_, kStreamId));
   }
 
   void Close() {
-    EXPECT_CALL(*observer_,
-                OnSetAudioStreamStatus(_, kStreamId, "closed"));
-
     // Send a message to AudioRendererHost to tell it we want to close the
     // stream.
     host_->OnCloseStream(kStreamId);
@@ -275,18 +267,14 @@
   void SimulateError() {
     EXPECT_CALL(*observer_,
                 OnSetAudioStreamStatus(_, kStreamId, "error"));
-    // Find the first AudioOutputController in the AudioRendererHost.
-    CHECK(host_->audio_entries_.size())
+    EXPECT_EQ(1u, host_->audio_entries_.size())
         << "Calls Create() before calling this method";
-    media::AudioOutputController* controller =
-        host_->LookupControllerByIdForTesting(kStreamId);
-    CHECK(controller) << "AudioOutputController not found";
 
     // Expect an error signal sent through IPC.
     EXPECT_CALL(*host_, OnStreamError(kStreamId));
 
     // Simulate an error sent from the audio device.
-    host_->OnError(controller);
+    host_->ReportErrorAndClose(kStreamId);
     SyncWithAudioThread();
 
     // Expect the audio stream record is removed.
@@ -294,13 +282,13 @@
   }
 
   // Called on the audio thread.
-  static void PostQuitMessageLoop(MessageLoop* message_loop) {
-    message_loop->PostTask(FROM_HERE, MessageLoop::QuitClosure());
+  static void PostQuitMessageLoop(base::MessageLoop* message_loop) {
+    message_loop->PostTask(FROM_HERE, base::MessageLoop::QuitClosure());
   }
 
   // Called on the main thread.
   static void PostQuitOnAudioThread(media::AudioManager* audio_manager,
-                                    MessageLoop* message_loop) {
+                                    base::MessageLoop* message_loop) {
     audio_manager->GetMessageLoop()->PostTask(FROM_HERE,
         base::Bind(&PostQuitMessageLoop, message_loop));
   }
@@ -323,7 +311,7 @@
   scoped_ptr<MockMediaInternals> observer_;
   MockAudioMirroringManager mirroring_manager_;
   scoped_refptr<MockAudioRendererHost> host_;
-  scoped_ptr<MessageLoop> message_loop_;
+  scoped_ptr<base::MessageLoop> message_loop_;
   scoped_ptr<BrowserThreadImpl> io_thread_;
   scoped_ptr<BrowserThreadImpl> ui_thread_;
   scoped_ptr<media::AudioManager> audio_manager_;
diff --git a/content/browser/renderer_host/media/audio_sync_reader.cc b/content/browser/renderer_host/media/audio_sync_reader.cc
index 620ba54..9ebf5ed 100644
--- a/content/browser/renderer_host/media/audio_sync_reader.cc
+++ b/content/browser/renderer_host/media/audio_sync_reader.cc
@@ -24,7 +24,7 @@
       input_channels_(input_channels),
       renderer_callback_count_(0),
       renderer_missed_callback_count_(0) {
-  packet_size_ = media::PacketSizeInBytes(shared_memory_->created_size());
+  packet_size_ = media::PacketSizeInBytes(shared_memory_->requested_size());
   int input_memory_size = 0;
   int output_memory_size = AudioBus::CalculateMemorySize(params);
   if (input_channels_ > 0) {
@@ -63,7 +63,7 @@
     media::SetUnknownDataSize(shared_memory_, packet_size_);
   }
 
-  if (socket_.get()) {
+  if (socket_) {
     socket_->Send(&bytes, sizeof(bytes));
   }
 }
@@ -75,10 +75,18 @@
 
   // Copy optional synchronized live audio input for consumption by renderer
   // process.
-  if (source && input_bus_.get()) {
+  if (source && input_bus_) {
     DCHECK_EQ(source->channels(), input_bus_->channels());
-    DCHECK_LE(source->frames(), input_bus_->frames());
-    source->CopyTo(input_bus_.get());
+    // TODO(crogers): In some cases with device and sample-rate changes
+    // it's possible for an AOR to insert a resampler in the path.
+    // Because this is used with the Web Audio API, it'd be better
+    // to bypass the device change handling in AOR and instead let
+    // the renderer-side Web Audio code deal with this.
+    if (source->frames() == input_bus_->frames() &&
+        source->channels() == input_bus_->channels())
+      source->CopyTo(input_bus_.get());
+    else
+      input_bus_->Zero();
   }
 
   // Retrieve the actual number of bytes available from the shared memory.  If
@@ -119,7 +127,7 @@
 }
 
 void AudioSyncReader::Close() {
-  if (socket_.get()) {
+  if (socket_) {
     socket_->Close();
   }
 }
diff --git a/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc b/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc
index 99fdc6b..abd600b 100644
--- a/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc
+++ b/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc
@@ -9,11 +9,11 @@
 #include "content/browser/browser_thread_impl.h"
 #include "content/browser/renderer_host/media/media_stream_dispatcher_host.h"
 #include "content/browser/renderer_host/media/media_stream_manager.h"
-#include "content/browser/renderer_host/media/mock_media_observer.h"
 #include "content/browser/renderer_host/media/video_capture_manager.h"
 #include "content/common/media/media_stream_messages.h"
 #include "content/common/media/media_stream_options.h"
 #include "content/public/test/mock_resource_context.h"
+#include "content/public/test/test_browser_thread.h"
 #include "content/test/test_content_browser_client.h"
 #include "content/test/test_content_client.h"
 #include "ipc/ipc_message_macros.h"
@@ -38,7 +38,7 @@
 class MockMediaStreamDispatcherHost : public MediaStreamDispatcherHost,
                                       public TestContentBrowserClient {
  public:
-  MockMediaStreamDispatcherHost(MessageLoop* message_loop,
+  MockMediaStreamDispatcherHost(base::MessageLoop* message_loop,
                                 MediaStreamManager* manager)
       : MediaStreamDispatcherHost(kProcessId),
         message_loop_(message_loop),
@@ -49,7 +49,6 @@
                void(int routing_id, int request_id, int audio_array_size,
                     int video_array_size));
   MOCK_METHOD2(OnStreamGenerationFailed, void(int routing_id, int request_id));
-  MOCK_METHOD0(GetMediaObserver, MediaObserver*());
 
   // Accessor to private functions.
   void OnGenerateStream(int page_request_id, const StreamOptions& components) {
@@ -110,7 +109,7 @@
     OnStreamGenerated(msg.routing_id(), request_id, audio_device_list.size(),
         video_device_list.size());
     // Notify that the event have occured.
-    message_loop_->PostTask(FROM_HERE, MessageLoop::QuitClosure());
+    message_loop_->PostTask(FROM_HERE, base::MessageLoop::QuitClosure());
     label_ = label;
     audio_devices_ = audio_device_list;
     video_devices_ = video_device_list;
@@ -118,18 +117,22 @@
 
   void OnStreamGenerationFailed(const IPC::Message& msg, int request_id) {
     OnStreamGenerationFailed(msg.routing_id(), request_id);
-    message_loop_->PostTask(FROM_HERE, MessageLoop::QuitClosure());
+    message_loop_->PostTask(FROM_HERE, base::MessageLoop::QuitClosure());
     label_= "";
   }
 
-  MessageLoop* message_loop_;
+  base::MessageLoop* message_loop_;
   MediaStreamManager* manager_;
 };
 
+class MockMediaStreamUI : public MediaStreamUI {
+ public:
+  MOCK_METHOD1(OnStarted, void(const base::Closure& stop));
+};
+
 class MediaStreamDispatcherHostTest : public testing::Test {
  public:
-  MediaStreamDispatcherHostTest() : old_client_(NULL),
-                                    old_browser_client_(NULL) {}
+  MediaStreamDispatcherHostTest() : old_browser_client_(NULL) {}
   virtual ~MediaStreamDispatcherHostTest() {}
 
   void WaitForResult() {
@@ -139,12 +142,11 @@
  protected:
   virtual void SetUp() OVERRIDE {
     // MediaStreamManager must be created and called on IO thread.
-    message_loop_.reset(new MessageLoop(MessageLoop::TYPE_IO));
-    io_thread_.reset(new BrowserThreadImpl(BrowserThread::IO,
+    message_loop_.reset(new MessageLoop(base::MessageLoop::TYPE_IO));
+    ui_thread_.reset(new TestBrowserThread(BrowserThread::UI,
                                            message_loop_.get()));
-
-    // Create our own media observer.
-    media_observer_.reset(new MockMediaObserver());
+    io_thread_.reset(new TestBrowserThread(BrowserThread::IO,
+                                           message_loop_.get()));
 
     // Create our own MediaStreamManager.
     audio_manager_.reset(media::AudioManager::Create());
@@ -156,19 +158,24 @@
                                               media_stream_manager_.get());
 
     // Use the fake content client and browser.
-    old_client_ = GetContentClient();
-    old_browser_client_ = GetContentClient()->browser();
     content_client_.reset(new TestContentClient);
     SetContentClient(content_client_.get());
-    content_client_->set_browser_for_testing(host_);
+    old_browser_client_ = SetBrowserClientForTesting(host_);
+  }
+
+  virtual void SetupFakeUI(bool expect_started) {
+    scoped_ptr<MockMediaStreamUI> stream_ui(new MockMediaStreamUI());
+    if (expect_started) {
+      EXPECT_CALL(*stream_ui, OnStarted(_));
+    }
+    media_stream_manager_->UseFakeUI(stream_ui.PassAs<MediaStreamUI>());
   }
 
   virtual void TearDown() OVERRIDE {
     message_loop_->RunUntilIdle();
 
     // Recover the old browser client and content client.
-    GetContentClient()->set_browser_for_testing(old_browser_client_);
-    SetContentClient(old_client_);
+    SetBrowserClientForTesting(old_browser_client_);
     content_client_.reset();
 
     // Delete the IO message loop to delete the device thread,
@@ -177,27 +184,22 @@
   }
 
   scoped_refptr<MockMediaStreamDispatcherHost> host_;
-  scoped_ptr<MessageLoop> message_loop_;
-  scoped_ptr<BrowserThreadImpl> io_thread_;
+  scoped_ptr<base::MessageLoop> message_loop_;
+  scoped_ptr<TestBrowserThread> ui_thread_;
+  scoped_ptr<TestBrowserThread> io_thread_;
   scoped_ptr<media::AudioManager> audio_manager_;
   scoped_ptr<MediaStreamManager> media_stream_manager_;
-  ContentClient* old_client_;
   ContentBrowserClient* old_browser_client_;
   scoped_ptr<ContentClient> content_client_;
-  scoped_ptr<MockMediaObserver> media_observer_;
 };
 
 TEST_F(MediaStreamDispatcherHostTest, GenerateStream) {
   StreamOptions options(MEDIA_NO_SERVICE, MEDIA_DEVICE_VIDEO_CAPTURE);
 
-  EXPECT_CALL(*host_, GetMediaObserver())
-      .WillRepeatedly(Return(media_observer_.get()));
+  SetupFakeUI(true);
   EXPECT_CALL(*host_, OnStreamGenerated(kRenderId, kPageRequestId, 0, 1));
   host_->OnGenerateStream(kPageRequestId, options);
 
-  EXPECT_CALL(*media_observer_.get(), OnCaptureDevicesOpened(_, _, _, _));
-  EXPECT_CALL(*media_observer_.get(), OnCaptureDevicesClosed(_, _, _));
-
   WaitForResult();
 
   std::string label =  host_->label_;
@@ -217,13 +219,10 @@
   StreamOptions options(MEDIA_NO_SERVICE, MEDIA_DEVICE_VIDEO_CAPTURE);
 
   // Generate first stream.
-  EXPECT_CALL(*host_, GetMediaObserver())
-      .WillRepeatedly(Return(media_observer_.get()));
+  SetupFakeUI(true);
   EXPECT_CALL(*host_, OnStreamGenerated(kRenderId, kPageRequestId, 0, 1));
   host_->OnGenerateStream(kPageRequestId, options);
 
-  EXPECT_CALL(*media_observer_.get(), OnCaptureDevicesOpened(_, _, _, _));
-
   WaitForResult();
 
   // Check the latest generated stream.
@@ -236,10 +235,10 @@
   EXPECT_EQ(host_->NumberOfStreams(), 1u);
 
   // Generate second stream.
+  SetupFakeUI(true);
   EXPECT_CALL(*host_, OnStreamGenerated(kRenderId, kPageRequestId + 1, 0, 1));
   host_->OnGenerateStream(kPageRequestId+1, options);
 
-  EXPECT_CALL(*media_observer_.get(), OnCaptureDevicesOpened(_, _, _, _));
 
   WaitForResult();
 
@@ -252,16 +251,13 @@
   EXPECT_NE(label1, label2);
 
   // Check that we now have two opened streams.
-  EXPECT_EQ(host_->NumberOfStreams(), 2u);
+  EXPECT_EQ(2u, host_->NumberOfStreams());
 
   // Generate third stream.
+  SetupFakeUI(true);
   EXPECT_CALL(*host_, OnStreamGenerated(kRenderId, kPageRequestId + 2, 0, 1));
   host_->OnGenerateStream(kPageRequestId+2, options);
 
-  EXPECT_CALL(*media_observer_.get(), OnCaptureDevicesOpened(_, _, _, _));
-  EXPECT_CALL(*media_observer_.get(), OnCaptureDevicesClosed(_, _, _))
-      .Times(3);
-
   WaitForResult();
 
   // Check the latest generated stream.
@@ -285,10 +281,8 @@
 TEST_F(MediaStreamDispatcherHostTest, FailOpenVideoDevice) {
   StreamOptions options(MEDIA_NO_SERVICE, MEDIA_DEVICE_VIDEO_CAPTURE);
 
-  EXPECT_CALL(*host_, GetMediaObserver())
-      .WillRepeatedly(Return(media_observer_.get()));
   media::FakeVideoCaptureDevice::SetFailNextCreate();
-  media_stream_manager_->UseFakeDevice();
+  SetupFakeUI(false);
   host_->OnGenerateStream(kPageRequestId, options);
   EXPECT_CALL(*host_, OnStreamGenerationFailed(kRenderId, kPageRequestId));
   WaitForResult();
@@ -297,9 +291,6 @@
 TEST_F(MediaStreamDispatcherHostTest, CancelPendingStreamsOnChannelClosing) {
   StreamOptions options(MEDIA_NO_SERVICE, MEDIA_DEVICE_VIDEO_CAPTURE);
 
-  EXPECT_CALL(*host_, GetMediaObserver())
-      .WillRepeatedly(Return(media_observer_.get()));
-
   // Create multiple GenerateStream requests.
   size_t streams = 5;
   for (size_t i = 1; i <= streams; ++i) {
@@ -317,14 +308,11 @@
 TEST_F(MediaStreamDispatcherHostTest, StopGeneratedStreamsOnChannelClosing) {
   StreamOptions options(MEDIA_NO_SERVICE, MEDIA_DEVICE_VIDEO_CAPTURE);
 
-  EXPECT_CALL(*host_, GetMediaObserver())
-      .WillRepeatedly(Return(media_observer_.get()));
-
   // Create first group of streams.
   size_t generated_streams = 3;
   for (size_t i = 0; i < generated_streams; ++i) {
+    SetupFakeUI(true);
     EXPECT_CALL(*host_, OnStreamGenerated(kRenderId, kPageRequestId + i, 0, 1));
-    EXPECT_CALL(*media_observer_.get(), OnCaptureDevicesOpened(_, _, _, _));
     host_->OnGenerateStream(kPageRequestId + i, options);
 
     // Wait until the stream is generated.
@@ -333,10 +321,10 @@
   EXPECT_EQ(host_->NumberOfStreams(), generated_streams);
 
   // Calling OnChannelClosing() to cancel all the pending/generated streams.
-  EXPECT_CALL(*media_observer_.get(), OnCaptureDevicesClosed(_, _, _))
-      .Times(3);
   host_->OnChannelClosing();
 
+  message_loop_->RunUntilIdle();
+
   // Streams should have been cleaned up.
   EXPECT_EQ(host_->NumberOfStreams(), 0u);
 }
@@ -344,18 +332,16 @@
 TEST_F(MediaStreamDispatcherHostTest, CloseFromUI) {
   StreamOptions options(MEDIA_NO_SERVICE, MEDIA_DEVICE_VIDEO_CAPTURE);
 
-  EXPECT_CALL(*host_, GetMediaObserver())
-      .WillRepeatedly(Return(media_observer_.get()));
+  base::Closure close_callback;
+  scoped_ptr<MockMediaStreamUI> stream_ui(new MockMediaStreamUI());
+  EXPECT_CALL(*stream_ui, OnStarted(_))
+    .WillOnce(SaveArg<0>(&close_callback));
+  media_stream_manager_->UseFakeUI(stream_ui.PassAs<MediaStreamUI>());
+
   EXPECT_CALL(*host_, OnStreamGenerated(kRenderId, kPageRequestId, 0, 1));
   EXPECT_CALL(*host_, OnStreamGenerationFailed(kRenderId, kPageRequestId));
   host_->OnGenerateStream(kPageRequestId, options);
 
-  base::Closure close_callback;
-
-  EXPECT_CALL(*media_observer_.get(), OnCaptureDevicesOpened(_, _, _, _))
-      .WillOnce(SaveArg<3>(&close_callback));
-  EXPECT_CALL(*media_observer_.get(), OnCaptureDevicesClosed(_, _, _));
-
   WaitForResult();
 
   EXPECT_EQ(host_->audio_devices_.size(), 0u);
diff --git a/content/browser/renderer_host/media/media_stream_manager.cc b/content/browser/renderer_host/media/media_stream_manager.cc
index a640dc5..1d63262 100644
--- a/content/browser/renderer_host/media/media_stream_manager.cc
+++ b/content/browser/renderer_host/media/media_stream_manager.cc
@@ -147,8 +147,7 @@
 }
 
 MediaStreamManager::MediaStreamManager(media::AudioManager* audio_manager)
-    : ALLOW_THIS_IN_INITIALIZER_LIST(
-          ui_controller_(new MediaStreamUIController(this))),
+    : ui_controller_(new MediaStreamUIController(this)),
       audio_manager_(audio_manager),
       monitoring_started_(false),
       io_loop_(NULL),
@@ -343,7 +342,7 @@
                             MEDIA_REQUEST_STATE_CLOSING);
         }
       }
-      NotifyDevicesClosed(*request);
+      NotifyUIDevicesClosed(label);
     }
 
     // If request isn't complete, notify the UI on the cancellation. And it
@@ -458,23 +457,14 @@
   return label;
 }
 
-void MediaStreamManager::NotifyUIDevicesOpened(
-    const std::string& label,
-    int render_process_id,
-    int render_view_id,
-    const MediaStreamDevices& devices) {
+void MediaStreamManager::NotifyUIDevicesOpened(const std::string& label) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-  ui_controller_->NotifyUIIndicatorDevicesOpened(
-      label, render_process_id, render_view_id, devices);
+  ui_controller_->NotifyUIIndicatorDevicesOpened(label);
 }
 
-void MediaStreamManager::NotifyUIDevicesClosed(
-    int render_process_id,
-    int render_view_id,
-    const MediaStreamDevices& devices) {
+void MediaStreamManager::NotifyUIDevicesClosed(const std::string& label) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-  ui_controller_->NotifyUIIndicatorDevicesClosed(
-      render_process_id, render_view_id, devices);
+  ui_controller_->NotifyUIIndicatorDevicesClosed(label);
 }
 
 void MediaStreamManager::SendCachedDeviceList(
@@ -508,7 +498,7 @@
 }
 
 void MediaStreamManager::StopMonitoring() {
-  DCHECK_EQ(MessageLoop::current(), io_loop_);
+  DCHECK_EQ(base::MessageLoop::current(), io_loop_);
   if (monitoring_started_) {
     base::SystemMonitor::Get()->RemoveDevicesChangedObserver(this);
     monitoring_started_ = false;
@@ -518,7 +508,7 @@
 }
 
 void MediaStreamManager::ClearEnumerationCache(EnumerationCache* cache) {
-  DCHECK_EQ(MessageLoop::current(), io_loop_);
+  DCHECK_EQ(base::MessageLoop::current(), io_loop_);
   cache->valid = false;
 }
 
@@ -564,6 +554,8 @@
     screen_capture_active_ = false;
   }
 
+  NotifyUIDevicesClosed(it->first);
+
   requests_.erase(it);
 }
 
@@ -615,7 +607,7 @@
 
 void MediaStreamManager::InitializeDeviceManagersOnIOThread() {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-  if (device_thread_.get())
+  if (device_thread_)
     return;
 
   device_thread_.reset(new base::Thread("MediaStreamDeviceThread"));
@@ -633,7 +625,7 @@
 
   // We want to be notified of IO message loop destruction to delete the thread
   // and the device managers.
-  io_loop_ = MessageLoop::current();
+  io_loop_ = base::MessageLoop::current();
   io_loop_->AddDestructionObserver(this);
 }
 
@@ -717,7 +709,7 @@
       }
 
       request->requester->StreamGenerated(label, audio_devices, video_devices);
-      NotifyDevicesOpened(label, *request);
+      NotifyUIDevicesOpened(label);
       break;
     }
     default:
@@ -995,13 +987,17 @@
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
   video_capture_manager()->UseFakeDevice();
   audio_input_device_manager()->UseFakeDevice();
-  ui_controller_->UseFakeUI();
+  UseFakeUI(scoped_ptr<MediaStreamUI>());
+}
+
+void MediaStreamManager::UseFakeUI(scoped_ptr<MediaStreamUI> fake_ui) {
+  ui_controller_->UseFakeUI(fake_ui.Pass());
 }
 
 void MediaStreamManager::WillDestroyCurrentMessageLoop() {
-  DCHECK_EQ(MessageLoop::current(), io_loop_);
+  DCHECK_EQ(base::MessageLoop::current(), io_loop_);
   DCHECK(requests_.empty());
-  if (device_thread_.get()) {
+  if (device_thread_) {
     StopMonitoring();
 
     video_capture_manager_->Unregister();
@@ -1015,37 +1011,6 @@
   ui_controller_.reset();
 }
 
-void MediaStreamManager::NotifyDevicesOpened(const std::string& label,
-                                             const DeviceRequest& request) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-  MediaStreamDevices opened_devices;
-  DevicesFromRequest(request, &opened_devices);
-  if (opened_devices.empty())
-    return;
-
-  NotifyUIDevicesOpened(
-      label, request.render_process_id, request.render_view_id, opened_devices);
-}
-
-void MediaStreamManager::NotifyDevicesClosed(const DeviceRequest& request) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-  MediaStreamDevices closed_devices;
-  DevicesFromRequest(request, &closed_devices);
-  if (closed_devices.empty())
-    return;
-
-  NotifyUIDevicesClosed(
-      request.render_process_id, request.render_view_id, closed_devices);
-}
-
-void MediaStreamManager::DevicesFromRequest(
-    const DeviceRequest& request, MediaStreamDevices* devices) {
-  for (StreamDeviceInfoArray::const_iterator it = request.devices.begin();
-       it != request.devices.end(); ++it) {
-    devices->push_back(it->device);
-  }
-}
-
 void MediaStreamManager::NotifyDevicesChanged(
     MediaStreamType stream_type,
     const StreamDeviceInfoArray& devices) {
diff --git a/content/browser/renderer_host/media/media_stream_manager.h b/content/browser/renderer_host/media/media_stream_manager.h
index 205ddb2..acde644 100644
--- a/content/browser/renderer_host/media/media_stream_manager.h
+++ b/content/browser/renderer_host/media/media_stream_manager.h
@@ -58,7 +58,7 @@
 // MediaStreamManager::Listener.
 class CONTENT_EXPORT MediaStreamManager
     : public MediaStreamProviderListener,
-      public MessageLoop::DestructionObserver,
+      public base::MessageLoop::DestructionObserver,
       public SettingsRequester,
       public base::SystemMonitor::DevicesChangedObserver {
  public:
@@ -125,15 +125,10 @@
   // Signals the UI that the devices are opened.
   // Users are responsible for calling NotifyUIDevicesClosed when the devices
   // are not used anymore, otherwise UI will leak.
-  void NotifyUIDevicesOpened(const std::string& label,
-                             int render_process_id,
-                             int render_view_id,
-                             const MediaStreamDevices& devices);
+  void NotifyUIDevicesOpened(const std::string& label);
 
   // Signals the UI that the devices are being closed.
-  void NotifyUIDevicesClosed(int render_process_id,
-                             int render_view_id,
-                             const MediaStreamDevices& devices);
+  void NotifyUIDevicesClosed(const std::string& label);
 
   // Implements MediaStreamProviderListener.
   virtual void Opened(MediaStreamType stream_type,
@@ -161,6 +156,10 @@
   // devices, which is needed for server based testing.
   void UseFakeDevice();
 
+  // Called by the unittests to specify fake UI that should be used for next
+  // generated stream.
+  void UseFakeUI(scoped_ptr<MediaStreamUI> fake_ui);
+
   // This object gets deleted on the UI thread after the IO thread has been
   // destroyed. So we need to know when IO thread is being destroyed so that
   // we can delete VideoCaptureManager and AudioInputDeviceManager.
@@ -185,14 +184,6 @@
   // thread and registers this as a listener with the device managers.
   void InitializeDeviceManagersOnIOThread();
 
-  // Helpers for signaling the media observer that new capture devices are
-  // opened/closed.
-  void NotifyDevicesOpened(const std::string& label,
-                           const DeviceRequest& request);
-  void NotifyDevicesClosed(const DeviceRequest& request);
-  void DevicesFromRequest(const DeviceRequest& request,
-                          MediaStreamDevices* devices);
-
   // Helper for sending up-to-date device lists to media observer when a
   // capture device is plugged in or unplugged.
   void NotifyDevicesChanged(MediaStreamType stream_type,
@@ -249,7 +240,7 @@
 
   // Hold a pointer to the IO loop to check we delete the device thread and
   // managers on the right thread.
-  MessageLoop* io_loop_;
+  base::MessageLoop* io_loop_;
 
   bool screen_capture_active_;
 
diff --git a/content/browser/renderer_host/media/media_stream_manager_unittest.cc b/content/browser/renderer_host/media/media_stream_manager_unittest.cc
index 27c1dea..a515a36 100644
--- a/content/browser/renderer_host/media/media_stream_manager_unittest.cc
+++ b/content/browser/renderer_host/media/media_stream_manager_unittest.cc
@@ -67,14 +67,14 @@
   void ResponseCallback(const std::string& label,
                         const MediaStreamDevices& devices) {
     Response(label);
-    message_loop_->PostTask(FROM_HERE, MessageLoop::QuitClosure());
+    message_loop_->PostTask(FROM_HERE, base::MessageLoop::QuitClosure());
   }
 
   void WaitForResult() { message_loop_->Run(); }
 
  protected:
   virtual void SetUp() {
-    message_loop_.reset(new MessageLoop(MessageLoop::TYPE_IO));
+    message_loop_.reset(new base::MessageLoop(base::MessageLoop::TYPE_IO));
     ui_thread_.reset(new BrowserThreadImpl(BrowserThread::UI,
                                            message_loop_.get()));
     io_thread_.reset(new BrowserThreadImpl(BrowserThread::IO,
@@ -111,7 +111,7 @@
                                                          callback);
   }
 
-  scoped_ptr<MessageLoop> message_loop_;
+  scoped_ptr<base::MessageLoop> message_loop_;
   scoped_ptr<BrowserThreadImpl> ui_thread_;
   scoped_ptr<BrowserThreadImpl> io_thread_;
   scoped_ptr<media::AudioManager> audio_manager_;
diff --git a/content/browser/renderer_host/media/media_stream_ui_controller.cc b/content/browser/renderer_host/media/media_stream_ui_controller.cc
index 63c0264..115bfd6 100644
--- a/content/browser/renderer_host/media/media_stream_ui_controller.cc
+++ b/content/browser/renderer_host/media/media_stream_ui_controller.cc
@@ -62,7 +62,7 @@
 
   // Tab may have gone away.
   if (!host || !host->GetDelegate()) {
-    callback.Run(MediaStreamDevices());
+    callback.Run(MediaStreamDevices(), scoped_ptr<MediaStreamUI>());
     return;
   }
 
@@ -73,13 +73,13 @@
 
 MediaStreamUIController::MediaStreamUIController(SettingsRequester* requester)
     : requester_(requester),
-      use_fake_ui_(false),
-      weak_ptr_factory_(this) {
+      use_fake_ui_(false) {
   DCHECK(requester_);
 }
 
 MediaStreamUIController::~MediaStreamUIController() {
   DCHECK(requests_.empty());
+  DCHECK(stream_indicators_.empty());
 }
 
 void MediaStreamUIController::MakeUIRequest(
@@ -135,16 +135,25 @@
     // page.
     ProcessNextRequestForView(render_process_id, render_view_id);
   }
+
+  NotifyUIIndicatorDevicesClosed(label);
 }
 
-void MediaStreamUIController::PostResponse(
+void MediaStreamUIController::ProcessAccessRequestResponse(
     const std::string& label,
-    const MediaStreamDevices& devices) {
+    const MediaStreamDevices& devices,
+    scoped_ptr<MediaStreamUI> stream_ui) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
   UIRequests::iterator request_iter = requests_.find(label);
   // Return if the request has been removed.
-  if (request_iter == requests_.end())
+  if (request_iter == requests_.end()) {
+    if (stream_ui) {
+      BrowserThread::DeleteSoon(BrowserThread::UI, FROM_HERE,
+                                stream_ui.release());
+    }
     return;
+  }
 
   DCHECK(requester_);
   scoped_ptr<MediaStreamRequestForUI> request(request_iter->second);
@@ -155,7 +164,12 @@
   ProcessNextRequestForView(request->render_process_id,
                             request->render_view_id);
 
-  if (devices.size() > 0) {
+  if (!devices.empty()) {
+    if (stream_ui) {
+      DCHECK(stream_indicators_.find(label) == stream_indicators_.end());
+      stream_indicators_[label] = stream_ui.release();
+    }
+
     // Build a list of "full" device objects for the accepted devices.
     StreamDeviceInfoArray device_list;
     // TODO(xians): figure out if it is all right to hard code in_use to false,
@@ -169,49 +183,47 @@
 
     requester_->DevicesAccepted(label, device_list);
   } else {
+    DCHECK(!stream_ui);
     requester_->SettingsError(label);
   }
 }
 
 void MediaStreamUIController::NotifyUIIndicatorDevicesOpened(
-    const std::string& label,
-    int render_process_id,
-    int render_view_id,
-    const MediaStreamDevices& devices) {
+    const std::string& label) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-  DCHECK(!devices.empty());
-  MediaObserver* media_observer =
-      GetContentClient()->browser()->GetMediaObserver();
-  if (media_observer == NULL)
-    return;
 
-  media_observer->OnCaptureDevicesOpened(
-      render_process_id, render_view_id, devices,
-      media::BindToLoop(
-          base::MessageLoopProxy::current(),
-          base::Bind(&MediaStreamUIController::OnStopStreamFromUI,
-                     weak_ptr_factory_.GetWeakPtr(), label)));
+  IndicatorsMap::iterator it = stream_indicators_.find(label);
+  if (it != stream_indicators_.end()) {
+    base::Closure stop_callback = media::BindToLoop(
+        base::MessageLoopProxy::current(),
+        base::Bind(&MediaStreamUIController::OnStopStreamFromUI,
+                   base::Unretained(this), label));
+
+    // base::Unretained is safe here because the target can be deleted only on
+    // UI thread when posted from IO thread (see
+    // NotifyUIIndicatorDevicesClosed()).
+    BrowserThread::PostTask(
+        BrowserThread::UI, FROM_HERE,
+        base::Bind(&MediaStreamUI::OnStarted,
+                   base::Unretained(it->second), stop_callback));
+  }
 }
 
 void MediaStreamUIController::NotifyUIIndicatorDevicesClosed(
-    int render_process_id,
-    int render_view_id,
-    const MediaStreamDevices& devices) {
+    const std::string& label) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-  DCHECK(!devices.empty());
-  MediaObserver* media_observer =
-      GetContentClient()->browser()->GetMediaObserver();
-  if (media_observer == NULL)
-    return;
 
-  media_observer->OnCaptureDevicesClosed(render_process_id,
-                                         render_view_id,
-                                         devices);
+  IndicatorsMap::iterator indicator = stream_indicators_.find(label);
+  if (indicator != stream_indicators_.end()) {
+    BrowserThread::DeleteSoon(BrowserThread::UI, FROM_HERE, indicator->second);
+    stream_indicators_.erase(indicator);
+  }
 }
 
-void MediaStreamUIController::UseFakeUI() {
+void MediaStreamUIController::UseFakeUI(scoped_ptr<MediaStreamUI> fake_ui) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
   use_fake_ui_ = true;
+  fake_ui_ = fake_ui.Pass();
 }
 
 bool MediaStreamUIController::IsUIBusy(int render_process_id,
@@ -246,7 +258,7 @@
   if (next_request_label.empty())
     return;
 
-  if (use_fake_ui_) {
+  if (fake_ui_) {
     PostRequestToFakeUI(next_request_label);
   } else {
     PostRequestToUI(next_request_label);
@@ -256,6 +268,7 @@
 void MediaStreamUIController::PostRequestToUI(const std::string& label) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
   UIRequests::iterator request_iter = requests_.find(label);
+
   if (request_iter == requests_.end()) {
     NOTREACHED();
     return;
@@ -266,11 +279,11 @@
   request->posted_task = true;
 
   BrowserThread::PostTask(
-      BrowserThread::UI, FROM_HERE,
-      base::Bind(&ProceedMediaAccessPermission, *request, media::BindToLoop(
+      BrowserThread::UI, FROM_HERE, base::Bind(
+          &ProceedMediaAccessPermission, *request, media::BindToLoop(
           base::MessageLoopProxy::current(), base::Bind(
-              &MediaStreamUIController::PostResponse,
-              weak_ptr_factory_.GetWeakPtr(), label))));
+              &MediaStreamUIController::ProcessAccessRequestResponse,
+              base::Unretained(this), label))));
 }
 
 void MediaStreamUIController::PostRequestToFakeUI(const std::string& label) {
@@ -304,13 +317,20 @@
 
   BrowserThread::PostTask(
       BrowserThread::IO, FROM_HERE,
-      base::Bind(&MediaStreamUIController::PostResponse,
-                 weak_ptr_factory_.GetWeakPtr(), label, devices_to_use));
+      base::Bind(&MediaStreamUIController::ProcessAccessRequestResponse,
+                 base::Unretained(this), label, devices_to_use,
+                 base::Passed(&fake_ui_)));
 }
 
 void MediaStreamUIController::OnStopStreamFromUI(const std::string& label) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-  requester_->StopStreamFromUI(label);
+  // It's safe to base::Unretained() here because |requester_| references
+  // MediaStreamManager which always outlives IO thread.
+  //
+  // TODO(sergeyu): Refactor this code to not rely on what |requester_| is.
+  BrowserThread::PostTask(
+      BrowserThread::IO, FROM_HERE,
+      base::Bind(&SettingsRequester::StopStreamFromUI,
+                 base::Unretained(requester_), label));
 }
 
 }  // namespace content
diff --git a/content/browser/renderer_host/media/media_stream_ui_controller.h b/content/browser/renderer_host/media/media_stream_ui_controller.h
index 72bdc6d..6d14e83 100644
--- a/content/browser/renderer_host/media/media_stream_ui_controller.h
+++ b/content/browser/renderer_host/media/media_stream_ui_controller.h
@@ -21,7 +21,6 @@
 #include <string>
 
 #include "base/basictypes.h"
-#include "base/memory/weak_ptr.h"
 #include "content/browser/renderer_host/media/media_stream_provider.h"
 #include "content/public/browser/web_contents_delegate.h"
 
@@ -52,34 +51,20 @@
   // user has no action for the media stream InfoBar.
   void CancelUIRequest(const std::string& label);
 
-  // Called by the InfoBar when the user grants/denies access to some devices
-  // to the webpage. This is placed here, so the request can be cleared from the
-  // list of pending requests, instead of letting the InfoBar itself respond to
-  // the requester. An empty list of devices means that access has been denied.
-  // This method must be called on the IO thread.
-  void PostResponse(const std::string& label,
-                    const MediaStreamDevices& devices);
-
   // Called to signal the UI indicator that the devices are opened.
-  void NotifyUIIndicatorDevicesOpened(
-      const std::string& label,
-      int render_process_id,
-      int render_view_id,
-      const MediaStreamDevices& devices);
+  void NotifyUIIndicatorDevicesOpened(const std::string& label);
 
   // Called to signal the UI indicator that the devices are closed.
-  void NotifyUIIndicatorDevicesClosed(
-      int render_process_id,
-      int render_view_id,
-      const MediaStreamDevices& devices);
+  void NotifyUIIndicatorDevicesClosed(const std::string& label);
 
   // Used for testing only. This function is called to use faked UI, which is
   // needed for server based tests. The first non-opened device(s) will be
   // picked.
-  void UseFakeUI();
+  void UseFakeUI(scoped_ptr<MediaStreamUI> fake_ui);
 
  private:
   typedef std::map<std::string, MediaStreamRequestForUI*> UIRequests;
+  typedef std::map<std::string, MediaStreamUI*> IndicatorsMap;
 
   // Returns true if the UI is already processing a request for this render
   // view.
@@ -95,6 +80,11 @@
   // Posts a request to fake UI which is used for testing purpose.
   void PostRequestToFakeUI(const std::string& label);
 
+  // Callback handler for WebContents::RequestMediaAccessPermission().
+  void ProcessAccessRequestResponse(const std::string& label,
+                                    const MediaStreamDevices& devices,
+                                    scoped_ptr<MediaStreamUI> stream_ui);
+
   // Callback for UI called when user requests a stream to be stopped.
   void OnStopStreamFromUI(const std::string& label);
 
@@ -103,8 +93,10 @@
 
   // See comment above for method UseFakeUI. Used for automated testing.
   bool use_fake_ui_;
+  scoped_ptr<MediaStreamUI> fake_ui_;
 
-  base::WeakPtrFactory<MediaStreamUIController> weak_ptr_factory_;
+  // Container MediaStreamUI objects for currently active streams.
+  IndicatorsMap stream_indicators_;
 
   DISALLOW_COPY_AND_ASSIGN(MediaStreamUIController);
 };
diff --git a/content/browser/renderer_host/media/media_stream_ui_controller_unittest.cc b/content/browser/renderer_host/media/media_stream_ui_controller_unittest.cc
index 695bdac..708fe7a 100644
--- a/content/browser/renderer_host/media/media_stream_ui_controller_unittest.cc
+++ b/content/browser/renderer_host/media/media_stream_ui_controller_unittest.cc
@@ -43,7 +43,7 @@
 
  protected:
   virtual void SetUp() {
-    message_loop_.reset(new MessageLoop(MessageLoop::TYPE_IO));
+    message_loop_.reset(new base::MessageLoop(base::MessageLoop::TYPE_IO));
     ui_thread_.reset(new BrowserThreadImpl(BrowserThread::UI,
                                            message_loop_.get()));
     io_thread_.reset(new BrowserThreadImpl(BrowserThread::IO,
@@ -71,7 +71,7 @@
                                   std::string());
   }
 
-  scoped_ptr<MessageLoop> message_loop_;
+  scoped_ptr<base::MessageLoop> message_loop_;
   scoped_ptr<BrowserThreadImpl> ui_thread_;
   scoped_ptr<BrowserThreadImpl> io_thread_;
   scoped_ptr<MediaStreamUIController> ui_controller_;
@@ -98,17 +98,21 @@
 }
 
 TEST_F(MediaStreamDeviceUIControllerTest, HandleRequestUsingFakeUI) {
-  ui_controller_->UseFakeUI();
+  ui_controller_->UseFakeUI(scoped_ptr<MediaStreamUI>());
 
   const std::string label = "label";
   CreateDummyRequest(label, true, true);
 
   // Remove the current request, it should not crash.
   EXPECT_CALL(*this, DevicesAccepted(label, _));
+
+  message_loop_->RunUntilIdle();
+
+  ui_controller_->NotifyUIIndicatorDevicesClosed(label);
 }
 
 TEST_F(MediaStreamDeviceUIControllerTest, CreateRequestsAndCancelTheFirst) {
-  ui_controller_->UseFakeUI();
+  ui_controller_->UseFakeUI(scoped_ptr<MediaStreamUI>());
 
   // Create the first audio request.
   const std::string label_1 = "label_1";
@@ -128,10 +132,15 @@
   // We should get callbacks from the rest of the requests.
   EXPECT_CALL(*this, DevicesAccepted(label_2, _));
   EXPECT_CALL(*this, DevicesAccepted(label_3, _));
+
+  message_loop_->RunUntilIdle();
+
+  ui_controller_->NotifyUIIndicatorDevicesClosed(label_2);
+  ui_controller_->NotifyUIIndicatorDevicesClosed(label_3);
 }
 
 TEST_F(MediaStreamDeviceUIControllerTest, CreateRequestsAndCancelTheLast) {
-  ui_controller_->UseFakeUI();
+  ui_controller_->UseFakeUI(scoped_ptr<MediaStreamUI>());
 
   // Create the first audio request.
   const std::string label_1 = "label_1";
@@ -151,6 +160,11 @@
   // We should get callbacks from the rest of the requests.
   EXPECT_CALL(*this, DevicesAccepted(label_1, _));
   EXPECT_CALL(*this, DevicesAccepted(label_2, _));
+
+  message_loop_->RunUntilIdle();
+
+  ui_controller_->NotifyUIIndicatorDevicesClosed(label_1);
+  ui_controller_->NotifyUIIndicatorDevicesClosed(label_2);
 }
 
 }  // namespace content
diff --git a/content/browser/renderer_host/media/mock_media_observer.h b/content/browser/renderer_host/media/mock_media_observer.h
index d4c297c..54f419e 100644
--- a/content/browser/renderer_host/media/mock_media_observer.h
+++ b/content/browser/renderer_host/media/mock_media_observer.h
@@ -20,13 +20,6 @@
   MockMediaObserver();
   virtual ~MockMediaObserver();
 
-  MOCK_METHOD4(OnCaptureDevicesOpened,
-               void(int render_process_id, int render_view_id,
-                    const MediaStreamDevices& devices,
-                    const base::Closure& close_callback));
-  MOCK_METHOD3(OnCaptureDevicesClosed,
-               void(int render_process_id, int render_view_id,
-                    const MediaStreamDevices& devices));
   MOCK_METHOD1(OnAudioCaptureDevicesChanged,
                void(const MediaStreamDevices& devices));
   MOCK_METHOD1(OnVideoCaptureDevicesChanged,
diff --git a/content/browser/renderer_host/media/peer_connection_tracker_host.cc b/content/browser/renderer_host/media/peer_connection_tracker_host.cc
index 68314b4..4ba1a0a 100644
--- a/content/browser/renderer_host/media/peer_connection_tracker_host.cc
+++ b/content/browser/renderer_host/media/peer_connection_tracker_host.cc
@@ -40,7 +40,7 @@
 
 void PeerConnectionTrackerHost::OnAddPeerConnection(
     const PeerConnectionInfo& info) {
-  WebRTCInternals::GetInstance()->AddPeerConnection(
+  WebRTCInternals::GetInstance()->OnAddPeerConnection(
       render_process_id_,
       base::GetProcId(peer_handle()),
       info.lid,
@@ -50,13 +50,13 @@
 }
 
 void PeerConnectionTrackerHost::OnRemovePeerConnection(int lid) {
-  WebRTCInternals::GetInstance()->RemovePeerConnection(
+  WebRTCInternals::GetInstance()->OnRemovePeerConnection(
       base::GetProcId(peer_handle()), lid);
 }
 
 void PeerConnectionTrackerHost::OnUpdatePeerConnection(
     int lid, const std::string& type, const std::string& value) {
-  WebRTCInternals::GetInstance()->UpdatePeerConnection(
+  WebRTCInternals::GetInstance()->OnUpdatePeerConnection(
       base::GetProcId(peer_handle()),
       lid,
       type,
@@ -65,7 +65,7 @@
 
 void PeerConnectionTrackerHost::OnAddStats(int lid,
                                            const base::ListValue& value) {
-  WebRTCInternals::GetInstance()->AddStats(
+  WebRTCInternals::GetInstance()->OnAddStats(
       base::GetProcId(peer_handle()), lid, value);
 }
 
diff --git a/content/browser/renderer_host/media/video_capture_buffer_pool.cc b/content/browser/renderer_host/media/video_capture_buffer_pool.cc
index d702201..8a6a0f8 100644
--- a/content/browser/renderer_host/media/video_capture_buffer_pool.cc
+++ b/content/browser/renderer_host/media/video_capture_buffer_pool.cc
@@ -65,7 +65,7 @@
 
   Buffer* buffer = buffers_[buffer_id];
 
-  CHECK_GE(buffer->shared_memory.created_size(), GetMemorySize());
+  CHECK_GE(buffer->shared_memory.requested_size(), GetMemorySize());
 
   // Complete the reservation.
   buffer->held_by_producer = true;
diff --git a/content/browser/renderer_host/media/video_capture_controller.cc b/content/browser/renderer_host/media/video_capture_controller.cc
index 879317b..b82b796 100644
--- a/content/browser/renderer_host/media/video_capture_controller.cc
+++ b/content/browser/renderer_host/media/video_capture_controller.cc
@@ -190,7 +190,9 @@
   controller_clients_.remove(client);
 
   // No more clients. Stop device.
-  if (controller_clients_.empty() && state_ == VIDEO_CAPTURE_STATE_STARTED) {
+  if (controller_clients_.empty() &&
+      (state_ == VIDEO_CAPTURE_STATE_STARTED ||
+       state_ == VIDEO_CAPTURE_STATE_ERROR)) {
     video_capture_manager_->Stop(session_id,
         base::Bind(&VideoCaptureController::OnDeviceStopped, this));
     frame_info_available_ = false;
@@ -209,7 +211,7 @@
 
   if (client) {
     client->session_closed = true;
-    client->event_handler->OnPaused(client->controller_id);
+    client->event_handler->OnEnded(client->controller_id);
   }
 }
 
@@ -257,9 +259,9 @@
     int rotation,
     bool flip_vert,
     bool flip_horiz) {
-  DCHECK (frame_info_.color == media::VideoCaptureCapability::kI420 ||
-          frame_info_.color == media::VideoCaptureCapability::kYV12 ||
-          (rotation == 0 && !flip_vert && !flip_horiz));
+  DCHECK(frame_info_.color == media::VideoCaptureCapability::kI420 ||
+         frame_info_.color == media::VideoCaptureCapability::kYV12 ||
+         (rotation == 0 && !flip_vert && !flip_horiz));
 
   scoped_refptr<media::VideoFrame> dst;
   {
@@ -396,6 +398,7 @@
   const int kYPlane = media::VideoFrame::kYPlane;
   const int kUPlane = media::VideoFrame::kUPlane;
   const int kVPlane = media::VideoFrame::kVPlane;
+  const int kAPlane = media::VideoFrame::kAPlane;
   const int kRGBPlane = media::VideoFrame::kRGBPlane;
 
   // Do color conversion from the camera format to I420.
@@ -428,6 +431,26 @@
                         target);
       break;
     }
+    case media::VideoFrame::YV12A: {
+      DCHECK(!chopped_width_ && !chopped_height_);
+      media::CopyYPlane(frame->data(kYPlane),
+                        frame->stride(kYPlane),
+                        frame->rows(kYPlane),
+                        target);
+      media::CopyUPlane(frame->data(kUPlane),
+                        frame->stride(kUPlane),
+                        frame->rows(kUPlane),
+                        target);
+      media::CopyVPlane(frame->data(kVPlane),
+                        frame->stride(kVPlane),
+                        frame->rows(kVPlane),
+                        target);
+      media::CopyAPlane(frame->data(kAPlane),
+                        frame->stride(kAPlane),
+                        frame->rows(kAPlane),
+                        target);
+      break;
+    }
     case media::VideoFrame::RGB32: {
       media::ConvertRGB32ToYUV(frame->data(kRGBPlane),
                                target->data(kYPlane),
diff --git a/content/browser/renderer_host/media/video_capture_controller_event_handler.h b/content/browser/renderer_host/media/video_capture_controller_event_handler.h
index 58f963c..35ab3ef 100644
--- a/content/browser/renderer_host/media/video_capture_controller_event_handler.h
+++ b/content/browser/renderer_host/media/video_capture_controller_event_handler.h
@@ -45,8 +45,8 @@
                            int height,
                            int frame_rate) = 0;
 
-  // The capture session has been paused. No more frame will be sent.
-  virtual void OnPaused(const VideoCaptureControllerID& id) = 0;
+  // The capture session has ended and no more frames will be sent.
+  virtual void OnEnded(const VideoCaptureControllerID& id) = 0;
 
  protected:
   virtual ~VideoCaptureControllerEventHandler() {}
diff --git a/content/browser/renderer_host/media/video_capture_controller_unittest.cc b/content/browser/renderer_host/media/video_capture_controller_unittest.cc
index 14c8da1..544001f 100644
--- a/content/browser/renderer_host/media/video_capture_controller_unittest.cc
+++ b/content/browser/renderer_host/media/video_capture_controller_unittest.cc
@@ -36,21 +36,21 @@
   message_loop->PostTask(FROM_HERE,
       base::Bind(&VideoCaptureController::StopCapture,
                  controller, controller_id, controller_handler));
-  message_loop->PostTask(FROM_HERE, MessageLoop::QuitClosure());
+  message_loop->PostTask(FROM_HERE, base::MessageLoop::QuitClosure());
 }
 
 ACTION_P3(StopSession, controller, session_id, message_loop) {
   message_loop->PostTask(FROM_HERE,
       base::Bind(&VideoCaptureController::StopSession,
                  controller, session_id));
-  message_loop->PostTask(FROM_HERE, MessageLoop::QuitClosure());
+  message_loop->PostTask(FROM_HERE, base::MessageLoop::QuitClosure());
 }
 
 class MockVideoCaptureControllerEventHandler
     : public VideoCaptureControllerEventHandler {
  public:
   MockVideoCaptureControllerEventHandler(VideoCaptureController* controller,
-                                         MessageLoop* message_loop)
+                                         base::MessageLoop* message_loop)
       : controller_(controller),
         message_loop_(message_loop),
         controller_id_(kDeviceId),
@@ -61,7 +61,7 @@
   MOCK_METHOD1(DoBufferCreated, void(const VideoCaptureControllerID&));
   MOCK_METHOD1(DoBufferReady, void(const VideoCaptureControllerID&));
   MOCK_METHOD1(DoFrameInfo, void(const VideoCaptureControllerID&));
-  MOCK_METHOD1(DoPaused, void(const VideoCaptureControllerID&));
+  MOCK_METHOD1(DoEnded, void(const VideoCaptureControllerID&));
 
   virtual void OnError(const VideoCaptureControllerID& id) OVERRIDE {}
   virtual void OnBufferCreated(const VideoCaptureControllerID& id,
@@ -86,13 +86,13 @@
     EXPECT_EQ(id, controller_id_);
     DoFrameInfo(id);
   }
-  virtual void OnPaused(const VideoCaptureControllerID& id) OVERRIDE {
+  virtual void OnEnded(const VideoCaptureControllerID& id) OVERRIDE {
     EXPECT_EQ(id, controller_id_);
-    DoPaused(id);
+    DoEnded(id);
   }
 
   scoped_refptr<VideoCaptureController> controller_;
-  MessageLoop* message_loop_;
+  base::MessageLoop* message_loop_;
   VideoCaptureControllerID controller_id_;
   base::ProcessHandle process_handle_;
 };
@@ -148,7 +148,7 @@
 
  protected:
   virtual void SetUp() OVERRIDE {
-    message_loop_.reset(new MessageLoop(MessageLoop::TYPE_IO));
+    message_loop_.reset(new base::MessageLoop(base::MessageLoop::TYPE_IO));
     file_thread_.reset(new BrowserThreadImpl(BrowserThread::FILE,
                                              message_loop_.get()));
     io_thread_.reset(new BrowserThreadImpl(BrowserThread::IO,
@@ -164,7 +164,7 @@
 
   virtual void TearDown() OVERRIDE {}
 
-  scoped_ptr<MessageLoop> message_loop_;
+  scoped_ptr<base::MessageLoop> message_loop_;
   scoped_ptr<BrowserThreadImpl> file_thread_;
   scoped_ptr<BrowserThreadImpl> io_thread_;
   scoped_refptr<MockVideoCaptureManager> vcm_;
@@ -240,7 +240,7 @@
                             vcm_->video_session_id_,
                             message_loop_.get()));
   EXPECT_CALL(*controller_handler_,
-              DoPaused(controller_handler_->controller_id_))
+              DoEnded(controller_handler_->controller_id_))
       .Times(1);
 
   controller_->StartCapture(controller_handler_->controller_id_,
@@ -254,8 +254,8 @@
   EXPECT_CALL(*controller_handler_,
               DoBufferReady(controller_handler_->controller_id_))
       .Times(0);
-  message_loop_->PostDelayedTask(
-      FROM_HERE, MessageLoop::QuitClosure(), base::TimeDelta::FromSeconds(1));
+  message_loop_->PostDelayedTask(FROM_HERE,
+      base::MessageLoop::QuitClosure(), base::TimeDelta::FromSeconds(1));
   message_loop_->Run();
 
   EXPECT_CALL(*vcm_,
diff --git a/content/browser/renderer_host/media/video_capture_host.cc b/content/browser/renderer_host/media/video_capture_host.cc
index 8e7231c..91d8f51 100644
--- a/content/browser/renderer_host/media/video_capture_host.cc
+++ b/content/browser/renderer_host/media/video_capture_host.cc
@@ -50,6 +50,7 @@
 
 // Implements VideoCaptureControllerEventHandler.
 void VideoCaptureHost::OnError(const VideoCaptureControllerID& controller_id) {
+  DVLOG(1) << "VideoCaptureHost::OnError";
   BrowserThread::PostTask(
       BrowserThread::IO, FROM_HERE,
       base::Bind(&VideoCaptureHost::DoHandleErrorOnIOThread,
@@ -88,10 +89,11 @@
                  this, controller_id, width, height, frame_per_second));
 }
 
-void VideoCaptureHost::OnPaused(const VideoCaptureControllerID& controller_id) {
+void VideoCaptureHost::OnEnded(const VideoCaptureControllerID& controller_id) {
+  DVLOG(1) << "VideoCaptureHost::OnEnded";
   BrowserThread::PostTask(
       BrowserThread::IO, FROM_HERE,
-      base::Bind(&VideoCaptureHost::DoPausedOnIOThread, this, controller_id));
+      base::Bind(&VideoCaptureHost::DoEndedOnIOThread, this, controller_id));
 }
 
 void VideoCaptureHost::DoSendNewBufferOnIOThread(
@@ -132,15 +134,15 @@
   DeleteVideoCaptureControllerOnIOThread(controller_id);
 }
 
-void VideoCaptureHost::DoPausedOnIOThread(
+void VideoCaptureHost::DoEndedOnIOThread(
     const VideoCaptureControllerID& controller_id) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-
+  DVLOG(1) << "VideoCaptureHost::DoEndedOnIOThread";
   if (entries_.find(controller_id) == entries_.end())
     return;
 
   Send(new VideoCaptureMsg_StateChanged(controller_id.device_id,
-                                        VIDEO_CAPTURE_STATE_PAUSED));
+                                        VIDEO_CAPTURE_STATE_ENDED));
   DeleteVideoCaptureControllerOnIOThread(controller_id);
 }
 
@@ -241,6 +243,7 @@
 
 void VideoCaptureHost::OnPauseCapture(int device_id) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DVLOG(1) << "VideoCaptureHost::OnPauseCapture, device_id " << device_id;
   // Not used.
   Send(new VideoCaptureMsg_StateChanged(device_id, VIDEO_CAPTURE_STATE_ERROR));
 }
diff --git a/content/browser/renderer_host/media/video_capture_host.h b/content/browser/renderer_host/media/video_capture_host.h
index 4f2f8cd..581ae88 100644
--- a/content/browser/renderer_host/media/video_capture_host.h
+++ b/content/browser/renderer_host/media/video_capture_host.h
@@ -71,7 +71,7 @@
                            int width,
                            int height,
                            int frame_per_second) OVERRIDE;
-  virtual void OnPaused(const VideoCaptureControllerID& id) OVERRIDE;
+  virtual void OnEnded(const VideoCaptureControllerID& id) OVERRIDE;
 
  private:
   friend class BrowserThread;
@@ -128,7 +128,7 @@
   // Handle error coming from VideoCaptureDevice.
   void DoHandleErrorOnIOThread(const VideoCaptureControllerID& controller_id);
 
-  void DoPausedOnIOThread(const VideoCaptureControllerID& controller_id);
+  void DoEndedOnIOThread(const VideoCaptureControllerID& controller_id);
 
   void DeleteVideoCaptureControllerOnIOThread(
       const VideoCaptureControllerID& controller_id);
diff --git a/content/browser/renderer_host/media/video_capture_host_unittest.cc b/content/browser/renderer_host/media/video_capture_host_unittest.cc
index 4c6334f..6da2b9f 100644
--- a/content/browser/renderer_host/media/video_capture_host_unittest.cc
+++ b/content/browser/renderer_host/media/video_capture_host_unittest.cc
@@ -191,7 +191,7 @@
 };
 
 ACTION_P(ExitMessageLoop, message_loop) {
-  message_loop->PostTask(FROM_HERE, MessageLoop::QuitClosure());
+  message_loop->PostTask(FROM_HERE, base::MessageLoop::QuitClosure());
 }
 
 class VideoCaptureHostTest : public testing::Test {
@@ -201,7 +201,7 @@
  protected:
   virtual void SetUp() OVERRIDE {
     // Create a message loop so VideoCaptureHostTest can use it.
-    message_loop_.reset(new MessageLoop(MessageLoop::TYPE_IO));
+    message_loop_.reset(new base::MessageLoop(base::MessageLoop::TYPE_IO));
 
     // MediaStreamManager must be created on the IO thread.
     io_thread_.reset(new BrowserThreadImpl(BrowserThread::IO,
@@ -338,7 +338,7 @@
   scoped_refptr<MockVideoCaptureHost> host_;
 
  private:
-  scoped_ptr<MessageLoop> message_loop_;
+  scoped_ptr<base::MessageLoop> message_loop_;
   scoped_ptr<BrowserThreadImpl> io_thread_;
   scoped_ptr<media::AudioManager> audio_manager_;
   scoped_ptr<MediaStreamManager> media_stream_manager_;
diff --git a/content/browser/renderer_host/media/video_capture_manager.cc b/content/browser/renderer_host/media/video_capture_manager.cc
index 1eaeabb..5605abb 100644
--- a/content/browser/renderer_host/media/video_capture_manager.cc
+++ b/content/browser/renderer_host/media/video_capture_manager.cc
@@ -94,6 +94,7 @@
 void VideoCaptureManager::Close(int capture_session_id) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
   DCHECK(listener_);
+  DVLOG(1) << "VideoCaptureManager::Close, id " << capture_session_id;
   device_loop_->PostTask(
       FROM_HERE,
       base::Bind(&VideoCaptureManager::OnClose, this, capture_session_id));
@@ -112,6 +113,7 @@
 void VideoCaptureManager::Stop(
     const media::VideoCaptureSessionId& capture_session_id,
     base::Closure stopped_cb) {
+  DVLOG(1) << "VideoCaptureManager::Stop, id " << capture_session_id;
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
   device_loop_->PostTask(
       FROM_HERE,
@@ -174,7 +176,7 @@
       }
       case MEDIA_TAB_VIDEO_CAPTURE: {
         video_capture_device = WebContentsVideoCaptureDevice::Create(
-            vc_device_name.unique_id, base::Closure());
+            vc_device_name.unique_id);
         break;
       }
       case MEDIA_SCREEN_VIDEO_CAPTURE: {
diff --git a/content/browser/renderer_host/media/video_capture_manager_unittest.cc b/content/browser/renderer_host/media/video_capture_manager_unittest.cc
index 295697a..a5890b1 100644
--- a/content/browser/renderer_host/media/video_capture_manager_unittest.cc
+++ b/content/browser/renderer_host/media/video_capture_manager_unittest.cc
@@ -70,7 +70,7 @@
  protected:
   virtual void SetUp() OVERRIDE {
     listener_.reset(new MockMediaStreamProviderListener());
-    message_loop_.reset(new MessageLoop(MessageLoop::TYPE_IO));
+    message_loop_.reset(new base::MessageLoop(base::MessageLoop::TYPE_IO));
     io_thread_.reset(new BrowserThreadImpl(BrowserThread::IO,
                                            message_loop_.get()));
     vcm_ = new VideoCaptureManager();
@@ -83,7 +83,7 @@
 
   scoped_refptr<VideoCaptureManager> vcm_;
   scoped_ptr<MockMediaStreamProviderListener> listener_;
-  scoped_ptr<MessageLoop> message_loop_;
+  scoped_ptr<base::MessageLoop> message_loop_;
   scoped_ptr<BrowserThreadImpl> io_thread_;
   scoped_ptr<MockFrameObserver> frame_observer_;
 
diff --git a/content/browser/renderer_host/media/web_contents_audio_input_stream.cc b/content/browser/renderer_host/media/web_contents_audio_input_stream.cc
index beddcb8..4e1928a 100644
--- a/content/browser/renderer_host/media/web_contents_audio_input_stream.cc
+++ b/content/browser/renderer_host/media/web_contents_audio_input_stream.cc
@@ -27,7 +27,7 @@
  public:
   // Takes ownership of |mixer_stream|.  The rest outlive this instance.
   Impl(int render_process_id, int render_view_id,
-       base::MessageLoopProxy* message_loop,
+       const scoped_refptr<base::MessageLoopProxy>& message_loop,
        AudioMirroringManager* mirroring_manager,
        const scoped_refptr<WebContentsTracker>& tracker,
        media::VirtualAudioInputStream* mixer_stream);
@@ -86,7 +86,7 @@
   void OnTargetChanged(int render_process_id, int render_view_id);
 
   // Injected dependencies.
-  base::MessageLoopProxy* const message_loop_;
+  const scoped_refptr<base::MessageLoopProxy> message_loop_;
   AudioMirroringManager* const mirroring_manager_;
   const scoped_refptr<WebContentsTracker> tracker_;
   // The AudioInputStream implementation that handles the audio conversion and
@@ -107,7 +107,7 @@
 
 WebContentsAudioInputStream::Impl::Impl(
     int render_process_id, int render_view_id,
-    base::MessageLoopProxy* message_loop,
+    const scoped_refptr<base::MessageLoopProxy>& message_loop,
     AudioMirroringManager* mirroring_manager,
     const scoped_refptr<WebContentsTracker>& tracker,
     media::VirtualAudioInputStream* mixer_stream)
@@ -279,7 +279,7 @@
 WebContentsAudioInputStream* WebContentsAudioInputStream::Create(
     const std::string& device_id,
     const media::AudioParameters& params,
-    base::MessageLoopProxy* message_loop) {
+    const scoped_refptr<base::MessageLoopProxy>& message_loop) {
   int render_process_id;
   int render_view_id;
   if (!WebContentsCaptureUtil::ExtractTabCaptureTarget(
@@ -298,7 +298,7 @@
 
 WebContentsAudioInputStream::WebContentsAudioInputStream(
     int render_process_id, int render_view_id,
-    base::MessageLoopProxy* message_loop,
+    const scoped_refptr<base::MessageLoopProxy>& message_loop,
     AudioMirroringManager* mirroring_manager,
     const scoped_refptr<WebContentsTracker>& tracker,
     media::VirtualAudioInputStream* mixer_stream)
diff --git a/content/browser/renderer_host/media/web_contents_audio_input_stream.h b/content/browser/renderer_host/media/web_contents_audio_input_stream.h
index fa4801c..b424801 100644
--- a/content/browser/renderer_host/media/web_contents_audio_input_stream.h
+++ b/content/browser/renderer_host/media/web_contents_audio_input_stream.h
@@ -58,7 +58,7 @@
   static WebContentsAudioInputStream* Create(
       const std::string& device_id,
       const media::AudioParameters& params,
-      base::MessageLoopProxy* message_loop);
+      const scoped_refptr<base::MessageLoopProxy>& message_loop);
 
  private:
   friend class WebContentsAudioInputStreamTest;
@@ -72,7 +72,7 @@
 
   WebContentsAudioInputStream(
       int render_process_id, int render_view_id,
-      base::MessageLoopProxy* message_loop,
+      const scoped_refptr<base::MessageLoopProxy>& message_loop,
       AudioMirroringManager* mirroring_manager,
       const scoped_refptr<WebContentsTracker>& tracker,
       media::VirtualAudioInputStream* mixer_stream);
diff --git a/content/browser/renderer_host/media/web_contents_audio_input_stream_unittest.cc b/content/browser/renderer_host/media/web_contents_audio_input_stream_unittest.cc
index b786932..ffd9cbb 100644
--- a/content/browser/renderer_host/media/web_contents_audio_input_stream_unittest.cc
+++ b/content/browser/renderer_host/media/web_contents_audio_input_stream_unittest.cc
@@ -88,7 +88,8 @@
 // tests to check how/when they are invoked.
 class MockVirtualAudioInputStream : public VirtualAudioInputStream {
  public:
-  explicit MockVirtualAudioInputStream(base::MessageLoopProxy* message_loop)
+  explicit MockVirtualAudioInputStream(
+      const scoped_refptr<base::MessageLoopProxy>& message_loop)
       : VirtualAudioInputStream(TestAudioParameters(), message_loop,
                                 VirtualAudioInputStream::AfterCloseCallback()),
         real_(TestAudioParameters(), message_loop,
diff --git a/content/browser/renderer_host/media/web_contents_capture_util.cc b/content/browser/renderer_host/media/web_contents_capture_util.cc
index 46b7376..843a8e5 100644
--- a/content/browser/renderer_host/media/web_contents_capture_util.cc
+++ b/content/browser/renderer_host/media/web_contents_capture_util.cc
@@ -6,8 +6,8 @@
 
 #include "base/basictypes.h"
 #include "base/string_number_conversions.h"
-#include "base/string_piece.h"
 #include "base/string_util.h"
+#include "base/strings/string_piece.h"
 
 namespace {
 
diff --git a/content/browser/renderer_host/media/web_contents_video_capture_device.cc b/content/browser/renderer_host/media/web_contents_video_capture_device.cc
index 97eeda3..04327dd 100644
--- a/content/browser/renderer_host/media/web_contents_video_capture_device.cc
+++ b/content/browser/renderer_host/media/web_contents_video_capture_device.cc
@@ -61,8 +61,10 @@
 #include "base/debug/trace_event.h"
 #include "base/logging.h"
 #include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
 #include "base/message_loop_proxy.h"
 #include "base/metrics/histogram.h"
+#include "base/sequenced_task_runner.h"
 #include "base/stringprintf.h"
 #include "base/synchronization/lock.h"
 #include "base/threading/thread.h"
@@ -101,9 +103,20 @@
 const int kMaxFramesInFlight = 2;
 const int kMaxSnapshotsInFlight = 1;
 
+// This value controls how many redundant, timer-base captures occur when the
+// content is static. Redundantly capturing the same frame allows iterative
+// quality enhancement, and also allows the buffer to fill in "buffered mode".
+//
+// TODO(nick): Controlling this here is a hack and a layering violation, since
+// it's a strategy specific to the WebRTC consumer, and probably just papers
+// over some frame dropping and quality bugs. It should either be controlled at
+// a higher level, or else redundant frame generation should be pushed down
+// further into the WebRTC encoding stack.
+const int kNumRedundantCapturesOfStaticContent = 200;
+
 // TODO(nick): Remove this once frame subscription is supported on Aura and
 // Linux.
-#if (defined(OS_WIN) || defined(OS_MACOSX)) && !defined(USE_AURA)
+#if (defined(OS_WIN) || defined(OS_MACOSX)) || defined(USE_AURA)
 const bool kAcceleratedSubscriberIsSupported = true;
 #else
 const bool kAcceleratedSubscriberIsSupported = false;
@@ -155,6 +168,7 @@
   // capture should be done, and a callback to invoke once the frame is ready.
   bool ObserveEventAndDecideCapture(
       Event event,
+      base::Time event_time,
       scoped_refptr<media::VideoFrame>* storage,
       DeliverFrameCallback* callback);
 
@@ -179,6 +193,7 @@
 
   // Callback invoked upon completion of all captures.
   void DidCaptureFrame(const scoped_refptr<media::VideoFrame>& frame,
+                       int frame_number,
                        base::Time timestamp,
                        bool success);
 
@@ -194,6 +209,12 @@
   // Incremented every time a paint or update event occurs.
   int frame_number_;
 
+  // Stores the frame number from the last delivered frame.
+  int last_delivered_frame_number_;
+
+  // Stores the timestamp of the last delivered frame.
+  base::Time last_delivered_frame_timestamp_;
+
   // Whether capturing is currently allowed. Can toggle back and forth.
   bool is_started_;
 
@@ -211,6 +232,7 @@
         oracle_(oracle) {}
 
   virtual bool ShouldCaptureFrame(
+      base::Time present_time,
       scoped_refptr<media::VideoFrame>* storage,
       RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback*
           deliver_frame_cb) OVERRIDE;
@@ -237,7 +259,8 @@
 // autonomously on some other thread.
 class ContentCaptureSubscription : public content::NotificationObserver {
  public:
-  typedef base::Callback<void(const scoped_refptr<media::VideoFrame>&,
+  typedef base::Callback<void(const base::Time&,
+                              const scoped_refptr<media::VideoFrame>&,
                               const DeliverFrameCallback&)> CaptureCallback;
 
   // Create a subscription. Whenever a manual capture is required, the
@@ -269,30 +292,18 @@
   DISALLOW_COPY_AND_ASSIGN(ContentCaptureSubscription);
 };
 
-// Renders captures (from the backing store) into video frame buffers on a
-// dedicated thread. Intended for use in the software rendering case, when GPU
-// acceleration of these activities is not possible.
-class VideoFrameRenderer {
- public:
-  VideoFrameRenderer();
-
-  // Render the SkBitmap |input| into the given VideoFrame buffer |output|, then
-  // invoke |done_cb| to indicate success or failure. |input| is expected to be
-  // ARGB. |output| must be YV12 or I420. Colorspace conversion is always done.
-  // Scaling and letterboxing will be done as needed.
-  void Render(const SkBitmap& input,
-              const scoped_refptr<media::VideoFrame>& output,
-              const base::Callback<void(bool)>& done_cb);
-
- private:
-  void RenderOnRenderThread(const SkBitmap& input,
-                            const scoped_refptr<media::VideoFrame>& output,
-                            const base::Callback<void(bool)>& done_cb);
-
-  base::Thread render_thread_;
-
-  DISALLOW_COPY_AND_ASSIGN(VideoFrameRenderer);
-};
+// Render the SkBitmap |input| into the given VideoFrame buffer |output|, then
+// invoke |done_cb| to indicate success or failure. |input| is expected to be
+// ARGB. |output| must be YV12 or I420. Colorspace conversion is always done.
+// Scaling and letterboxing will be done as needed.
+//
+// This software implementation should be used only when GPU acceleration of
+// these activities is not possible. This operation may be expensive (tens to
+// hundreds of milliseconds), so the caller should ensure that it runs on a
+// thread where such a pause would cause UI jank.
+void RenderVideoFrame(const SkBitmap& input,
+                      const scoped_refptr<media::VideoFrame>& output,
+                      const base::Callback<void(bool)>& done_cb);
 
 // Keeps track of the RenderView to be sourced, and executes copying of the
 // backing store on the UI BrowserThread.
@@ -311,6 +322,7 @@
   static scoped_ptr<CaptureMachine> Create(
       int render_process_id,
       int render_view_id,
+      const scoped_refptr<base::SequencedTaskRunner>& render_task_runner,
       const scoped_refptr<CaptureOracle>& oracle);
 
   // Starts a copy from the backing store or the composited surface. Must be run
@@ -319,6 +331,7 @@
   //
   // This may be used as a ContentCaptureSubscription::CaptureCallback.
   void Capture(
+      const base::Time& start_time,
       const scoped_refptr<media::VideoFrame>& target,
       const DeliverFrameCallback& deliver_frame_cb);
 
@@ -338,19 +351,22 @@
     RenewFrameSubscription();
   }
 
-  virtual void AboutToNavigateRenderView(RenderViewHost* rvh) {
+  virtual void AboutToNavigateRenderView(RenderViewHost* rvh) OVERRIDE {
     RenewFrameSubscription();
   }
 
   virtual void DidNavigateMainFrame(
-      const LoadCommittedDetails& details, const FrameNavigateParams& params) {
+      const LoadCommittedDetails& details,
+      const FrameNavigateParams& params) OVERRIDE {
     RenewFrameSubscription();
   }
 
   virtual void WebContentsDestroyed(WebContents* web_contents) OVERRIDE;
 
  private:
-  explicit CaptureMachine(const scoped_refptr<CaptureOracle>& oracle);
+  CaptureMachine(
+     const scoped_refptr<base::SequencedTaskRunner>& render_task_runner,
+     const scoped_refptr<CaptureOracle>& oracle);
 
   // Starts observing the web contents, returning false if lookup fails.
   bool StartObservingWebContents(int initial_render_process_id,
@@ -361,7 +377,7 @@
 
   // Response callback for RenderWidgetHost::CopyFromBackingStore().
   void DidCopyFromBackingStore(
-      base::Time start_time,
+      const base::Time& start_time,
       const scoped_refptr<media::VideoFrame>& target,
       const DeliverFrameCallback& deliver_frame_cb,
       bool success,
@@ -369,7 +385,7 @@
 
   // Response callback for RWHVP::CopyFromCompositingSurfaceToVideoFrame().
   void DidCopyFromCompositingSurfaceToVideoFrame(
-      base::Time start_time,
+      const base::Time& start_time,
       const DeliverFrameCallback& deliver_frame_cb,
       bool success);
 
@@ -378,6 +394,11 @@
   // attached views.
   void RenewFrameSubscription();
 
+  // The task runner of the thread on which SkBitmap->VideoFrame conversion will
+  // occur. Only used when this activity cannot be done on the GPU.
+  const scoped_refptr<base::SequencedTaskRunner> render_task_runner_;
+
+  // Makes all the decisions about which frames to copy, and how.
   const scoped_refptr<CaptureOracle> oracle_;
 
   // Routing ID of any active fullscreen render widget or MSG_ROUTING_NONE
@@ -387,13 +408,10 @@
   // Last known RenderView size.
   gfx::Size last_view_size_;
 
+  // Responsible for forwarding events from the active RenderWidgetHost to the
+  // oracle, and initiating captures accordingly.
   scoped_ptr<ContentCaptureSubscription> subscription_;
 
-  // Handles SkBitmap->VideoFrame copying (including scaling, letterboxing, and
-  // YV12 conversion) on another thread for us. Only used when this activity
-  // cannot be done on the GPU.
-  VideoFrameRenderer renderer_;
-
   DISALLOW_COPY_AND_ASSIGN(CaptureMachine);
 };
 
@@ -422,11 +440,14 @@
     : capture_period_(capture_period),
       consumer_(consumer),
       frame_number_(0),
+      last_delivered_frame_number_(0),
       is_started_(false),
-      sampler_(capture_period_, kAcceleratedSubscriberIsSupported) {}
+      sampler_(capture_period_, kAcceleratedSubscriberIsSupported,
+               kNumRedundantCapturesOfStaticContent) {}
 
 bool CaptureOracle::ObserveEventAndDecideCapture(
       Event event,
+      base::Time event_time,
       scoped_refptr<media::VideoFrame>* storage,
       RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback* callback) {
   base::AutoLock guard(lock_);
@@ -440,13 +461,12 @@
   // Record |event| and decide whether it's a good time to capture.
   const bool content_is_dirty = (event == COMPOSITOR_UPDATE ||
                                  event == SOFTWARE_PAINT);
-  base::Time now = base::Time::Now();
   bool should_sample;
   if (content_is_dirty) {
     frame_number_++;
-    should_sample = sampler_.AddEventAndConsiderSampling(now);
+    should_sample = sampler_.AddEventAndConsiderSampling(event_time);
   } else {
-    should_sample = sampler_.IsOverdueForSamplingAt(now);
+    should_sample = sampler_.IsOverdueForSamplingAt(event_time);
   }
 
   const char* event_name = (event == TIMER_POLL ? "poll" :
@@ -456,6 +476,7 @@
   // Step 3: Consider the various reasons not to initiate a capture.
   if (should_sample && !output_buffer) {
     TRACE_EVENT_INSTANT1("mirroring", "EncodeLimited",
+                         TRACE_EVENT_SCOPE_THREAD,
                          "trigger", event_name);
     return false;
   } else if (!should_sample && output_buffer) {
@@ -464,6 +485,7 @@
       // capture rate limit: for example, the content is animating at 60fps but
       // we're capturing at 30fps.
       TRACE_EVENT_INSTANT1("mirroring", "FpsRateLimited",
+                           TRACE_EVENT_SCOPE_THREAD,
                            "trigger", event_name);
     }
     return false;
@@ -471,6 +493,7 @@
     // We decided not to capture, but we wouldn't have been able to if we wanted
     // to because no output buffer was available.
     TRACE_EVENT_INSTANT1("mirroring", "NearlyEncodeLimited",
+                         TRACE_EVENT_SCOPE_THREAD,
                          "trigger", event_name);
     return false;
   }
@@ -482,7 +505,7 @@
                            "trigger", event_name);
   *storage = output_buffer;
   *callback = base::Bind(&CaptureOracle::DidCaptureFrame,
-                         this, output_buffer);
+                         this, output_buffer, frame_number_);
   return true;
 }
 
@@ -505,7 +528,8 @@
 void CaptureOracle::InvalidateConsumer() {
   base::AutoLock guard(lock_);
 
-  TRACE_EVENT_INSTANT0("mirroring", "InvalidateConsumer");
+  TRACE_EVENT_INSTANT0("mirroring", "InvalidateConsumer",
+                       TRACE_EVENT_SCOPE_THREAD);
 
   is_started_ = false;
   consumer_ = NULL;
@@ -513,28 +537,50 @@
 
 void CaptureOracle::DidCaptureFrame(
     const scoped_refptr<media::VideoFrame>& frame,
+    int frame_number,
     base::Time timestamp,
     bool success) {
   base::AutoLock guard(lock_);
 
-  TRACE_EVENT_ASYNC_END1("mirroring", "Capture", frame.get(),
-                         "success", success);
+  TRACE_EVENT_ASYNC_END2("mirroring", "Capture", frame.get(),
+                         "success", success,
+                         "timestamp", timestamp.ToInternalValue());
 
   if (!consumer_ || !is_started_)
     return;  // Capture is stopped.
 
-  if (success)
+  if (success) {
+    // Drop frame if previous frame number is higher or we're trying to deliver
+    // a frame with the same timestamp.
+    if (last_delivered_frame_number_ > frame_number ||
+        last_delivered_frame_timestamp_ == timestamp) {
+      LOG(ERROR) << "Frame with same timestamp or out of order delivery. "
+                 << "Dropping frame.";
+      return;
+    }
+
+    if (last_delivered_frame_timestamp_ > timestamp) {
+      // We should not get here unless time was adjusted backwards.
+      LOG(ERROR) << "Frame with past timestamp (" << timestamp.ToInternalValue()
+                 << ") was delivered";
+    }
+
+    last_delivered_frame_number_ = frame_number;
+    last_delivered_frame_timestamp_ = timestamp;
+
     consumer_->OnIncomingCapturedVideoFrame(frame, timestamp);
+  }
 }
 
 bool FrameSubscriber::ShouldCaptureFrame(
+    base::Time present_time,
     scoped_refptr<media::VideoFrame>* storage,
     DeliverFrameCallback* deliver_frame_cb) {
   TRACE_EVENT1("mirroring", "FrameSubscriber::ShouldCaptureFrame",
                "instance", this);
 
-  return oracle_->ObserveEventAndDecideCapture(event_type_, storage,
-                                               deliver_frame_cb);
+  return oracle_->ObserveEventAndDecideCapture(event_type_, present_time,
+                                               storage, deliver_frame_cb);
 }
 
 ContentCaptureSubscription::ContentCaptureSubscription(
@@ -607,12 +653,15 @@
   base::Closure copy_done_callback;
   scoped_refptr<media::VideoFrame> frame;
   RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback deliver_frame_cb;
-  if (paint_subscriber_.ShouldCaptureFrame(&frame, &deliver_frame_cb)) {
+  const base::Time start_time = base::Time::Now();
+  if (paint_subscriber_.ShouldCaptureFrame(start_time,
+                                           &frame,
+                                           &deliver_frame_cb)) {
     // This message happens just before paint. If we post a task to do the copy,
     // it should run soon after the paint.
     BrowserThread::PostTask(
         BrowserThread::UI, FROM_HERE,
-        base::Bind(capture_callback_, frame, deliver_frame_cb));
+        base::Bind(capture_callback_, start_time, frame, deliver_frame_cb));
   }
 }
 
@@ -622,30 +671,18 @@
 
   scoped_refptr<media::VideoFrame> frame;
   RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback deliver_frame_cb;
-  if (timer_subscriber_.ShouldCaptureFrame(&frame, &deliver_frame_cb)) {
-    capture_callback_.Run(frame, deliver_frame_cb);
+
+  const base::Time start_time = base::Time::Now();
+  if (timer_subscriber_.ShouldCaptureFrame(start_time,
+                                           &frame,
+                                           &deliver_frame_cb)) {
+    capture_callback_.Run(start_time, frame, deliver_frame_cb);
   }
 }
 
-VideoFrameRenderer::VideoFrameRenderer()
-    : render_thread_("WebContentsVideo_RenderThread") {
-  render_thread_.Start();
-}
-
-void VideoFrameRenderer::Render(const SkBitmap& input,
-                                const scoped_refptr<media::VideoFrame>& output,
-                                const base::Callback<void(bool)>& done_cb) {
-  render_thread_.message_loop()->PostTask(
-      FROM_HERE,
-      base::Bind(&VideoFrameRenderer::RenderOnRenderThread,
-                 base::Unretained(this), input, output, done_cb));
-}
-
-void VideoFrameRenderer::RenderOnRenderThread(
-    const SkBitmap& input,
-    const scoped_refptr<media::VideoFrame>& output,
-    const base::Callback<void(bool)>& done_cb) {
-  DCHECK_EQ(render_thread_.message_loop(), MessageLoop::current());
+void RenderVideoFrame(const SkBitmap& input,
+                      const scoped_refptr<media::VideoFrame>& output,
+                      const base::Callback<void(bool)>& done_cb) {
   base::ScopedClosureRunner failure_handler(base::Bind(done_cb, false));
 
   SkAutoLockPixels locker(input);
@@ -744,9 +781,13 @@
 scoped_ptr<CaptureMachine> CaptureMachine::Create(
     int render_process_id,
     int render_view_id,
+    const scoped_refptr<base::SequencedTaskRunner>& render_task_runner,
     const scoped_refptr<CaptureOracle>& oracle) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  scoped_ptr<CaptureMachine> machine(new CaptureMachine(oracle));
+  DCHECK(render_task_runner);
+  DCHECK(oracle);
+  scoped_ptr<CaptureMachine> machine(
+      new CaptureMachine(render_task_runner, oracle));
 
   if (!machine->StartObservingWebContents(render_process_id, render_view_id))
     machine.reset();
@@ -754,12 +795,16 @@
   return machine.Pass();
 }
 
-CaptureMachine::CaptureMachine(const scoped_refptr<CaptureOracle>& oracle)
-    : oracle_(oracle),
+CaptureMachine::CaptureMachine(
+    const scoped_refptr<base::SequencedTaskRunner>& render_task_runner,
+    const scoped_refptr<CaptureOracle>& oracle)
+    : render_task_runner_(render_task_runner),
+      oracle_(oracle),
       fullscreen_widget_id_(MSG_ROUTING_NONE) {}
 
 CaptureMachine::~CaptureMachine() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI) ||
+         !BrowserThread::IsMessageLoopValid(BrowserThread::UI));
 
   // Stop observing the web contents.
   subscription_.reset();
@@ -770,6 +815,7 @@
 }
 
 void CaptureMachine::Capture(
+    const base::Time& start_time,
     const scoped_refptr<media::VideoFrame>& target,
     const DeliverFrameCallback& deliver_frame_cb) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
@@ -797,7 +843,6 @@
         view_size.width() * view_size.height() / 1024);
   }
 
-  base::Time start_time = base::Time::Now();
   if (!view->IsSurfaceAvailableForCopy()) {
     // Fallback to the more expensive renderer-side copy if the surface and
     // backing store are not accessible.
@@ -879,7 +924,7 @@
 }
 
 void CaptureMachine::DidCopyFromBackingStore(
-    base::Time start_time,
+    const base::Time& start_time,
     const scoped_refptr<media::VideoFrame>& target,
     const DeliverFrameCallback& deliver_frame_cb,
     bool success,
@@ -890,18 +935,18 @@
   if (success) {
     UMA_HISTOGRAM_TIMES("TabCapture.CopyTimeBitmap", now - start_time);
     TRACE_EVENT_ASYNC_STEP0("mirroring", "Capture", target.get(), "Render");
-    renderer_.Render(bitmap,
-                     target,
-                     base::Bind(deliver_frame_cb, now));
+    render_task_runner_->PostTask(FROM_HERE, base::Bind(
+        &RenderVideoFrame, bitmap, target,
+        base::Bind(deliver_frame_cb, start_time)));
   } else {
     // Capture can fail due to transient issues, so just skip this frame.
     DVLOG(1) << "CopyFromBackingStore failed; skipping frame.";
-    deliver_frame_cb.Run(now, false);
+    deliver_frame_cb.Run(start_time, false);
   }
 }
 
 void CaptureMachine::DidCopyFromCompositingSurfaceToVideoFrame(
-    base::Time start_time,
+    const base::Time& start_time,
     const DeliverFrameCallback& deliver_frame_cb,
     bool success) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
@@ -913,7 +958,7 @@
     // Capture can fail due to transient issues, so just skip this frame.
     DVLOG(1) << "CopyFromCompositingSurface failed; skipping frame.";
   }
-  deliver_frame_cb.Run(now, success);
+  deliver_frame_cb.Run(start_time, success);
 }
 
 void CaptureMachine::RenewFrameSubscription() {
@@ -930,6 +975,12 @@
       base::Bind(&CaptureMachine::Capture, this->AsWeakPtr())));
 }
 
+void DeleteCaptureMachineOnUIThread(
+    scoped_ptr<CaptureMachine> capture_machine) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  capture_machine.reset();
+}
+
 }  // namespace
 
 // The "meat" of the video capture implementation, which is a ref-counted class.
@@ -941,15 +992,11 @@
 // pipeline (see notes at top of this file).  It times the start of successive
 // captures and facilitates the processing of each through the stages of the
 // pipeline.
-class WebContentsVideoCaptureDevice::Impl
-    : public base::RefCountedThreadSafe<Impl> {
+class WebContentsVideoCaptureDevice::Impl : public base::SupportsWeakPtr<Impl> {
  public:
 
-  // |destroy_cb| will be invoked after WebContentsVideoCaptureDevice::Impl is
-  // fully destroyed, to synchronize tear-down.
-  Impl(int render_process_id,
-       int render_view_id,
-       const base::Closure& destroy_cb);
+  Impl(int render_process_id, int render_view_id);
+  virtual ~Impl();
 
   // Asynchronous requests to change WebContentsVideoCaptureDevice::Impl state.
   void Allocate(int width,
@@ -961,7 +1008,6 @@
   void DeAllocate();
 
  private:
-  friend class base::RefCountedThreadSafe<Impl>;
 
   // Flag indicating current state.
   enum State {
@@ -971,19 +1017,17 @@
     kError
   };
 
-  virtual ~Impl();
-
   void TransitionStateTo(State next_state);
 
   // Stops capturing and notifies consumer_ of an error state.
   void Error();
 
-  bool CreateCaptureMachineOnUIThread(
-      const scoped_refptr<CaptureOracle>& oracle);
-  void DestroyCaptureMachineOnUIThread();
-
-  // Response callback for CreateCaptureMachineOnUIThread.
-  void DidCreateCaptureMachine(bool created);
+  // Called in response to CaptureMachine::Create that runs on the UI thread.
+  // It will assign the capture machine to the Impl class if it still exists
+  // otherwise it will post a task to delete CaptureMachine on the UI thread.
+  static void AssignCaptureMachine(
+      base::WeakPtr<WebContentsVideoCaptureDevice::Impl> impl,
+      scoped_ptr<CaptureMachine> capture_machine);
 
   // Tracks that all activity occurs on the media stream manager's thread.
   base::ThreadChecker thread_checker_;
@@ -1000,6 +1044,10 @@
   // Current lifecycle state.
   State state_;
 
+  // A dedicated worker thread for doing image operations. Started/joined here,
+  // but used by the CaptureMachine.
+  base::Thread render_thread_;
+
   // Tracks the CaptureMachine that's doing work on our behalf on the UI thread.
   // This value should never be dereferenced by this class, other than to
   // create and destroy it on the UI thread.
@@ -1010,20 +1058,16 @@
   // system with direct access to |consumer_|.
   scoped_refptr<CaptureOracle> oracle_;
 
-  // Invoked once WebContentsVideoCaptureDevice::Impl is destroyed.
-  base::Closure destroy_cb_;
-
   DISALLOW_COPY_AND_ASSIGN(Impl);
 };
 
 WebContentsVideoCaptureDevice::Impl::Impl(int render_process_id,
-                                          int render_view_id,
-                                          const base::Closure& destroy_cb)
+                                          int render_view_id)
     : initial_render_process_id_(render_process_id),
       initial_render_view_id_(render_view_id),
       consumer_(NULL),
       state_(kIdle),
-      destroy_cb_(destroy_cb) {
+      render_thread_("WebContentsVideo_RenderThread") {
 }
 
 void WebContentsVideoCaptureDevice::Impl::Allocate(
@@ -1044,6 +1088,12 @@
     return;
   }
 
+  if (!render_thread_.Start()) {
+    DVLOG(1) << "Failed to spawn render thread.";
+    consumer->OnError();
+    return;
+  }
+
   // Frame dimensions must each be a positive, even integer, since the consumer
   // wants (or will convert to) YUV420.
   width = MakeEven(width);
@@ -1075,6 +1125,19 @@
   consumer_->OnFrameInfo(settings);
   oracle_ = new CaptureOracle(consumer_, capture_period);
 
+  // Allocates the CaptureMachine. The CaptureMachine will be tracking render
+  // view swapping over its lifetime, and we don't want to lose our reference to
+  // the current render view by starting over with the stale
+  // |initial_render_view_id_|.
+  DCHECK(!capture_machine_.get());
+  BrowserThread::PostTaskAndReplyWithResult(
+      BrowserThread::UI, FROM_HERE,
+      base::Bind(&CaptureMachine::Create,
+                 initial_render_process_id_,
+                 initial_render_view_id_,
+                 render_thread_.message_loop_proxy(), oracle_),
+      base::Bind(&Impl::AssignCaptureMachine, AsWeakPtr()));
+
   TransitionStateTo(kAllocated);
 }
 
@@ -1088,39 +1151,29 @@
   TransitionStateTo(kCapturing);
 
   oracle_->Start();
-
-  BrowserThread::PostTaskAndReplyWithResult(
-      BrowserThread::UI, FROM_HERE,
-      base::Bind(&Impl::CreateCaptureMachineOnUIThread, this, oracle_),
-      base::Bind(&Impl::DidCreateCaptureMachine, this));
 }
 
-bool WebContentsVideoCaptureDevice::Impl::CreateCaptureMachineOnUIThread(
-    const scoped_refptr<CaptureOracle>& oracle) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+// static
+void WebContentsVideoCaptureDevice::Impl::AssignCaptureMachine(
+    base::WeakPtr<WebContentsVideoCaptureDevice::Impl> impl,
+    scoped_ptr<CaptureMachine> capture_machine) {
+  DCHECK(!impl || impl->thread_checker_.CalledOnValidThread());
 
-  // Only create the CaptureMachine if we haven't already. The CaptureMachine
-  // will be tracking render view swapping over its lifetime, and we don't want
-  // to lose our reference to the current render view by starting over with the
-  // stale |initial_render_view_id_|.
-  if (!capture_machine_) {
-    capture_machine_ = CaptureMachine::Create(
-        initial_render_process_id_, initial_render_view_id_, oracle).Pass();
+  if (!impl) {
+    // If WCVD::Impl was destroyed before we got back on it's thread and
+    // capture_machine is not NULL, then we need to return to the UI thread to
+    // safely cleanup the CaptureMachine.
+    if (capture_machine) {
+      BrowserThread::PostTask(
+          BrowserThread::UI, FROM_HERE, base::Bind(
+              &DeleteCaptureMachineOnUIThread, base::Passed(&capture_machine)));
+      return;
+    }
+  } else if (!capture_machine) {
+    impl->Error();
+  } else {
+    impl->capture_machine_ = capture_machine.Pass();
   }
-
-  return capture_machine_ != NULL;
-}
-
-void WebContentsVideoCaptureDevice::Impl::DestroyCaptureMachineOnUIThread() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  capture_machine_.reset();
-}
-
-void WebContentsVideoCaptureDevice::Impl::DidCreateCaptureMachine(
-    bool created) {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  if (!created)
-    Error();
 }
 
 void WebContentsVideoCaptureDevice::Impl::Stop() {
@@ -1144,26 +1197,28 @@
     oracle_->InvalidateConsumer();
     consumer_ = NULL;
     oracle_ = NULL;
-
-    // The above call to InvalidateConsumer() has shut-off capture at the
-    // |consumer_| interface. But there is still a capture pipeline running that
-    // is checking in with the oracle, and processing captures that are already
-    // started in flight. That pipeline must be shut down asynchronously, on the
-    // UI thread.
-    BrowserThread::PostTask(
-        BrowserThread::UI, FROM_HERE,
-        base::Bind(&Impl::DestroyCaptureMachineOnUIThread, this));
+    render_thread_.Stop();
 
     TransitionStateTo(kIdle);
   }
 }
 
 WebContentsVideoCaptureDevice::Impl::~Impl() {
+  // There is still a capture pipeline running that is checking in with the
+  // oracle, and processing captures that are already started in flight. That
+  // pipeline must be shut down asynchronously, on the UI thread.
+  if (capture_machine_) {
+    // The task that is posted to the UI thread might not run if we are shutting
+    // down, so we transfer ownership of CaptureMachine to the closure so that
+    // it is still cleaned up when the closure is deleted.
+    BrowserThread::PostTask(
+        BrowserThread::UI, FROM_HERE, base::Bind(
+            &DeleteCaptureMachineOnUIThread, base::Passed(&capture_machine_)));
+  }
+
   DCHECK(!capture_machine_) << "Cleanup on UI thread did not happen.";
   DCHECK(!consumer_) << "Device not DeAllocated -- possible data race.";
   DVLOG(1) << "WebContentsVideoCaptureDevice::Impl@" << this << " destroying.";
-  if (!destroy_cb_.is_null())
-    destroy_cb_.Run();
 }
 
 void WebContentsVideoCaptureDevice::Impl::TransitionStateTo(State next_state) {
@@ -1196,12 +1251,10 @@
 WebContentsVideoCaptureDevice::WebContentsVideoCaptureDevice(
     const media::VideoCaptureDevice::Name& name,
     int render_process_id,
-    int render_view_id,
-    const base::Closure& destroy_cb)
+    int render_view_id)
     : device_name_(name),
-      capturer_(new WebContentsVideoCaptureDevice::Impl(render_process_id,
-                                                        render_view_id,
-                                                        destroy_cb)) {}
+      impl_(new WebContentsVideoCaptureDevice::Impl(render_process_id,
+                                                    render_view_id)) {}
 
 WebContentsVideoCaptureDevice::~WebContentsVideoCaptureDevice() {
   DVLOG(2) << "WebContentsVideoCaptureDevice@" << this << " destroying.";
@@ -1209,8 +1262,7 @@
 
 // static
 media::VideoCaptureDevice* WebContentsVideoCaptureDevice::Create(
-    const std::string& device_id,
-    const base::Closure& destroy_cb) {
+    const std::string& device_id) {
   // Parse device_id into render_process_id and render_view_id.
   int render_process_id = -1;
   int render_view_id = -1;
@@ -1226,29 +1278,25 @@
   name.unique_id = device_id;
 
   return new WebContentsVideoCaptureDevice(
-      name, render_process_id, render_view_id, destroy_cb);
+      name, render_process_id, render_view_id);
 }
 
 void WebContentsVideoCaptureDevice::Allocate(
     int width, int height, int frame_rate,
     VideoCaptureDevice::EventHandler* consumer) {
-  DCHECK(capturer_);
-  capturer_->Allocate(width, height, frame_rate, consumer);
+  impl_->Allocate(width, height, frame_rate, consumer);
 }
 
 void WebContentsVideoCaptureDevice::Start() {
-  DCHECK(capturer_);
-  capturer_->Start();
+  impl_->Start();
 }
 
 void WebContentsVideoCaptureDevice::Stop() {
-  DCHECK(capturer_);
-  capturer_->Stop();
+  impl_->Stop();
 }
 
 void WebContentsVideoCaptureDevice::DeAllocate() {
-  DCHECK(capturer_);
-  capturer_->DeAllocate();
+  impl_->DeAllocate();
 }
 
 const media::VideoCaptureDevice::Name&
@@ -1257,56 +1305,80 @@
 }
 
 SmoothEventSampler::SmoothEventSampler(base::TimeDelta capture_period,
-                                       bool events_are_reliable)
+                                       bool events_are_reliable,
+                                       int redundant_capture_goal)
     :  events_are_reliable_(events_are_reliable),
-       capture_period_(capture_period) {}
+       capture_period_(capture_period),
+       redundant_capture_goal_(redundant_capture_goal),
+       token_bucket_capacity_(capture_period + capture_period / 2),
+       overdue_sample_count_(0),
+       token_bucket_(token_bucket_capacity_) {
+  DCHECK_GT(capture_period_.InMicroseconds(), 0);
+}
 
-bool SmoothEventSampler::AddEventAndConsiderSampling(base::Time now) {
-  current_event_ = now;
+bool SmoothEventSampler::AddEventAndConsiderSampling(base::Time event_time) {
+  DCHECK(!event_time.is_null());
 
-  // If we've never sampled, then the choice is obvious.
-  if (last_sample_.is_null())
-    return true;
+  // Add tokens to the bucket based on advancement in time.  Then, re-bound the
+  // number of tokens in the bucket.  Overflow occurs when there is too much
+  // time between events (a common case), or when RecordSample() is not being
+  // called often enough (a bug).  On the other hand, if RecordSample() is being
+  // called too often (e.g., as a reaction to IsOverdueForSamplingAt()), the
+  // bucket will underflow.
+  if (!current_event_.is_null()) {
+    if (current_event_ < event_time) {
+      token_bucket_ += event_time - current_event_;
+      if (token_bucket_ > token_bucket_capacity_)
+        token_bucket_ = token_bucket_capacity_;
+    }
+    // Side note: If the system clock is reset, causing |current_event_| to be
+    // greater than |event_time|, everything here will simply gracefully adjust.
+    if (token_bucket_ < base::TimeDelta())
+      token_bucket_ = base::TimeDelta();
+    TRACE_COUNTER1("mirroring",
+                   "MirroringTokenBucketUsec", token_bucket_.InMicroseconds());
+  }
+  current_event_ = event_time;
 
-  // TODO(nick): Actually track the effective frame rate here, and use an
-  // uncertainty window based on that (half seems like a reasonable choice). E.g
-  // if content is updating every 16.6ms, and we're hoping to sampling every
-  // 100ms, then we might consider sampling events no sooner than (100ms -
-  // 8.3ms) from the last sample.
-  base::TimeDelta uncertainty_window = capture_period_ / 10;
-
-  base::TimeDelta interval = current_event_ - last_sample_;
-  return interval >= (capture_period_ - uncertainty_window);
+  // Return true if one capture period's worth of tokens are in the bucket.
+  return token_bucket_ >= capture_period_;
 }
 
 void SmoothEventSampler::RecordSample() {
-  if (!current_event_.is_null())
+  token_bucket_ -= capture_period_;
+  TRACE_COUNTER1("mirroring",
+                 "MirroringTokenBucketUsec", token_bucket_.InMicroseconds());
+  if (HasUnrecordedEvent()) {
     last_sample_ = current_event_;
-  current_event_ = base::Time();
+    overdue_sample_count_ = 0;
+  } else {
+    ++overdue_sample_count_;
+  }
 }
 
-bool SmoothEventSampler::IsOverdueForSamplingAt(base::Time now) const {
-  if (last_sample_.is_null())
-    return true;  // Definitely old and dirty.
+bool SmoothEventSampler::IsOverdueForSamplingAt(base::Time event_time) const {
+  DCHECK(!event_time.is_null());
 
   // If we don't get events on compositor updates on this platform, then we
   // don't reliably know whether we're dirty.
   if (events_are_reliable_) {
-    if (current_event_.is_null())
+    if (!HasUnrecordedEvent() &&
+        overdue_sample_count_ >= redundant_capture_goal_) {
       return false;  // Not dirty.
+    }
   }
 
   // If we're dirty but not yet old, then we've recently gotten updates, so we
   // won't request a sample just yet.
-  base::TimeDelta dirty_interval = now - last_sample_;
-  if (dirty_interval < capture_period_ * 2)
+  base::TimeDelta dirty_interval = event_time - last_sample_;
+  if (dirty_interval < capture_period_ * 4)
     return false;
   else
     return true;
 }
 
-base::Time SmoothEventSampler::GetLastSampledEvent() {
-  return last_sample_;
+bool SmoothEventSampler::HasUnrecordedEvent() const {
+  return !current_event_.is_null() && current_event_ != last_sample_;
 }
 
 }  // namespace content
diff --git a/content/browser/renderer_host/media/web_contents_video_capture_device.h b/content/browser/renderer_host/media/web_contents_video_capture_device.h
index fe9820b..ec23511 100644
--- a/content/browser/renderer_host/media/web_contents_video_capture_device.h
+++ b/content/browser/renderer_host/media/web_contents_video_capture_device.h
@@ -38,8 +38,7 @@
   // WebContentsVideoCaptureDevice is itself deleted.
   // TODO(miu): Passing a destroy callback suggests needing to revisit the
   // design philosophy of an asynchronous DeAllocate().  http://crbug.com/158641
-  static media::VideoCaptureDevice* Create(const std::string& device_id,
-                                           const base::Closure& destroy_cb);
+  static media::VideoCaptureDevice* Create(const std::string& device_id);
 
   virtual ~WebContentsVideoCaptureDevice();
 
@@ -60,13 +59,13 @@
 
  private:
   class Impl;
+
   WebContentsVideoCaptureDevice(const Name& name,
                                 int render_process_id,
-                                int render_view_id,
-                                const base::Closure& destroy_cb);
+                                int render_view_id);
 
   Name device_name_;
-  scoped_refptr<Impl> capturer_;
+  const scoped_ptr<Impl> impl_;
 
   DISALLOW_COPY_AND_ASSIGN(WebContentsVideoCaptureDevice);
 };
@@ -75,29 +74,38 @@
 class CONTENT_EXPORT SmoothEventSampler {
  public:
   explicit SmoothEventSampler(base::TimeDelta capture_period,
-                              bool events_are_reliable);
+                              bool events_are_reliable,
+                              int redundant_capture_goal);
 
   // Add a new event to the event history, and return whether it ought to be
-  // sampled per to the sampling frequency limit. Even if this method returns
-  // true, the event is not recorded as a sample until RecordSample() is called.
-  bool AddEventAndConsiderSampling(base::Time now);
+  // sampled based on the desired |capture_period|. The event is not recorded as
+  // a sample until RecordSample() is called.
+  bool AddEventAndConsiderSampling(base::Time event_time);
 
   // Operates on the last event added by AddEventAndConsiderSampling(), marking
   // it as sampled. After this point we are current in the stream of events, as
   // we have sampled the most recent event.
   void RecordSample();
 
-  // Returns true if, at time |now|, sampling should occur because too much time
-  // will have passed relative to the last event and/or sample.
-  bool IsOverdueForSamplingAt(base::Time now) const;
+  // Returns true if, at time |event_time|, sampling should occur because too
+  // much time will have passed relative to the last event and/or sample.
+  bool IsOverdueForSamplingAt(base::Time event_time) const;
 
-  base::Time GetLastSampledEvent();
+  // Returns true if AddEventAndConsiderSampling() has been called since the
+  // last call to RecordSample().
+  bool HasUnrecordedEvent() const;
 
  private:
   const bool events_are_reliable_;
   const base::TimeDelta capture_period_;
+  const int redundant_capture_goal_;
+  const base::TimeDelta token_bucket_capacity_;
+
   base::Time current_event_;
   base::Time last_sample_;
+  int overdue_sample_count_;
+  base::TimeDelta token_bucket_;
+
   DISALLOW_COPY_AND_ASSIGN(SmoothEventSampler);
 };
 
diff --git a/content/browser/renderer_host/media/web_contents_video_capture_device_unittest.cc b/content/browser/renderer_host/media/web_contents_video_capture_device_unittest.cc
index b160452..a09ac16 100644
--- a/content/browser/renderer_host/media/web_contents_video_capture_device_unittest.cc
+++ b/content/browser/renderer_host/media/web_contents_video_capture_device_unittest.cc
@@ -7,6 +7,7 @@
 #include "base/bind_helpers.h"
 #include "base/debug/debugger.h"
 #include "base/run_loop.h"
+#include "base/test/test_timeouts.h"
 #include "base/time.h"
 #include "base/timer.h"
 #include "content/browser/browser_thread_impl.h"
@@ -32,10 +33,10 @@
 
 namespace content {
 namespace {
+
 const int kTestWidth = 320;
 const int kTestHeight = 240;
 const int kTestFramesPerSecond = 20;
-const base::TimeDelta kWaitTimeout = base::TimeDelta::FromMilliseconds(10000);
 const SkColor kNothingYet = 0xdeadbeef;
 const SkColor kNotInterested = ~kNothingYet;
 
@@ -51,9 +52,9 @@
 
 void RunCurrentLoopWithDeadline() {
   base::Timer deadline(false, false);
-  deadline.Start(FROM_HERE, kWaitTimeout, base::Bind(
-      &DeadlineExceeded, MessageLoop::current()->QuitClosure()));
-  MessageLoop::current()->Run();
+  deadline.Start(FROM_HERE, TestTimeouts::action_max_timeout(), base::Bind(
+      &DeadlineExceeded, base::MessageLoop::current()->QuitClosure()));
+  base::MessageLoop::current()->Run();
   deadline.Stop();
 }
 
@@ -129,22 +130,12 @@
   void WaitForNextCopy() {
     {
       base::AutoLock guard(lock_);
-      copy_done_ = MessageLoop::current()->QuitClosure();
+      copy_done_ = base::MessageLoop::current()->QuitClosure();
     }
 
     RunCurrentLoopWithDeadline();
   }
 
-  void OnShutdown() {
-    base::AutoLock guard(lock_);
-    BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, shutdown_hook_);
-  }
-
-  void SetShutdownHook(base::Closure shutdown_hook) {
-    base::AutoLock guard(lock_);
-    shutdown_hook_ = shutdown_hook;
-  }
-
  private:
   base::Lock lock_;  // Guards changes to all members.
   SkColor color_;
@@ -152,7 +143,6 @@
   bool can_copy_to_video_frame_;
   bool use_frame_subscriber_;
   base::Closure copy_done_;
-  base::Closure shutdown_hook_;
 
   DISALLOW_COPY_AND_ASSIGN(CaptureTestSourceController);
 };
@@ -167,6 +157,7 @@
                            CaptureTestSourceController* controller)
       : TestRenderWidgetHostView(rwh),
         controller_(controller) {}
+
   virtual ~CaptureTestView() {}
 
   // TestRenderWidgetHostView overrides.
@@ -199,13 +190,15 @@
 
   // Simulate a compositor paint event for our subscriber.
   void SimulateUpdate() {
+    const base::Time present_time = base::Time::Now();
     RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback callback;
     scoped_refptr<media::VideoFrame> target;
-    if (subscriber_ && subscriber_->ShouldCaptureFrame(&target, &callback)) {
+    if (subscriber_ && subscriber_->ShouldCaptureFrame(present_time,
+                                                       &target, &callback)) {
       SkColor c = ConvertRgbToYuv(controller_->GetSolidColor());
       media::FillYUV(target, SkColorGetR(c), SkColorGetG(c), SkColorGetB(c));
       BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
-          base::Bind(callback, base::Time::Now(), true));
+          base::Bind(callback, present_time, true));
       controller_->SignalCopy();
     }
   }
@@ -321,7 +314,7 @@
     base::AutoLock guard(lock_);
 
     if (wait_color_yuv_ == color || error_encountered_)
-      MessageLoop::current()->Quit();
+      base::MessageLoop::current()->Quit();
   }
 
   void WaitForNextColor(SkColor expected_color) {
@@ -350,6 +343,11 @@
     }
   }
 
+  bool HasError() {
+    base::AutoLock guard(lock_);
+    return error_encountered_;
+  }
+
   virtual scoped_refptr<media::VideoFrame> ReserveOutputBuffer() OVERRIDE {
     return buffer_pool_->ReserveForProducer(0);
   }
@@ -409,8 +407,6 @@
   DISALLOW_COPY_AND_ASSIGN(StubConsumer);
 };
 
-}  // namespace
-
 // Test harness that sets up a minimal environment with necessary stubs.
 class WebContentsVideoCaptureDeviceTest : public testing::Test {
  public:
@@ -458,11 +454,7 @@
             base::StringPrintf("%d:%d", rwh->GetProcess()->GetID(),
                                rwh->GetRoutingID()));
 
-    base::Closure destroy_cb = base::Bind(
-        &CaptureTestSourceController::OnShutdown,
-        base::Unretained(&controller_));
-
-    device_.reset(WebContentsVideoCaptureDevice::Create(device_id, destroy_cb));
+    device_.reset(WebContentsVideoCaptureDevice::Create(device_id));
 
     content::RunAllPendingInMessageLoop();
   }
@@ -473,11 +465,10 @@
     // The device is destroyed asynchronously, and will notify the
     // CaptureTestSourceController when it finishes destruction.
     // Trigger this, and wait.
-    base::RunLoop shutdown_loop;
-    controller_.SetShutdownHook(shutdown_loop.QuitClosure());
-    device_->DeAllocate();
-    device_.reset();
-    shutdown_loop.Run();
+    if (device_) {
+      device_->DeAllocate();
+      device_.reset();
+    }
 
     content::RunAllPendingInMessageLoop();
 
@@ -511,6 +502,8 @@
     }
   }
 
+  void DestroyVideoCaptureDevice() { device_.reset(); }
+
  private:
   // The consumer is the ultimate recipient of captured pixel data.
   StubConsumer consumer_;
@@ -520,7 +513,7 @@
 
   // We run the UI message loop on the main thread. The capture device
   // will also spin up its own threads.
-  MessageLoopForUI message_loop_;
+  base::MessageLoopForUI message_loop_;
   scoped_ptr<TestBrowserThread> ui_thread_;
 
   // Self-registering RenderProcessHostFactory.
@@ -574,6 +567,76 @@
   device()->DeAllocate();
 }
 
+TEST_F(WebContentsVideoCaptureDeviceTest,
+       StopDeviceBeforeCaptureMachineCreation) {
+  device()->Allocate(kTestWidth, kTestHeight, kTestFramesPerSecond, consumer());
+  device()->Start();
+  // Make a point of not running the UI messageloop here.
+  device()->Stop();
+  device()->DeAllocate();
+  DestroyVideoCaptureDevice();
+
+  // Currently, there should be CreateCaptureMachineOnUIThread() and
+  // DestroyCaptureMachineOnUIThread() tasks pending on the current (UI) message
+  // loop. These should both succeed without crashing, and the machine should
+  // wind up in the idle state.
+  content::RunAllPendingInMessageLoop();
+}
+
+TEST_F(WebContentsVideoCaptureDeviceTest, StopWithRendererWorkToDo) {
+  // Set up the test to use RGB copies and an normal
+  source()->SetCanCopyToVideoFrame(false);
+  source()->SetUseFrameSubscriber(false);
+  device()->Allocate(kTestWidth, kTestHeight, kTestFramesPerSecond,
+                     consumer());
+  device()->Start();
+  // Make a point of not running the UI messageloop here.
+  content::RunAllPendingInMessageLoop();
+
+  for (int i = 0; i < 10; ++i)
+    SimulateDrawEvent();
+
+  device()->Stop();
+  device()->DeAllocate();
+  // Currently, there should be CreateCaptureMachineOnUIThread() and
+  // DestroyCaptureMachineOnUIThread() tasks pending on the current message
+  // loop. These should both succeed without crashing, and the machine should
+  // wind up in the idle state.
+  ASSERT_FALSE(consumer()->HasError());
+  content::RunAllPendingInMessageLoop();
+  ASSERT_FALSE(consumer()->HasError());
+}
+
+TEST_F(WebContentsVideoCaptureDeviceTest, DeviceRestart) {
+  device()->Allocate(kTestWidth, kTestHeight, kTestFramesPerSecond, consumer());
+  device()->Start();
+  content::RunAllPendingInMessageLoop();
+  source()->SetSolidColor(SK_ColorRED);
+  SimulateDrawEvent();
+  SimulateDrawEvent();
+  ASSERT_NO_FATAL_FAILURE(consumer()->WaitForNextColor(SK_ColorRED));
+  SimulateDrawEvent();
+  SimulateDrawEvent();
+  source()->SetSolidColor(SK_ColorGREEN);
+  SimulateDrawEvent();
+  ASSERT_NO_FATAL_FAILURE(consumer()->WaitForNextColor(SK_ColorGREEN));
+  device()->Stop();
+
+  // Device is stopped, but content can still be animating.
+  SimulateDrawEvent();
+  SimulateDrawEvent();
+  content::RunAllPendingInMessageLoop();
+
+  device()->Start();
+  source()->SetSolidColor(SK_ColorBLUE);
+  SimulateDrawEvent();
+  ASSERT_NO_FATAL_FAILURE(consumer()->WaitForNextColor(SK_ColorBLUE));
+  source()->SetSolidColor(SK_ColorYELLOW);
+  SimulateDrawEvent();
+  ASSERT_NO_FATAL_FAILURE(consumer()->WaitForNextColor(SK_ColorYELLOW));
+  device()->DeAllocate();
+}
+
 // The "happy case" test.  No scaling is needed, so we should be able to change
 // the picture emitted from the source and expect to see each delivered to the
 // consumer. The test will alternate between the three capture paths, simulating
@@ -660,30 +723,211 @@
   device()->DeAllocate();
 }
 
-// 60Hz sampled at 30Hz should produce 30Hz.
+void SteadyStateSampleAndAdvance(base::TimeDelta vsync,
+                                 SmoothEventSampler* sampler, base::Time* t) {
+  ASSERT_TRUE(sampler->AddEventAndConsiderSampling(*t));
+  ASSERT_TRUE(sampler->HasUnrecordedEvent());
+  sampler->RecordSample();
+  ASSERT_FALSE(sampler->HasUnrecordedEvent());
+  ASSERT_FALSE(sampler->IsOverdueForSamplingAt(*t));
+  *t += vsync;
+  ASSERT_FALSE(sampler->IsOverdueForSamplingAt(*t));
+}
+
+void SteadyStateNoSampleAndAdvance(base::TimeDelta vsync,
+                                   SmoothEventSampler* sampler, base::Time* t) {
+  ASSERT_FALSE(sampler->AddEventAndConsiderSampling(*t));
+  ASSERT_TRUE(sampler->HasUnrecordedEvent());
+  ASSERT_FALSE(sampler->IsOverdueForSamplingAt(*t));
+  *t += vsync;
+  ASSERT_FALSE(sampler->IsOverdueForSamplingAt(*t));
+}
+
+void TestRedundantCaptureStrategy(base::TimeDelta capture_period,
+                                  int redundant_capture_goal,
+                                  SmoothEventSampler* sampler, base::Time* t) {
+  // Before any events have been considered, we're overdue for sampling.
+  ASSERT_TRUE(sampler->IsOverdueForSamplingAt(*t));
+
+  // Consider the first event.  We want to sample that.
+  ASSERT_FALSE(sampler->HasUnrecordedEvent());
+  ASSERT_TRUE(sampler->AddEventAndConsiderSampling(*t));
+  ASSERT_TRUE(sampler->HasUnrecordedEvent());
+  sampler->RecordSample();
+  ASSERT_FALSE(sampler->HasUnrecordedEvent());
+
+  // After more than one capture period has passed without considering an event,
+  // we should repeatedly be overdue for sampling.  However, once the redundant
+  // capture goal is achieved, we should no longer be overdue for sampling.
+  *t += capture_period * 4;
+  for (int i = 0; i < redundant_capture_goal; i++) {
+    SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
+    ASSERT_FALSE(sampler->HasUnrecordedEvent());
+    ASSERT_TRUE(sampler->IsOverdueForSamplingAt(*t))
+        << "Should sample until redundant capture goal is hit";
+    sampler->RecordSample();
+    *t += capture_period;  // Timer fires once every capture period.
+  }
+  ASSERT_FALSE(sampler->IsOverdueForSamplingAt(*t))
+      << "Should not be overdue once redundant capture goal achieved.";
+}
+
+// 60Hz sampled at 30Hz should produce 30Hz.  In addition, this test contains
+// much more comprehensive before/after/edge-case scenarios than the others.
 TEST(SmoothEventSamplerTest, Sample60HertzAt30Hertz) {
-  SmoothEventSampler sampler(base::TimeDelta::FromSeconds(1) / 30, true);
+  const base::TimeDelta capture_period = base::TimeDelta::FromSeconds(1) / 30;
+  const int redundant_capture_goal = 200;
   const base::TimeDelta vsync = base::TimeDelta::FromSeconds(1) / 60;
 
+  SmoothEventSampler sampler(capture_period, true, redundant_capture_goal);
   base::Time t;
   ASSERT_TRUE(base::Time::FromString("Sat, 23 Mar 2013 1:21:08 GMT", &t));
-  ASSERT_TRUE(sampler.IsOverdueForSamplingAt(t))
-      << "First timer event should sample.";
-  sampler.RecordSample();
-  ASSERT_TRUE(sampler.IsOverdueForSamplingAt(t))
-      << "Should always be overdue until first paint.";
+
+  TestRedundantCaptureStrategy(capture_period, redundant_capture_goal,
+                               &sampler, &t);
 
   // Steady state, we should capture every other vsync, indefinitely.
   for (int i = 0; i < 100; i++) {
     SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
-    ASSERT_TRUE(sampler.AddEventAndConsiderSampling(t));
-    sampler.RecordSample();
-    t += vsync;
+    SteadyStateSampleAndAdvance(vsync, &sampler, &t);
+    SteadyStateNoSampleAndAdvance(vsync, &sampler, &t);
+  }
 
-    ASSERT_FALSE(sampler.AddEventAndConsiderSampling(t));
+  // Now pretend we're limited by backpressure in the pipeline. In this scenario
+  // case we are adding events but not sampling them.
+  for (int i = 0; i < 20; i++) {
+    SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
+    ASSERT_EQ(i >= 7, sampler.IsOverdueForSamplingAt(t));
+    ASSERT_TRUE(sampler.AddEventAndConsiderSampling(t));
+    ASSERT_TRUE(sampler.HasUnrecordedEvent());
     t += vsync;
   }
 
+  // Now suppose we can sample again. We should be back in the steady state,
+  // but at a different phase.
+  ASSERT_TRUE(sampler.IsOverdueForSamplingAt(t));
+  for (int i = 0; i < 100; i++) {
+    SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
+    SteadyStateSampleAndAdvance(vsync, &sampler, &t);
+    SteadyStateNoSampleAndAdvance(vsync, &sampler, &t);
+  }
+}
+
+// 50Hz sampled at 30Hz should produce a sequence where some frames are skipped.
+TEST(SmoothEventSamplerTest, Sample50HertzAt30Hertz) {
+  const base::TimeDelta capture_period = base::TimeDelta::FromSeconds(1) / 30;
+  const int redundant_capture_goal = 2;
+  const base::TimeDelta vsync = base::TimeDelta::FromSeconds(1) / 50;
+
+  SmoothEventSampler sampler(capture_period, true, redundant_capture_goal);
+  base::Time t;
+  ASSERT_TRUE(base::Time::FromString("Sat, 23 Mar 2013 1:21:08 GMT", &t));
+
+  TestRedundantCaptureStrategy(capture_period, redundant_capture_goal,
+                               &sampler, &t);
+
+  // Steady state, we should capture 1st, 2nd and 4th frames out of every five
+  // frames, indefinitely.
+  for (int i = 0; i < 100; i++) {
+    SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
+    SteadyStateSampleAndAdvance(vsync, &sampler, &t);
+    SteadyStateSampleAndAdvance(vsync, &sampler, &t);
+    SteadyStateNoSampleAndAdvance(vsync, &sampler, &t);
+    SteadyStateSampleAndAdvance(vsync, &sampler, &t);
+    SteadyStateNoSampleAndAdvance(vsync, &sampler, &t);
+  }
+
+  // Now pretend we're limited by backpressure in the pipeline. In this scenario
+  // case we are adding events but not sampling them.
+  for (int i = 0; i < 12; i++) {
+    SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
+    ASSERT_EQ(i >= 5, sampler.IsOverdueForSamplingAt(t));
+    ASSERT_TRUE(sampler.AddEventAndConsiderSampling(t));
+    t += vsync;
+  }
+
+  // Now suppose we can sample again. We should be back in the steady state
+  // again.
+  ASSERT_TRUE(sampler.IsOverdueForSamplingAt(t));
+  for (int i = 0; i < 100; i++) {
+    SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
+    SteadyStateSampleAndAdvance(vsync, &sampler, &t);
+    SteadyStateSampleAndAdvance(vsync, &sampler, &t);
+    SteadyStateNoSampleAndAdvance(vsync, &sampler, &t);
+    SteadyStateSampleAndAdvance(vsync, &sampler, &t);
+    SteadyStateNoSampleAndAdvance(vsync, &sampler, &t);
+  }
+}
+
+// 75Hz sampled at 30Hz should produce a sequence where some frames are skipped.
+TEST(SmoothEventSamplerTest, Sample75HertzAt30Hertz) {
+  const base::TimeDelta capture_period = base::TimeDelta::FromSeconds(1) / 30;
+  const int redundant_capture_goal = 32;
+  const base::TimeDelta vsync = base::TimeDelta::FromSeconds(1) / 75;
+
+  SmoothEventSampler sampler(capture_period, true, redundant_capture_goal);
+  base::Time t;
+  ASSERT_TRUE(base::Time::FromString("Sat, 23 Mar 2013 1:21:08 GMT", &t));
+
+  TestRedundantCaptureStrategy(capture_period, redundant_capture_goal,
+                               &sampler, &t);
+
+  // Steady state, we should capture 1st and 3rd frames out of every five
+  // frames, indefinitely.
+  SteadyStateSampleAndAdvance(vsync, &sampler, &t);
+  SteadyStateNoSampleAndAdvance(vsync, &sampler, &t);
+  for (int i = 0; i < 100; i++) {
+    SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
+    SteadyStateSampleAndAdvance(vsync, &sampler, &t);
+    SteadyStateNoSampleAndAdvance(vsync, &sampler, &t);
+    SteadyStateSampleAndAdvance(vsync, &sampler, &t);
+    SteadyStateNoSampleAndAdvance(vsync, &sampler, &t);
+    SteadyStateNoSampleAndAdvance(vsync, &sampler, &t);
+  }
+
+  // Now pretend we're limited by backpressure in the pipeline. In this scenario
+  // case we are adding events but not sampling them.
+  for (int i = 0; i < 20; i++) {
+    SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
+    ASSERT_EQ(i >= 8, sampler.IsOverdueForSamplingAt(t));
+    ASSERT_TRUE(sampler.AddEventAndConsiderSampling(t));
+    t += vsync;
+  }
+
+  // Now suppose we can sample again. We capture the next frame, and not the one
+  // after that, and then we're back in the steady state again.
+  ASSERT_TRUE(sampler.IsOverdueForSamplingAt(t));
+  SteadyStateSampleAndAdvance(vsync, &sampler, &t);
+  SteadyStateNoSampleAndAdvance(vsync, &sampler, &t);
+  for (int i = 0; i < 100; i++) {
+    SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
+    SteadyStateSampleAndAdvance(vsync, &sampler, &t);
+    SteadyStateNoSampleAndAdvance(vsync, &sampler, &t);
+    SteadyStateSampleAndAdvance(vsync, &sampler, &t);
+    SteadyStateNoSampleAndAdvance(vsync, &sampler, &t);
+    SteadyStateNoSampleAndAdvance(vsync, &sampler, &t);
+  }
+}
+
+// 30Hz sampled at 30Hz should produce 30Hz.
+TEST(SmoothEventSamplerTest, Sample30HertzAt30Hertz) {
+  const base::TimeDelta capture_period = base::TimeDelta::FromSeconds(1) / 30;
+  const int redundant_capture_goal = 1;
+  const base::TimeDelta vsync = base::TimeDelta::FromSeconds(1) / 30;
+
+  SmoothEventSampler sampler(capture_period, true, redundant_capture_goal);
+  base::Time t;
+  ASSERT_TRUE(base::Time::FromString("Sat, 23 Mar 2013 1:21:08 GMT", &t));
+
+  TestRedundantCaptureStrategy(capture_period, redundant_capture_goal,
+                               &sampler, &t);
+
+  // Steady state, we should capture every vsync, indefinitely.
+  for (int i = 0; i < 200; i++) {
+    SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
+    SteadyStateSampleAndAdvance(vsync, &sampler, &t);
+  }
+
   // Now pretend we're limited by backpressure in the pipeline. In this scenario
   // case we are adding events but not sampling them.
   for (int i = 0; i < 7; i++) {
@@ -693,139 +937,38 @@
     t += vsync;
   }
 
-  // Now suppose we can sample again. We should be back in the steady state,
-  // but at a different phase.
-  ASSERT_TRUE(sampler.IsOverdueForSamplingAt(t));
-  for (int i = 0; i < 100; i++) {
-    SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
-    ASSERT_TRUE(sampler.AddEventAndConsiderSampling(t));
-    sampler.RecordSample();
-    t += vsync;
-    ASSERT_FALSE(sampler.IsOverdueForSamplingAt(t));
-
-    ASSERT_FALSE(sampler.AddEventAndConsiderSampling(t));
-    t += vsync;
-    ASSERT_FALSE(sampler.IsOverdueForSamplingAt(t));
-  }
-}
-
-// 50Hz sampled at 30Hz should produce 25Hz.
-TEST(SmoothEventSamplerTest, Sample50HertzAt30Hertz) {
-  SmoothEventSampler sampler(base::TimeDelta::FromSeconds(1) / 30, true);
-  const base::TimeDelta vsync = base::TimeDelta::FromSeconds(1) / 50;
-
-  base::Time t;
-  ASSERT_TRUE(base::Time::FromString("Sat, 23 Mar 2013 1:21:08 GMT", &t));
-  ASSERT_TRUE(sampler.IsOverdueForSamplingAt(t))
-      << "First timer event should sample.";
-  sampler.RecordSample();
-  ASSERT_TRUE(sampler.IsOverdueForSamplingAt(t))
-      << "Should always be overdue until first paint.";
-
-  // Steady state, we should capture every other vsync, indefinitely.
-  for (int i = 0; i < 100; i++) {
-    SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
-    ASSERT_TRUE(sampler.AddEventAndConsiderSampling(t));
-    sampler.RecordSample();
-    t += vsync;
-
-    ASSERT_FALSE(sampler.AddEventAndConsiderSampling(t));
-    t += vsync;
-  }
-
-  // Now pretend we're limited by backpressure in the pipeline. In this scenario
-  // case we are adding events but not sampling them.
-  for (int i = 0; i < 7; i++) {
-    SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
-    ASSERT_EQ(i >= 2, sampler.IsOverdueForSamplingAt(t));
-    ASSERT_TRUE(sampler.AddEventAndConsiderSampling(t));
-    t += vsync;
-  }
-
-  // Now suppose we can sample again. We should be back in the steady state,
-  // but at a different phase.
-  ASSERT_TRUE(sampler.IsOverdueForSamplingAt(t));
-  for (int i = 0; i < 100; i++) {
-    SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
-    ASSERT_TRUE(sampler.AddEventAndConsiderSampling(t));
-    sampler.RecordSample();
-    t += vsync;
-    ASSERT_FALSE(sampler.IsOverdueForSamplingAt(t));
-
-    ASSERT_FALSE(sampler.AddEventAndConsiderSampling(t));
-    t += vsync;
-    ASSERT_FALSE(sampler.IsOverdueForSamplingAt(t));
-  }
-}
-
-// 30Hz sampled at 30Hz should produce 30Hz.
-TEST(SmoothEventSamplerTest, Sample30HertzAt30Hertz) {
-  SmoothEventSampler sampler(base::TimeDelta::FromSeconds(1) / 30, true);
-  const base::TimeDelta vsync = base::TimeDelta::FromSeconds(1) / 30;
-
-  base::Time t;
-  ASSERT_TRUE(base::Time::FromString("Sat, 23 Mar 2013 1:21:08 GMT", &t));
-  ASSERT_TRUE(sampler.IsOverdueForSamplingAt(t))
-      << "First timer event should sample.";
-  sampler.RecordSample();
-  ASSERT_TRUE(sampler.IsOverdueForSamplingAt(t))
-      << "Should always be overdue until first paint.";
-
-  // Steady state, we should capture every vsync, indefinitely.
-  for (int i = 0; i < 200; i++) {
-    SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
-    ASSERT_TRUE(sampler.AddEventAndConsiderSampling(t));
-    sampler.RecordSample();
-    t += vsync;
-  }
-
-  // Now pretend we're limited by backpressure in the pipeline. In this scenario
-  // case we are adding events but not sampling them.
-  for (int i = 0; i < 7; i++) {
-    SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
-    ASSERT_EQ(i >= 1, sampler.IsOverdueForSamplingAt(t));
-    ASSERT_TRUE(sampler.AddEventAndConsiderSampling(t));
-    t += vsync;
-  }
-
   // Now suppose we can sample again. We should be back in the steady state.
   ASSERT_TRUE(sampler.IsOverdueForSamplingAt(t));
   for (int i = 0; i < 100; i++) {
     SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
-    ASSERT_TRUE(sampler.AddEventAndConsiderSampling(t));
-    sampler.RecordSample();
-    t += vsync;
-    ASSERT_FALSE(sampler.IsOverdueForSamplingAt(t));
+    SteadyStateSampleAndAdvance(vsync, &sampler, &t);
   }
 }
 
-
 // 24Hz sampled at 30Hz should produce 24Hz.
 TEST(SmoothEventSamplerTest, Sample24HertzAt30Hertz) {
-  SmoothEventSampler sampler(base::TimeDelta::FromSeconds(1) / 30, true);
+  const base::TimeDelta capture_period = base::TimeDelta::FromSeconds(1) / 30;
+  const int redundant_capture_goal = 333;
   const base::TimeDelta vsync = base::TimeDelta::FromSeconds(1) / 24;
 
+  SmoothEventSampler sampler(capture_period, true, redundant_capture_goal);
   base::Time t;
   ASSERT_TRUE(base::Time::FromString("Sat, 23 Mar 2013 1:21:08 GMT", &t));
-  ASSERT_TRUE(sampler.IsOverdueForSamplingAt(t))
-      << "First timer event should sample.";
-  sampler.RecordSample();
-  ASSERT_TRUE(sampler.IsOverdueForSamplingAt(t))
-      << "Should always be overdue until first paint.";
+
+  TestRedundantCaptureStrategy(capture_period, redundant_capture_goal,
+                               &sampler, &t);
 
   // Steady state, we should capture every vsync, indefinitely.
   for (int i = 0; i < 200; i++) {
     SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
-    ASSERT_TRUE(sampler.AddEventAndConsiderSampling(t));
-    sampler.RecordSample();
-    t += vsync;
+    SteadyStateSampleAndAdvance(vsync, &sampler, &t);
   }
 
   // Now pretend we're limited by backpressure in the pipeline. In this scenario
   // case we are adding events but not sampling them.
   for (int i = 0; i < 7; i++) {
     SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
-    ASSERT_EQ(i >= 1, sampler.IsOverdueForSamplingAt(t));
+    ASSERT_EQ(i >= 3, sampler.IsOverdueForSamplingAt(t));
     ASSERT_TRUE(sampler.AddEventAndConsiderSampling(t));
     t += vsync;
   }
@@ -834,24 +977,23 @@
   ASSERT_TRUE(sampler.IsOverdueForSamplingAt(t));
   for (int i = 0; i < 100; i++) {
     SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
-    ASSERT_TRUE(sampler.AddEventAndConsiderSampling(t));
-    sampler.RecordSample();
-    t += vsync;
-    ASSERT_FALSE(sampler.IsOverdueForSamplingAt(t));
+    SteadyStateSampleAndAdvance(vsync, &sampler, &t);
   }
 }
 
 TEST(SmoothEventSamplerTest, DoubleDrawAtOneTimeStillDirties) {
-  SmoothEventSampler sampler(base::TimeDelta::FromSeconds(1) / 30, true);
+  const base::TimeDelta capture_period = base::TimeDelta::FromSeconds(1) / 30;
   const base::TimeDelta overdue_period = base::TimeDelta::FromSeconds(1);
 
+  SmoothEventSampler sampler(capture_period, true, 1);
   base::Time t;
   ASSERT_TRUE(base::Time::FromString("Sat, 23 Mar 2013 1:21:08 GMT", &t));
+
   ASSERT_TRUE(sampler.AddEventAndConsiderSampling(t));
   sampler.RecordSample();
-  t += overdue_period;
   ASSERT_FALSE(sampler.IsOverdueForSamplingAt(t))
       << "Sampled last event; should not be dirty.";
+  t += overdue_period;
 
   // Now simulate 2 events with the same clock value.
   ASSERT_TRUE(sampler.AddEventAndConsiderSampling(t));
@@ -866,32 +1008,49 @@
 
 TEST(SmoothEventSamplerTest, FallbackToPollingIfUpdatesUnreliable) {
   const base::TimeDelta timer_interval = base::TimeDelta::FromSeconds(1) / 30;
-  SmoothEventSampler should_not_poll(timer_interval, true);
-  SmoothEventSampler should_poll(timer_interval, false);
 
+  SmoothEventSampler should_not_poll(timer_interval, true, 1);
+  SmoothEventSampler should_poll(timer_interval, false, 1);
   base::Time t;
   ASSERT_TRUE(base::Time::FromString("Sat, 23 Mar 2013 1:21:08 GMT", &t));
+
+  // Do one round of the "happy case" where an event was received and
+  // RecordSample() was called by the client.
   ASSERT_TRUE(should_not_poll.AddEventAndConsiderSampling(t));
   ASSERT_TRUE(should_poll.AddEventAndConsiderSampling(t));
   should_not_poll.RecordSample();
   should_poll.RecordSample();
+
+  // One time period ahead, neither sampler says we're overdue.
+  for (int i = 0; i < 3; i++) {
+    t += timer_interval;
+    ASSERT_FALSE(should_not_poll.IsOverdueForSamplingAt(t))
+        << "Sampled last event; should not be dirty.";
+    ASSERT_FALSE(should_poll.IsOverdueForSamplingAt(t))
+        << "Dirty interval has not elapsed yet.";
+  }
+
+  // Next time period ahead, both samplers say we're overdue.  The non-polling
+  // sampler is returning true here because it has been configured to allow one
+  // redundant capture.
   t += timer_interval;
-  ASSERT_FALSE(should_not_poll.IsOverdueForSamplingAt(t))
-      << "Sampled last event; should not be dirty.";
-  ASSERT_FALSE(should_poll.IsOverdueForSamplingAt(t))
-      << "Dirty interval has not elapsed yet.";
-  t += timer_interval;
-  ASSERT_FALSE(should_not_poll.IsOverdueForSamplingAt(t))
-      << "Sampled last event; should not be dirty.";
+  ASSERT_TRUE(should_not_poll.IsOverdueForSamplingAt(t))
+      << "Sampled last event; is dirty one time only to meet redundancy goal.";
   ASSERT_TRUE(should_poll.IsOverdueForSamplingAt(t))
       << "If updates are unreliable, must fall back to polling when idle.";
+  should_not_poll.RecordSample();
   should_poll.RecordSample();
-  t += timer_interval;
-  ASSERT_FALSE(should_not_poll.IsOverdueForSamplingAt(t))
-      << "Sampled last event; should not be dirty.";
-  ASSERT_TRUE(should_poll.IsOverdueForSamplingAt(t))
-      << "If updates are unreliable, must fall back to polling when idle.";
-  should_poll.RecordSample();
+
+  // Forever more, the non-polling sampler returns false while the polling one
+  // returns true.
+  for (int i = 0; i < 100; ++i) {
+    t += timer_interval;
+    ASSERT_FALSE(should_not_poll.IsOverdueForSamplingAt(t))
+        << "Sampled last event; should not be dirty.";
+    ASSERT_TRUE(should_poll.IsOverdueForSamplingAt(t))
+        << "If updates are unreliable, must fall back to polling when idle.";
+    should_poll.RecordSample();
+  }
   t += timer_interval / 3;
   ASSERT_FALSE(should_not_poll.IsOverdueForSamplingAt(t))
       << "Sampled last event; should not be dirty.";
@@ -900,5 +1059,132 @@
   should_poll.RecordSample();
 }
 
-}  // namespace content
+struct DataPoint {
+  bool should_capture;
+  double increment_ms;
+};
 
+void ReplayCheckingSamplerDecisions(const DataPoint* data_points,
+                                    size_t num_data_points,
+                                    SmoothEventSampler* sampler) {
+  base::Time t;
+  ASSERT_TRUE(base::Time::FromString("Sat, 23 Mar 2013 1:21:08 GMT", &t));
+  for (size_t i = 0; i < num_data_points; ++i) {
+    t += base::TimeDelta::FromMicroseconds(
+        static_cast<int64>(data_points[i].increment_ms * 1000));
+    ASSERT_EQ(data_points[i].should_capture,
+              sampler->AddEventAndConsiderSampling(t))
+        << "at data_points[" << i << ']';
+    if (data_points[i].should_capture)
+      sampler->RecordSample();
+  }
+}
+
+TEST(SmoothEventSamplerTest, DrawingAt24FpsWith60HzVsyncSampledAt30Hertz) {
+  // Actual capturing of timing data: Initial instability as a 24 FPS video was
+  // started from a still screen, then clearly followed by steady-state.
+  static const DataPoint data_points[] = {
+    { true, 1437.93 }, { true, 150.484 }, { true, 217.362 }, { true, 50.161 },
+    { true, 33.44 }, { false, 0 }, { true, 16.721 }, { true, 66.88 },
+    { true, 50.161 }, { false, 0 }, { false, 0 }, { true, 50.16 },
+    { true, 33.441 }, { true, 16.72 }, { false, 16.72 }, { true, 117.041 },
+    { true, 16.72 }, { false, 16.72 }, { true, 50.161 }, { true, 50.16 },
+    { true, 33.441 }, { true, 33.44 }, { true, 33.44 }, { true, 16.72 },
+    { false, 0 }, { true, 50.161 }, { false, 0 }, { true, 33.44 },
+    { true, 16.72 }, { false, 16.721 }, { true, 66.881 }, { false, 0 },
+    { true, 33.441 }, { true, 16.72 }, { true, 50.16 }, { true, 16.72 },
+    { false, 16.721 }, { true, 50.161 }, { true, 50.16 }, { false, 0 },
+    { true, 33.441 }, { true, 50.337 }, { true, 50.183 }, { true, 16.722 },
+    { true, 50.161 }, { true, 33.441 }, { true, 50.16 }, { true, 33.441 },
+    { true, 50.16 }, { true, 33.441 }, { true, 50.16 }, { true, 33.44 },
+    { true, 50.161 }, { true, 50.16 }, { true, 33.44 }, { true, 33.441 },
+    { true, 50.16 }, { true, 50.161 }, { true, 33.44 }, { true, 33.441 },
+    { true, 50.16 }, { true, 33.44 }, { true, 50.161 }, { true, 33.44 },
+    { true, 50.161 }, { true, 33.44 }, { true, 50.161 }, { true, 33.44 },
+    { true, 83.601 }, { true, 16.72 }, { true, 33.44 }, { false, 0 }
+  };
+
+  SmoothEventSampler sampler(base::TimeDelta::FromSeconds(1) / 30, true, 3);
+  ReplayCheckingSamplerDecisions(data_points, arraysize(data_points), &sampler);
+}
+
+TEST(SmoothEventSamplerTest, DrawingAt30FpsWith60HzVsyncSampledAt30Hertz) {
+  // Actual capturing of timing data: Initial instability as a 30 FPS video was
+  // started from a still screen, then followed by steady-state.  Drawing
+  // framerate from the video rendering was a bit volatile, but averaged 30 FPS.
+  static const DataPoint data_points[] = {
+    { true, 2407.69 }, { true, 16.733 }, { true, 217.362 }, { true, 33.441 },
+    { true, 33.44 }, { true, 33.44 }, { true, 33.441 }, { true, 33.44 },
+    { true, 33.44 }, { true, 33.441 }, { true, 33.44 }, { true, 33.44 },
+    { true, 16.721 }, { true, 33.44 }, { false, 0 }, { true, 50.161 },
+    { true, 50.16 }, { false, 0 }, { true, 50.161 }, { true, 33.44 },
+    { true, 16.72 }, { false, 0 }, { false, 16.72 }, { true, 66.881 },
+    { false, 0 }, { true, 33.44 }, { true, 16.72 }, { true, 50.161 },
+    { false, 0 }, { true, 33.538 }, { true, 33.526 }, { true, 33.447 },
+    { true, 33.445 }, { true, 33.441 }, { true, 16.721 }, { true, 33.44 },
+    { true, 33.44 }, { true, 50.161 }, { true, 16.72 }, { true, 33.44 },
+    { true, 33.441 }, { true, 33.44 }, { false, 0 }, { false, 16.72 },
+    { true, 66.881 }, { true, 16.72 }, { false, 16.72 }, { true, 50.16 },
+    { true, 33.441 }, { true, 33.44 }, { true, 33.44 }, { true, 33.44 },
+    { true, 33.441 }, { true, 33.44 }, { true, 50.161 }, { false, 0 },
+    { true, 33.44 }, { true, 33.44 }, { true, 50.161 }, { true, 16.72 },
+    { true, 33.44 }, { true, 33.441 }, { false, 0 }, { true, 66.88 },
+    { true, 33.441 }, { true, 33.44 }, { true, 33.44 }, { false, 0 },
+    { true, 33.441 }, { true, 33.44 }, { true, 33.44 }, { false, 0 },
+    { true, 16.72 }, { true, 50.161 }, { false, 0 }, { true, 50.16 },
+    { false, 0.001 }, { true, 16.721 }, { true, 66.88 }, { true, 33.44 },
+    { true, 33.441 }, { true, 33.44 }, { true, 50.161 }, { true, 16.72 },
+    { false, 0 }, { true, 33.44 }, { false, 16.72 }, { true, 66.881 },
+    { true, 33.44 }, { true, 16.72 }, { true, 33.441 }, { false, 16.72 },
+    { true, 66.88 }, { true, 16.721 }, { true, 50.16 }, { true, 33.44 },
+    { true, 16.72 }, { true, 33.441 }, { true, 33.44 }, { true, 33.44 }
+  };
+
+  SmoothEventSampler sampler(base::TimeDelta::FromSeconds(1) / 30, true, 3);
+  ReplayCheckingSamplerDecisions(data_points, arraysize(data_points), &sampler);
+}
+
+TEST(SmoothEventSamplerTest, DrawingAt60FpsWith60HzVsyncSampledAt30Hertz) {
+  // Actual capturing of timing data: WebGL Acquarium demo
+  // (http://webglsamples.googlecode.com/hg/aquarium/aquarium.html) which ran
+  // between 55-60 FPS in the steady-state.
+  static const DataPoint data_points[] = {
+    { true, 16.72 }, { true, 16.72 }, { true, 4163.29 }, { true, 50.193 },
+    { true, 117.041 }, { true, 50.161 }, { true, 50.16 }, { true, 33.441 },
+    { true, 50.16 }, { true, 33.44 }, { false, 0 }, { false, 0 },
+    { true, 50.161 }, { true, 83.601 }, { true, 50.16 }, { true, 16.72 },
+    { true, 33.441 }, { false, 16.72 }, { true, 50.16 }, { true, 16.72 },
+    { false, 0.001 }, { true, 33.441 }, { false, 16.72 }, { true, 16.72 },
+    { true, 50.16 }, { false, 0 }, { true, 16.72 }, { true, 33.441 },
+    { false, 0 }, { true, 33.44 }, { false, 16.72 }, { true, 16.72 },
+    { true, 50.161 }, { false, 0 }, { true, 16.72 }, { true, 33.44 },
+    { false, 0 }, { true, 33.44 }, { false, 16.721 }, { true, 16.721 },
+    { true, 50.161 }, { false, 0 }, { true, 16.72 }, { true, 33.441 },
+    { false, 0 }, { true, 33.44 }, { false, 16.72 }, { true, 33.44 },
+    { false, 0 }, { true, 16.721 }, { true, 50.161 }, { false, 0 },
+    { true, 33.44 }, { false, 0 }, { true, 16.72 }, { true, 33.441 },
+    { false, 0 }, { true, 33.44 }, { false, 16.72 }, { true, 16.72 },
+    { true, 50.16 }, { false, 0 }, { true, 16.721 }, { true, 33.44 },
+    { false, 0 }, { true, 33.44 }, { false, 16.721 }, { true, 16.721 },
+    { true, 50.161 }, { false, 0 }, { true, 16.72 }, { true, 33.44 },
+    { false, 0 }, { true, 33.441 }, { false, 16.72 }, { true, 16.72 },
+    { true, 50.16 }, { false, 0 }, { true, 16.72 }, { true, 33.441 },
+    { true, 33.44 }, { false, 0 }, { true, 33.44 }, { true, 33.441 },
+    { false, 0 }, { true, 33.44 }, { true, 33.441 }, { false, 0 },
+    { true, 33.44 }, { false, 0 }, { true, 33.44 }, { false, 16.72 },
+    { true, 16.721 }, { true, 50.161 }, { false, 0 }, { true, 16.72 },
+    { true, 33.44 }, { true, 33.441 }, { false, 0 }, { true, 33.44 },
+    { true, 33.44 }, { false, 0 }, { true, 33.441 }, { false, 16.72 },
+    { true, 16.72 }, { true, 50.16 }, { false, 0 }, { true, 16.72 },
+    { true, 33.441 }, { false, 0 }, { true, 33.44 }, { false, 16.72 },
+    { true, 33.44 }, { false, 0 }, { true, 16.721 }, { true, 50.161 },
+    { false, 0 }, { true, 16.72 }, { true, 33.44 }, { false, 0 },
+    { true, 33.441 }, { false, 16.72 }, { true, 16.72 }, { true, 50.16 }
+  };
+
+  SmoothEventSampler sampler(base::TimeDelta::FromSeconds(1) / 30, true, 3);
+  ReplayCheckingSamplerDecisions(data_points, arraysize(data_points), &sampler);
+}
+
+}  // namespace
+}  // namespace content
diff --git a/content/browser/renderer_host/media/webrtc_logging_handler_host.cc b/content/browser/renderer_host/media/webrtc_logging_handler_host.cc
new file mode 100644
index 0000000..00d90fd
--- /dev/null
+++ b/content/browser/renderer_host/media/webrtc_logging_handler_host.cc
@@ -0,0 +1,61 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/media/webrtc_logging_handler_host.h"
+
+#include "base/bind.h"
+#include "base/logging.h"
+#include "content/common/media/webrtc_logging_messages.h"
+
+namespace content {
+
+const size_t kWebRtcLogSize = 6 * 1024 * 1024;  // 6 MB
+
+WebRtcLoggingHandlerHost::WebRtcLoggingHandlerHost() {
+}
+
+WebRtcLoggingHandlerHost::~WebRtcLoggingHandlerHost() {
+}
+
+void WebRtcLoggingHandlerHost::OnChannelClosing() {
+  BrowserMessageFilter::OnChannelClosing();
+}
+
+void WebRtcLoggingHandlerHost::OnDestruct() const {
+  BrowserThread::DeleteOnIOThread::Destruct(this);
+}
+
+bool WebRtcLoggingHandlerHost::OnMessageReceived(const IPC::Message& message,
+                                                 bool* message_was_ok) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  bool handled = true;
+  IPC_BEGIN_MESSAGE_MAP_EX(WebRtcLoggingHandlerHost, message, *message_was_ok)
+    IPC_MESSAGE_HANDLER(WebRtcLoggingMsg_OpenLog, OnOpenLog)
+    IPC_MESSAGE_UNHANDLED(handled = false)
+  IPC_END_MESSAGE_MAP_EX()
+
+  return handled;
+}
+
+void WebRtcLoggingHandlerHost::OnOpenLog() {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK(!base::SharedMemory::IsHandleValid(shared_memory_.handle()));
+
+  if (!shared_memory_.CreateAndMapAnonymous(kWebRtcLogSize)) {
+    DLOG(ERROR) << "Failed to create shared memory.";
+    Send(new WebRtcLoggingMsg_OpenLogFailed());
+    return;
+  }
+
+  base::SharedMemoryHandle foreign_memory_handle;
+  if (!shared_memory_.ShareToProcess(peer_handle(),
+                                     &foreign_memory_handle)) {
+    Send(new WebRtcLoggingMsg_OpenLogFailed());
+    return;
+  }
+
+  Send(new WebRtcLoggingMsg_LogOpened(foreign_memory_handle, kWebRtcLogSize));
+}
+
+}  // namespace content
diff --git a/content/browser/renderer_host/media/webrtc_logging_handler_host.h b/content/browser/renderer_host/media/webrtc_logging_handler_host.h
new file mode 100644
index 0000000..f3ab4a4
--- /dev/null
+++ b/content/browser/renderer_host/media/webrtc_logging_handler_host.h
@@ -0,0 +1,42 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_RENDERER_HOST_MEDIA_WEBRTC_LOGGING_HANDLER_HOST_H_
+#define CONTENT_BROWSER_RENDERER_HOST_MEDIA_WEBRTC_LOGGING_HANDLER_HOST_H_
+
+#include "base/basictypes.h"
+#include "base/shared_memory.h"
+#include "content/public/browser/browser_message_filter.h"
+
+namespace content {
+
+// WebRtcLoggingHandlerHost handles operations regarding the WebRTC logging:
+// opening and closing shared memory buffer that the handler in the renderer
+// process writes to.
+class WebRtcLoggingHandlerHost : public BrowserMessageFilter {
+ public:
+  WebRtcLoggingHandlerHost();
+
+ private:
+  // BrowserMessageFilter implementation.
+  virtual void OnChannelClosing() OVERRIDE;
+  virtual void OnDestruct() const OVERRIDE;
+  virtual bool OnMessageReceived(const IPC::Message& message,
+                                 bool* message_was_ok) OVERRIDE;
+
+  friend class BrowserThread;
+  friend class base::DeleteHelper<WebRtcLoggingHandlerHost>;
+
+  virtual ~WebRtcLoggingHandlerHost();
+
+  void OnOpenLog();
+
+  base::SharedMemory shared_memory_;
+
+  DISALLOW_COPY_AND_ASSIGN(WebRtcLoggingHandlerHost);
+};
+
+}  // namespace content
+
+#endif  // CONTENT_BROWSER_RENDERER_HOST_MEDIA_WEBRTC_LOGGING_HANDLER_HOST_H_
diff --git a/content/browser/renderer_host/overscroll_controller.cc b/content/browser/renderer_host/overscroll_controller.cc
index 0b5925a..0a4086a 100644
--- a/content/browser/renderer_host/overscroll_controller.cc
+++ b/content/browser/renderer_host/overscroll_controller.cc
@@ -65,6 +65,10 @@
     // Consume the event and update overscroll state when in the middle of the
     // overscroll gesture.
     ProcessEventForOverscroll(event);
+
+    if (event.type == WebKit::WebInputEvent::TouchEnd ||
+        event.type == WebKit::WebInputEvent::TouchCancel)
+      return true;
     return false;
   }
 
diff --git a/content/browser/renderer_host/p2p/socket_dispatcher_host.cc b/content/browser/renderer_host/p2p/socket_dispatcher_host.cc
index 7c79711..36b9210 100644
--- a/content/browser/renderer_host/p2p/socket_dispatcher_host.cc
+++ b/content/browser/renderer_host/p2p/socket_dispatcher_host.cc
@@ -197,7 +197,7 @@
   scoped_ptr<P2PSocketHost> socket(
       P2PSocketHost::Create(this, socket_id, type));
 
-  if (!socket.get()) {
+  if (!socket) {
     Send(new P2PMsg_OnError(socket_id));
     return;
   }
diff --git a/content/browser/renderer_host/p2p/socket_host.h b/content/browser/renderer_host/p2p/socket_host.h
index 0abb74e..9fe985d 100644
--- a/content/browser/renderer_host/p2p/socket_host.h
+++ b/content/browser/renderer_host/p2p/socket_host.h
@@ -62,15 +62,6 @@
     STATE_ERROR,
   };
 
-  // Maximum size of send buffers. Must be big enough to fit data for
-  // one data burst. Send buffers size needs to be limited to prevent
-  // from consuming too much memory with misbehaving renderer process.
-  //
-  // TODO(sergeyu): Consider implementing congestion notifications to
-  // minimize buffering. This will require some fixes in libjingle,
-  // see crbug.com/91495 .
-  static const int kMaxSendBufferSize = 256 * 1024;
-
   P2PSocketHost(IPC::Sender* message_sender, int id);
 
   // Verifies that the packet |data| has a valid STUN header. In case
diff --git a/content/browser/renderer_host/p2p/socket_host_tcp.cc b/content/browser/renderer_host/p2p/socket_host_tcp.cc
index 2409280..de62ffb 100644
--- a/content/browser/renderer_host/p2p/socket_host_tcp.cc
+++ b/content/browser/renderer_host/p2p/socket_host_tcp.cc
@@ -21,6 +21,7 @@
 
 P2PSocketHostTcp::P2PSocketHostTcp(IPC::Sender* message_sender, int id)
     : P2PSocketHost(message_sender, id),
+      write_pending_(false),
       connected_(false) {
 }
 
@@ -87,10 +88,6 @@
     return;
   }
 
-  if (!socket_->SetSendBufferSize(kMaxSendBufferSize)) {
-    LOG(WARNING) << "Failed to set send buffer size for TCP socket.";
-  }
-
   net::IPEndPoint address;
   result = socket_->GetLocalAddress(&address);
   if (result < 0) {
@@ -190,22 +187,14 @@
 
 void P2PSocketHostTcp::Send(const net::IPEndPoint& to,
                             const std::vector<char>& data) {
-  if (!socket_.get()) {
+  if (!socket_) {
     // The Send message may be sent after the an OnError message was
     // sent by hasn't been processed the renderer.
     return;
   }
 
-  if (write_buffer_) {
-    // Silently drop packet if we haven't finished sending previous
-    // packet.
-    VLOG(1) << "Dropping TCP packet.";
-    return;
-  }
-
   if (!(to == remote_address_)) {
-    // Renderer should use this socket only to send data to
-    // |remote_address_|.
+    // Renderer should use this socket only to send data to |remote_address_|.
     NOTREACHED();
     OnError();
     return;
@@ -223,51 +212,56 @@
   }
 
   int size = kPacketHeaderSize + data.size();
-  write_buffer_ = new net::DrainableIOBuffer(new net::IOBuffer(size), size);
-  *reinterpret_cast<uint16*>(write_buffer_->data()) =
-      base::HostToNet16(data.size());
-  memcpy(write_buffer_->data() + kPacketHeaderSize, &data[0], data.size());
+  scoped_refptr<net::DrainableIOBuffer> buffer =
+      new net::DrainableIOBuffer(new net::IOBuffer(size), size);
+  *reinterpret_cast<uint16*>(buffer->data()) = base::HostToNet16(data.size());
+  memcpy(buffer->data() + kPacketHeaderSize, &data[0], data.size());
 
+  if (write_buffer_) {
+    write_queue_.push(buffer);
+    return;
+  }
+
+  write_buffer_ = buffer;
   DoWrite();
 }
 
 void P2PSocketHostTcp::DoWrite() {
-  while (true) {
+  while (write_buffer_ && state_ == STATE_OPEN && !write_pending_) {
     int result = socket_->Write(write_buffer_, write_buffer_->BytesRemaining(),
                                 base::Bind(&P2PSocketHostTcp::OnWritten,
                                            base::Unretained(this)));
-    if (result >= 0) {
-      write_buffer_->DidConsume(result);
-      if (write_buffer_->BytesRemaining() == 0) {
-        write_buffer_ = NULL;
-        break;
-      }
-    } else {
-      if (result != net::ERR_IO_PENDING) {
-        LOG(ERROR) << "Error when sending data in TCP socket: " << result;
-        OnError();
-      }
-      break;
-    }
+    HandleWriteResult(result);
   }
 }
 
 void P2PSocketHostTcp::OnWritten(int result) {
-  DCHECK(write_buffer_);
+  DCHECK(write_pending_);
   DCHECK_NE(result, net::ERR_IO_PENDING);
 
-  if (result < 0) {
-    DCHECK(result != net::ERR_IO_PENDING);
+  write_pending_ = false;
+  HandleWriteResult(result);
+  DoWrite();
+}
+
+void P2PSocketHostTcp::HandleWriteResult(int result) {
+  DCHECK(write_buffer_);
+  if (result >= 0) {
+    write_buffer_->DidConsume(result);
+    if (write_buffer_->BytesRemaining() == 0) {
+      message_sender_->Send(new P2PMsg_OnSendComplete(id_));
+      if (write_queue_.empty()) {
+        write_buffer_ = NULL;
+      } else {
+        write_buffer_ = write_queue_.front();
+        write_queue_.pop();
+      }
+    }
+  } else if (result == net::ERR_IO_PENDING) {
+    write_pending_ = true;
+  } else {
     LOG(ERROR) << "Error when sending data in TCP socket: " << result;
     OnError();
-    return;
-  }
-
-  write_buffer_->DidConsume(result);
-  if (write_buffer_->BytesRemaining() == 0) {
-    write_buffer_ = NULL;
-  } else {
-    DoWrite();
   }
 }
 
diff --git a/content/browser/renderer_host/p2p/socket_host_tcp.h b/content/browser/renderer_host/p2p/socket_host_tcp.h
index 48cc7f9..4fa3fae 100644
--- a/content/browser/renderer_host/p2p/socket_host_tcp.h
+++ b/content/browser/renderer_host/p2p/socket_host_tcp.h
@@ -51,6 +51,7 @@
   void OnPacket(std::vector<char>& data);
 
   void DoWrite();
+  void HandleWriteResult(int result);
 
   // Callbacks for Connect(), Read() and Write().
   void OnConnected(int result);
@@ -61,7 +62,10 @@
 
   scoped_ptr<net::StreamSocket> socket_;
   scoped_refptr<net::GrowableIOBuffer> read_buffer_;
+
+  std::queue<scoped_refptr<net::DrainableIOBuffer> > write_queue_;
   scoped_refptr<net::DrainableIOBuffer> write_buffer_;
+  bool write_pending_;
 
   bool connected_;
 
diff --git a/content/browser/renderer_host/p2p/socket_host_tcp_server.cc b/content/browser/renderer_host/p2p/socket_host_tcp_server.cc
index 206a0e4..113eb4d 100644
--- a/content/browser/renderer_host/p2p/socket_host_tcp_server.cc
+++ b/content/browser/renderer_host/p2p/socket_host_tcp_server.cc
@@ -24,9 +24,9 @@
     IPC::Sender* message_sender, int id)
     : P2PSocketHost(message_sender, id),
       socket_(new net::TCPServerSocket(NULL, net::NetLog::Source())),
-      ALLOW_THIS_IN_INITIALIZER_LIST(accept_callback_(
+      accept_callback_(
           base::Bind(&P2PSocketHostTcpServer::OnAccepted,
-                     base::Unretained(this)))) {
+                     base::Unretained(this))) {
 }
 
 P2PSocketHostTcpServer::~P2PSocketHostTcpServer() {
diff --git a/content/browser/renderer_host/p2p/socket_host_tcp_unittest.cc b/content/browser/renderer_host/p2p/socket_host_tcp_unittest.cc
index 86e1d97..cc46b2b 100644
--- a/content/browser/renderer_host/p2p/socket_host_tcp_unittest.cc
+++ b/content/browser/renderer_host/p2p/socket_host_tcp_unittest.cc
@@ -62,6 +62,11 @@
 // Verify that we can send STUN message and that they are formatted
 // properly.
 TEST_F(P2PSocketHostTcpTest, SendStunNoAuth) {
+  EXPECT_CALL(sender_, Send(
+      MatchMessage(static_cast<uint32>(P2PMsg_OnSendComplete::ID))))
+      .Times(3)
+      .WillRepeatedly(DoAll(DeleteArg<0>(), Return(true)));
+
   std::vector<char> packet1;
   CreateStunRequest(&packet1);
   socket_host_->Send(dest_, packet1);
@@ -88,6 +93,11 @@
 // Verify that we can receive STUN messages from the socket, and that
 // the messages are parsed properly.
 TEST_F(P2PSocketHostTcpTest, ReceiveStun) {
+  EXPECT_CALL(sender_, Send(
+      MatchMessage(static_cast<uint32>(P2PMsg_OnSendComplete::ID))))
+      .Times(3)
+      .WillRepeatedly(DoAll(DeleteArg<0>(), Return(true)));
+
   std::vector<char> packet1;
   CreateStunRequest(&packet1);
   socket_host_->Send(dest_, packet1);
@@ -152,6 +162,9 @@
   received_data.append(IntToSize(request_packet.size()));
   received_data.append(request_packet.begin(), request_packet.end());
 
+  EXPECT_CALL(sender_, Send(
+      MatchMessage(static_cast<uint32>(P2PMsg_OnSendComplete::ID))))
+      .WillOnce(DoAll(DeleteArg<0>(), Return(true)));
   EXPECT_CALL(sender_, Send(MatchPacketMessage(request_packet)))
       .WillOnce(DoAll(DeleteArg<0>(), Return(true)));
   socket_->AppendInputData(&received_data[0], received_data.size());
@@ -168,4 +181,34 @@
   EXPECT_EQ(expected_data, sent_data_);
 }
 
+// Verify that asynchronous writes are handled correctly.
+TEST_F(P2PSocketHostTcpTest, AsyncWrites) {
+  base::MessageLoop message_loop;
+
+  socket_->set_async_write(true);
+
+  EXPECT_CALL(sender_, Send(
+      MatchMessage(static_cast<uint32>(P2PMsg_OnSendComplete::ID))))
+      .Times(2)
+      .WillRepeatedly(DoAll(DeleteArg<0>(), Return(true)));
+
+  std::vector<char> packet1;
+  CreateStunRequest(&packet1);
+  socket_host_->Send(dest_, packet1);
+
+  std::vector<char> packet2;
+  CreateStunResponse(&packet2);
+  socket_host_->Send(dest_, packet2);
+
+  message_loop.RunUntilIdle();
+
+  std::string expected_data;
+  expected_data.append(IntToSize(packet1.size()));
+  expected_data.append(packet1.begin(), packet1.end());
+  expected_data.append(IntToSize(packet2.size()));
+  expected_data.append(packet2.begin(), packet2.end());
+
+  EXPECT_EQ(expected_data, sent_data_);
+}
+
 }  // namespace content
diff --git a/content/browser/renderer_host/p2p/socket_host_test_utils.h b/content/browser/renderer_host/p2p/socket_host_test_utils.h
index c3deea8..77da0cd 100644
--- a/content/browser/renderer_host/p2p/socket_host_test_utils.h
+++ b/content/browser/renderer_host/p2p/socket_host_test_utils.h
@@ -7,10 +7,13 @@
 
 #include <vector>
 
+#include "base/location.h"
+#include "base/single_thread_task_runner.h"
 #include "base/sys_byteorder.h"
+#include "base/thread_task_runner_handle.h"
 #include "content/common/p2p_messages.h"
-#include "ipc/ipc_sender.h"
 #include "ipc/ipc_message_utils.h"
+#include "ipc/ipc_sender.h"
 #include "net/base/address_list.h"
 #include "net/base/completion_callback.h"
 #include "net/base/io_buffer.h"
@@ -49,6 +52,7 @@
   FakeSocket(std::string* written_data);
   virtual ~FakeSocket();
 
+  void set_async_write(bool async_write) { async_write_ = async_write; }
   void AppendInputData(const char* data, int data_size);
   int input_pos() const { return input_pos_; }
   bool read_pending() const { return read_pending_; }
@@ -73,22 +77,26 @@
   virtual void SetOmniboxSpeculation() OVERRIDE;
   virtual bool WasEverUsed() const OVERRIDE;
   virtual bool UsingTCPFastOpen() const OVERRIDE;
-  virtual int64 NumBytesRead() const OVERRIDE;
-  virtual base::TimeDelta GetConnectTimeMicros() const OVERRIDE;
   virtual bool WasNpnNegotiated() const OVERRIDE;
   virtual net::NextProto GetNegotiatedProtocol() const OVERRIDE;
   virtual bool GetSSLInfo(net::SSLInfo* ssl_info) OVERRIDE;
 
  private:
+  void DoAsyncWrite(scoped_refptr<net::IOBuffer> buf, int buf_len,
+                    const net::CompletionCallback& callback);
+
   bool read_pending_;
   scoped_refptr<net::IOBuffer> read_buffer_;
   int read_buffer_size_;
   net::CompletionCallback read_callback_;
 
-  std::string* written_data_;
   std::string input_data_;
   int input_pos_;
 
+  std::string* written_data_;
+  bool async_write_;
+  bool write_pending_;
+
   net::IPEndPoint peer_address_;
   net::IPEndPoint local_address_;
 
@@ -97,8 +105,10 @@
 
 FakeSocket::FakeSocket(std::string* written_data)
     : read_pending_(false),
+      input_pos_(0),
       written_data_(written_data),
-      input_pos_(0) {
+      async_write_(false),
+      write_pending_(false) {
 }
 
 FakeSocket::~FakeSocket() { }
@@ -149,6 +159,17 @@
 int FakeSocket::Write(net::IOBuffer* buf, int buf_len,
                       const net::CompletionCallback& callback) {
   DCHECK(buf);
+  DCHECK(!write_pending_);
+
+  if (async_write_) {
+
+    base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, base::Bind(
+        &FakeSocket::DoAsyncWrite, base::Unretained(this),
+        scoped_refptr<net::IOBuffer>(buf), buf_len, callback));
+    write_pending_ = true;
+    return net::ERR_IO_PENDING;
+  }
+
   if (written_data_) {
     written_data_->insert(written_data_->end(),
                           buf->data(), buf->data() + buf_len);
@@ -156,6 +177,16 @@
   return buf_len;
 }
 
+void FakeSocket::DoAsyncWrite(scoped_refptr<net::IOBuffer> buf, int buf_len,
+                              const net::CompletionCallback& callback) {
+  write_pending_ = false;
+
+  if (written_data_) {
+    written_data_->insert(written_data_->end(),
+                          buf->data(), buf->data() + buf_len);
+  }
+  callback.Run(buf_len);
+}
 
 bool FakeSocket::SetReceiveBufferSize(int32 size) {
   NOTIMPLEMENTED();
@@ -213,14 +244,6 @@
   return false;
 }
 
-int64 FakeSocket::NumBytesRead() const {
-  return -1;
-}
-
-base::TimeDelta FakeSocket::GetConnectTimeMicros() const {
-  return base::TimeDelta::FromMicroseconds(-1);
-}
-
 bool FakeSocket::WasNpnNegotiated() const {
   return false;
 }
diff --git a/content/browser/renderer_host/p2p/socket_host_udp.cc b/content/browser/renderer_host/p2p/socket_host_udp.cc
index b84ee68..402898c 100644
--- a/content/browser/renderer_host/p2p/socket_host_udp.cc
+++ b/content/browser/renderer_host/p2p/socket_host_udp.cc
@@ -5,6 +5,7 @@
 #include "content/browser/renderer_host/p2p/socket_host_udp.h"
 
 #include "base/bind.h"
+#include "base/debug/trace_event.h"
 #include "content/common/p2p_messages.h"
 #include "ipc/ipc_sender.h"
 #include "net/base/io_buffer.h"
@@ -17,11 +18,23 @@
 const int kReadBufferSize = 65536;
 
 // Defines set of transient errors. These errors are ignored when we get them
-// from sendto() calls.
+// from sendto() or recvfrom() calls.
+//
+// net::ERR_OUT_OF_MEMORY
+//
+// This is caused by ENOBUFS which means the buffer of the network interface
+// is full.
+//
+// net::ERR_CONNECTION_RESET
+//
+// This is caused by WSAENETRESET or WSAECONNRESET which means the
+// last send resulted in an "ICMP Port Unreachable" message.
 bool IsTransientError(int error) {
   return error == net::ERR_ADDRESS_UNREACHABLE ||
          error == net::ERR_ADDRESS_INVALID ||
-         error == net::ERR_ACCESS_DENIED;
+         error == net::ERR_ACCESS_DENIED ||
+         error == net::ERR_CONNECTION_RESET ||
+         error == net::ERR_OUT_OF_MEMORY;
 }
 
 }  // namespace
@@ -42,7 +55,6 @@
 P2PSocketHostUdp::P2PSocketHostUdp(IPC::Sender* message_sender, int id)
     : P2PSocketHost(message_sender, id),
       socket_(new net::UDPServerSocket(NULL, net::NetLog::Source())),
-      send_queue_bytes_(0),
       send_pending_(false) {
 }
 
@@ -102,18 +114,18 @@
                                           base::Unretained(this)));
     if (result == net::ERR_IO_PENDING)
       return;
-    DidCompleteRead(result);
+    HandleReadResult(result);
   } while (state_ == STATE_OPEN);
 }
 
 void P2PSocketHostUdp::OnRecv(int result) {
-  DidCompleteRead(result);
+  HandleReadResult(result);
   if (state_ == STATE_OPEN) {
     DoRead();
   }
 }
 
-void P2PSocketHostUdp::DidCompleteRead(int result) {
+void P2PSocketHostUdp::HandleReadResult(int result) {
   DCHECK_EQ(state_, STATE_OPEN);
 
   if (result > 0) {
@@ -141,7 +153,7 @@
 
 void P2PSocketHostUdp::Send(const net::IPEndPoint& to,
                             const std::vector<char>& data) {
-  if (!socket_.get()) {
+  if (!socket_) {
     // The Send message may be sent after the an OnError message was
     // sent by hasn't been processed the renderer.
     return;
@@ -159,13 +171,7 @@
   }
 
   if (send_pending_) {
-    if (send_queue_bytes_ + static_cast<int>(data.size()) >
-        kMaxSendBufferSize) {
-      LOG(WARNING) << "Send buffer is full. Dropping a packet.";
-      return;
-    }
     send_queue_.push_back(PendingPacket(to, data));
-    send_queue_bytes_ += data.size();
   } else {
     PendingPacket packet(to, data);
     DoSend(packet);
@@ -173,6 +179,8 @@
 }
 
 void P2PSocketHostUdp::DoSend(const PendingPacket& packet) {
+  TRACE_EVENT_ASYNC_BEGIN2("p2p", "Udp::DoSend", this,
+                           "id", id_, "size", packet.size);
   int result = socket_->SendTo(packet.data, packet.size, packet.to,
                                base::Bind(&P2PSocketHostUdp::OnSend,
                                           base::Unretained(this)));
@@ -188,12 +196,8 @@
 
   if (result == net::ERR_IO_PENDING) {
     send_pending_ = true;
-  } else if (IsTransientError(result)) {
-    LOG(INFO) << "sendto() has failed twice returning a "
-        " transient error. Dropping the packet.";
-  } else if (result < 0) {
-    LOG(ERROR) << "Error when sending data in UDP socket: " << result;
-    OnError();
+  } else {
+    HandleSendResult(result);
   }
 }
 
@@ -203,19 +207,28 @@
 
   send_pending_ = false;
 
-  if (result < 0 && !IsTransientError(result)) {
-    OnError();
-    return;
-  }
+  HandleSendResult(result);
 
   // Send next packets if we have them waiting in the buffer.
-  while (!send_queue_.empty() && !send_pending_) {
+  while (state_ == STATE_OPEN && !send_queue_.empty() && !send_pending_) {
     DoSend(send_queue_.front());
-    send_queue_bytes_ -= send_queue_.front().size;
     send_queue_.pop_front();
   }
 }
 
+void P2PSocketHostUdp::HandleSendResult(int result) {
+  TRACE_EVENT_ASYNC_END1("p2p", "Udp::DoSend", this, "result", result);
+  if (result > 0) {
+    message_sender_->Send(new P2PMsg_OnSendComplete(id_));
+  } else if (IsTransientError(result)) {
+    LOG(INFO) << "sendto() has failed twice returning a "
+        " transient error. Dropping the packet.";
+  } else if (result < 0) {
+    LOG(ERROR) << "Error when sending data in UDP socket: " << result;
+    OnError();
+  }
+}
+
 P2PSocketHost* P2PSocketHostUdp::AcceptIncomingTcpConnection(
     const net::IPEndPoint& remote_address, int id) {
   NOTREACHED();
diff --git a/content/browser/renderer_host/p2p/socket_host_udp.h b/content/browser/renderer_host/p2p/socket_host_udp.h
index 710f743..2b83c97 100644
--- a/content/browser/renderer_host/p2p/socket_host_udp.h
+++ b/content/browser/renderer_host/p2p/socket_host_udp.h
@@ -48,20 +48,20 @@
   };
 
   void OnError();
-  void DoRead();
-  void DoSend(const PendingPacket& packet);
-  void DidCompleteRead(int result);
 
-  // Callbacks for RecvFrom() and SendTo().
+  void DoRead();
   void OnRecv(int result);
+  void HandleReadResult(int result);
+
+  void DoSend(const PendingPacket& packet);
   void OnSend(int result);
+  void HandleSendResult(int result);
 
   scoped_ptr<net::DatagramServerSocket> socket_;
   scoped_refptr<net::IOBuffer> recv_buffer_;
   net::IPEndPoint recv_address_;
 
   std::deque<PendingPacket> send_queue_;
-  int send_queue_bytes_;
   bool send_pending_;
 
   // Set of peer for which we have received STUN binding request or
diff --git a/content/browser/renderer_host/p2p/socket_host_udp_unittest.cc b/content/browser/renderer_host/p2p/socket_host_udp_unittest.cc
index 5a5f15a..d7a3bec 100644
--- a/content/browser/renderer_host/p2p/socket_host_udp_unittest.cc
+++ b/content/browser/renderer_host/p2p/socket_host_udp_unittest.cc
@@ -164,6 +164,11 @@
 // Verify that we can send STUN messages before we receive anything
 // from the other side.
 TEST_F(P2PSocketHostUdpTest, SendStunNoAuth) {
+  EXPECT_CALL(sender_, Send(
+      MatchMessage(static_cast<uint32>(P2PMsg_OnSendComplete::ID))))
+      .Times(3)
+      .WillRepeatedly(DoAll(DeleteArg<0>(), Return(true)));
+
   std::vector<char> packet1;
   CreateStunRequest(&packet1);
   socket_host_->Send(dest1_, packet1);
@@ -208,6 +213,9 @@
   socket_->ReceivePacket(dest1_, request_packet);
 
   // Now we should be able to send any data to |dest1_|.
+  EXPECT_CALL(sender_, Send(
+      MatchMessage(static_cast<uint32>(P2PMsg_OnSendComplete::ID))))
+      .WillOnce(DoAll(DeleteArg<0>(), Return(true)));
   std::vector<char> packet;
   CreateRandomPacket(&packet);
   socket_host_->Send(dest1_, packet);
@@ -228,6 +236,9 @@
   socket_->ReceivePacket(dest1_, request_packet);
 
   // Now we should be able to send any data to |dest1_|.
+  EXPECT_CALL(sender_, Send(
+      MatchMessage(static_cast<uint32>(P2PMsg_OnSendComplete::ID))))
+      .WillOnce(DoAll(DeleteArg<0>(), Return(true)));
   std::vector<char> packet;
   CreateRandomPacket(&packet);
   socket_host_->Send(dest1_, packet);
diff --git a/content/browser/renderer_host/pepper/browser_ppapi_host_impl.cc b/content/browser/renderer_host/pepper/browser_ppapi_host_impl.cc
index ff4284a..4fcbcf2 100644
--- a/content/browser/renderer_host/pepper/browser_ppapi_host_impl.cc
+++ b/content/browser/renderer_host/pepper/browser_ppapi_host_impl.cc
@@ -21,15 +21,14 @@
     IPC::ChannelProxy* channel,
     net::HostResolver* host_resolver,
     int render_process_id,
-    int render_view_id) {
-  // TODO(raymes): Figure out how to plumb plugin_name and
-  // profile_data_directory through for NaCl. They are currently only needed for
-  // PPB_Flash_File interfaces so it doesn't matter.
+    int render_view_id,
+    const base::FilePath& profile_directory) {
+  // TODO(raymes): Figure out how to plumb plugin_name through for NaCl. It is
+  // currently only needed for PPB_Flash_File interfaces so it doesn't matter.
   std::string plugin_name;
-  base::FilePath profile_data_directory;
   BrowserPpapiHostImpl* browser_ppapi_host =
       new BrowserPpapiHostImpl(sender, permissions, plugin_name,
-                               profile_data_directory,
+                               profile_directory,
                                true);
   browser_ppapi_host->set_plugin_process_handle(plugin_child_process);
 
diff --git a/content/browser/renderer_host/pepper/pepper_browser_font_singleton_host.cc b/content/browser/renderer_host/pepper/pepper_browser_font_singleton_host.cc
index 02ae2a8..99a8e04 100644
--- a/content/browser/renderer_host/pepper/pepper_browser_font_singleton_host.cc
+++ b/content/browser/renderer_host/pepper/pepper_browser_font_singleton_host.cc
@@ -46,9 +46,12 @@
 
 scoped_refptr<base::TaskRunner> FontMessageFilter::OverrideTaskRunnerForMessage(
     const IPC::Message& msg) {
-  // Use the blocking pool to get the font list (currently the only message
-  // so we can always just return it).
-  return scoped_refptr<base::TaskRunner>(BrowserThread::GetBlockingPool());
+  // Use the blocking pool to get the font list (currently the only message)
+  // Since getting the font list is non-threadsafe on Linux (for versions of
+  // Pango predating 2013), use a sequenced task runner.
+  base::SequencedWorkerPool* pool = BrowserThread::GetBlockingPool();
+  return pool->GetSequencedTaskRunner(
+      pool->GetNamedSequenceToken(kFontListSequenceToken));
 }
 
 int32_t FontMessageFilter::OnResourceMessageReceived(
diff --git a/content/browser/renderer_host/pepper/pepper_gamepad_host.cc b/content/browser/renderer_host/pepper/pepper_gamepad_host.cc
index 1edb1ba..818bf24 100644
--- a/content/browser/renderer_host/pepper/pepper_gamepad_host.cc
+++ b/content/browser/renderer_host/pepper/pepper_gamepad_host.cc
@@ -23,7 +23,7 @@
       browser_ppapi_host_(host),
       gamepad_service_(GamepadService::GetInstance()),
       is_started_(false),
-      weak_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
+      weak_factory_(this) {
 }
 
 PepperGamepadHost::PepperGamepadHost(GamepadService* gamepad_service,
@@ -34,7 +34,7 @@
       browser_ppapi_host_(host),
       gamepad_service_(gamepad_service),
       is_started_(false),
-      weak_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
+      weak_factory_(this) {
 }
 
 PepperGamepadHost::~PepperGamepadHost() {
diff --git a/content/browser/renderer_host/pepper/pepper_host_resolver_private_message_filter.cc b/content/browser/renderer_host/pepper/pepper_host_resolver_private_message_filter.cc
index d42cb56..ba27bf4 100644
--- a/content/browser/renderer_host/pepper/pepper_host_resolver_private_message_filter.cc
+++ b/content/browser/renderer_host/pepper/pepper_host_resolver_private_message_filter.cc
@@ -122,9 +122,9 @@
 
   // Check plugin permissions.
   SocketPermissionRequest request(
-      content::SocketPermissionRequest::NONE, "", 0);
-  RenderViewHost* render_view_host = RenderViewHost::FromID(render_process_id_,
-                                                            render_view_id_);
+      content::SocketPermissionRequest::TCP_CONNECT, std::string(), 0);
+  RenderViewHost* render_view_host =
+      RenderViewHost::FromID(render_process_id_, render_view_id_);
   if (!render_view_host ||
       !pepper_socket_utils::CanUseSocketAPIs(external_plugin_,
                                              request,
diff --git a/content/browser/renderer_host/pepper/pepper_message_filter.cc b/content/browser/renderer_host/pepper/pepper_message_filter.cc
index 069678c..95fe84d 100644
--- a/content/browser/renderer_host/pepper/pepper_message_filter.cc
+++ b/content/browser/renderer_host/pepper/pepper_message_filter.cc
@@ -30,9 +30,9 @@
 #include "content/public/common/content_client.h"
 #include "net/base/address_family.h"
 #include "net/base/address_list.h"
-#include "net/base/cert_verifier.h"
 #include "net/base/host_port_pair.h"
 #include "net/base/sys_addrinfo.h"
+#include "net/cert/cert_verifier.h"
 #include "ppapi/c/pp_errors.h"
 #include "ppapi/c/private/ppb_net_address_private.h"
 #include "ppapi/proxy/ppapi_messages.h"
@@ -154,7 +154,7 @@
 }
 
 net::CertVerifier* PepperMessageFilter::GetCertVerifier() {
-  if (!cert_verifier_.get())
+  if (!cert_verifier_)
     cert_verifier_.reset(net::CertVerifier::CreateDefault());
 
   return cert_verifier_.get();
diff --git a/content/browser/renderer_host/pepper/pepper_printing_host.cc b/content/browser/renderer_host/pepper/pepper_printing_host.cc
index 959d589..c11939c 100644
--- a/content/browser/renderer_host/pepper/pepper_printing_host.cc
+++ b/content/browser/renderer_host/pepper/pepper_printing_host.cc
@@ -20,7 +20,7 @@
     scoped_ptr<PepperPrintSettingsManager> print_settings_manager)
     : ResourceHost(host, instance, resource),
       print_settings_manager_(print_settings_manager.Pass()),
-      weak_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
+      weak_factory_(this) {
 }
 
 PepperPrintingHost::~PepperPrintingHost() {
diff --git a/content/browser/renderer_host/pepper/pepper_tcp_socket.cc b/content/browser/renderer_host/pepper/pepper_tcp_socket.cc
index e6732e5..3638898 100644
--- a/content/browser/renderer_host/pepper/pepper_tcp_socket.cc
+++ b/content/browser/renderer_host/pepper/pepper_tcp_socket.cc
@@ -13,12 +13,12 @@
 #include "base/string_util.h"
 #include "content/browser/renderer_host/pepper/pepper_message_filter.h"
 #include "content/public/browser/browser_thread.h"
-#include "net/base/cert_verifier.h"
 #include "net/base/host_port_pair.h"
 #include "net/base/io_buffer.h"
 #include "net/base/ip_endpoint.h"
 #include "net/base/net_errors.h"
-#include "net/base/x509_certificate.h"
+#include "net/cert/cert_verifier.h"
+#include "net/cert/x509_certificate.h"
 #include "net/dns/host_resolver.h"
 #include "net/dns/single_request_host_resolver.h"
 #include "net/socket/client_socket_factory.h"
@@ -66,7 +66,7 @@
 
 PepperTCPSocket::~PepperTCPSocket() {
   // Make sure no further callbacks from socket_.
-  if (socket_.get())
+  if (socket_)
     socket_->Disconnect();
 }
 
@@ -140,7 +140,7 @@
   ssl_context.cert_verifier = manager_->GetCertVerifier();
   socket_.reset(factory->CreateSSLClientSocket(
       handle, host_port_pair, manager_->ssl_config(), ssl_context));
-  if (!socket_.get()) {
+  if (!socket_) {
     LOG(WARNING) << "Failed to create an SSL client socket.";
     OnSSLHandshakeCompleted(net::ERR_UNEXPECTED);
     return;
@@ -291,7 +291,7 @@
     ppapi::PPB_X509Certificate_Fields* fields) {
   scoped_refptr<net::X509Certificate> cert =
       net::X509Certificate::CreateFromBytes(der, length);
-  if (!cert.get())
+  if (!cert)
     return false;
   return GetCertificateFields(*cert, fields);
 }
@@ -314,7 +314,7 @@
         static_cast<net::SSLClientSocket*>(socket_.get());
     net::SSLInfo ssl_info;
     ssl_socket->GetSSLInfo(&ssl_info);
-    if (ssl_info.cert.get())
+    if (ssl_info.cert)
       GetCertificateFields(*ssl_info.cert, &certificate_fields);
   }
   manager_->Send(new PpapiMsg_PPBTCPSocket_SSLHandshakeACK(
diff --git a/content/browser/renderer_host/pepper/pepper_truetype_font_list.h b/content/browser/renderer_host/pepper/pepper_truetype_font_list.h
index c0ce782..da944c5 100644
--- a/content/browser/renderer_host/pepper/pepper_truetype_font_list.h
+++ b/content/browser/renderer_host/pepper/pepper_truetype_font_list.h
@@ -8,6 +8,12 @@
 #include <string>
 #include <vector>
 
+namespace ppapi {
+namespace proxy {
+struct SerializedTrueTypeFontDesc;
+}
+}
+
 namespace content {
 
 // Adds font family names on the host platform to the vector of strings.
@@ -16,6 +22,15 @@
 // sure not to call this on a time-critical thread like the UI or I/O threads.
 void GetFontFamilies_SlowBlocking(std::vector<std::string>* font_families);
 
+// Adds font descriptors for fonts on the host platform in the given family to
+// the vector of descriptors.
+//
+// This function is potentially slow (the system may do a bunch of I/O) so be
+// sure not to call this on a time-critical thread like the UI or I/O threads.
+void GetFontsInFamily_SlowBlocking(
+    const std::string& family,
+    std::vector<ppapi::proxy::SerializedTrueTypeFontDesc>* fonts_in_family);
+
 }  // namespace content
 
 #endif  // CONTENT_BROWSER_RENDERER_HOST_PEPPER_PEPPER_TRUETYPE_FONT_LIST_H_
diff --git a/content/browser/renderer_host/pepper/pepper_truetype_font_list_android.cc b/content/browser/renderer_host/pepper/pepper_truetype_font_list_android.cc
index 7a8880a..28db24f 100644
--- a/content/browser/renderer_host/pepper/pepper_truetype_font_list_android.cc
+++ b/content/browser/renderer_host/pepper/pepper_truetype_font_list_android.cc
@@ -11,4 +11,10 @@
   NOTIMPLEMENTED();  // Font API isn't implemented on Android.
 }
 
+void GetFontsInFamily_SlowBlocking(
+    const std::string& family,
+    std::vector<ppapi::proxy::SerializedTrueTypeFontDesc>* fonts_in_family) {
+  NOTIMPLEMENTED();  // Font API isn't implemented on Android.
+}
+
 }  // namespace content
diff --git a/content/browser/renderer_host/pepper/pepper_truetype_font_list_host.cc b/content/browser/renderer_host/pepper/pepper_truetype_font_list_host.cc
index 74e8653..1b2aa66 100644
--- a/content/browser/renderer_host/pepper/pepper_truetype_font_list_host.cc
+++ b/content/browser/renderer_host/pepper/pepper_truetype_font_list_host.cc
@@ -9,6 +9,7 @@
 #include "base/safe_numerics.h"
 #include "base/threading/sequenced_worker_pool.h"
 #include "content/browser/renderer_host/pepper/pepper_truetype_font_list.h"
+#include "content/common/font_list.h"
 #include "content/public/browser/browser_ppapi_host.h"
 #include "content/public/browser/browser_thread.h"
 #include "ppapi/host/dispatch_host_message.h"
@@ -35,8 +36,10 @@
  private:
   virtual ~FontMessageFilter();
 
-  // Message handler.
+  // Message handlers.
   int32_t OnHostMsgGetFontFamilies(ppapi::host::HostMessageContext* context);
+  int32_t OnHostMsgGetFontsInFamily(ppapi::host::HostMessageContext* context,
+                                    const std::string& family);
 
   DISALLOW_COPY_AND_ASSIGN(FontMessageFilter);
 };
@@ -49,9 +52,12 @@
 
 scoped_refptr<base::TaskRunner> FontMessageFilter::OverrideTaskRunnerForMessage(
     const IPC::Message& msg) {
-  // Use the blocking pool to get the font list (currently the only message
-  // so we can always just return it).
-  return scoped_refptr<base::TaskRunner>(BrowserThread::GetBlockingPool());
+  // Use the blocking pool to get the font list (currently the only message)
+  // Since getting the font list is non-threadsafe on Linux (for versions of
+  // Pango predating 2013), use a sequenced task runner.
+  base::SequencedWorkerPool* pool = BrowserThread::GetBlockingPool();
+  return pool->GetSequencedTaskRunner(
+      pool->GetNamedSequenceToken(kFontListSequenceToken));
 }
 
 int32_t FontMessageFilter::OnResourceMessageReceived(
@@ -61,6 +67,9 @@
     PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(
         PpapiHostMsg_TrueTypeFontSingleton_GetFontFamilies,
         OnHostMsgGetFontFamilies)
+    PPAPI_DISPATCH_HOST_RESOURCE_CALL(
+        PpapiHostMsg_TrueTypeFontSingleton_GetFontsInFamily,
+        OnHostMsgGetFontsInFamily)
   IPC_END_MESSAGE_MAP()
   return PP_ERROR_FAILED;
 }
@@ -82,6 +91,23 @@
   return result;
 }
 
+int32_t FontMessageFilter::OnHostMsgGetFontsInFamily(
+    ppapi::host::HostMessageContext* context,
+    const std::string& family) {
+  // OK to use "slow blocking" version since we're on the blocking pool.
+  std::vector<ppapi::proxy::SerializedTrueTypeFontDesc> fonts_in_family;
+  GetFontsInFamily_SlowBlocking(family, &fonts_in_family);
+
+  int32_t result = base::checked_numeric_cast<int32_t>(fonts_in_family.size());
+  ppapi::host::ReplyMessageContext reply_context =
+      context->MakeReplyMessageContext();
+  reply_context.params.set_result(result);
+  context->reply_msg =
+      PpapiPluginMsg_TrueTypeFontSingleton_GetFontsInFamilyReply(
+          fonts_in_family);
+  return result;
+}
+
 }  // namespace
 
 PepperTrueTypeFontListHost::PepperTrueTypeFontListHost(
diff --git a/content/browser/renderer_host/pepper/pepper_truetype_font_list_host.h b/content/browser/renderer_host/pepper/pepper_truetype_font_list_host.h
index c67553b..69a471b 100644
--- a/content/browser/renderer_host/pepper/pepper_truetype_font_list_host.h
+++ b/content/browser/renderer_host/pepper/pepper_truetype_font_list_host.h
@@ -15,8 +15,8 @@
 class PepperTrueTypeFontListHost : public ppapi::host::ResourceHost {
  public:
   PepperTrueTypeFontListHost(BrowserPpapiHost* host,
-                                  PP_Instance instance,
-                                  PP_Resource resource);
+                             PP_Instance instance,
+                             PP_Resource resource);
   virtual ~PepperTrueTypeFontListHost();
 
  private:
diff --git a/content/browser/renderer_host/pepper/pepper_truetype_font_list_linux.cc b/content/browser/renderer_host/pepper/pepper_truetype_font_list_linux.cc
index 661266d..24c3f5d 100644
--- a/content/browser/renderer_host/pepper/pepper_truetype_font_list_linux.cc
+++ b/content/browser/renderer_host/pepper/pepper_truetype_font_list_linux.cc
@@ -9,6 +9,8 @@
 
 #include <string>
 
+#include "ppapi/proxy/serialized_structs.h"
+
 namespace content {
 
 void GetFontFamilies_SlowBlocking(std::vector<std::string>* font_families) {
@@ -17,9 +19,46 @@
   int num_families = 0;
   ::pango_font_map_list_families(font_map, &families, &num_families);
 
-  for (int i = 0; i < num_families; i++)
+  for (int i = 0; i < num_families; ++i)
     font_families->push_back(::pango_font_family_get_name(families[i]));
   g_free(families);
 }
 
+void GetFontsInFamily_SlowBlocking(
+    const std::string& family,
+    std::vector<ppapi::proxy::SerializedTrueTypeFontDesc>* fonts_in_family) {
+  PangoFontMap* font_map = ::pango_cairo_font_map_get_default();
+  PangoFontFamily** font_families = NULL;
+  int num_families = 0;
+  ::pango_font_map_list_families(font_map, &font_families, &num_families);
+
+  for (int i = 0; i < num_families; ++i) {
+    PangoFontFamily* font_family = font_families[i];
+    if (family.compare(::pango_font_family_get_name(font_family)) == 0) {
+      PangoFontFace** font_faces = NULL;
+      int num_faces = 0;
+      ::pango_font_family_list_faces(font_family, &font_faces, &num_faces);
+
+      for (int j = 0; j < num_faces; ++j) {
+        PangoFontFace* font_face = font_faces[j];
+        PangoFontDescription* font_desc = ::pango_font_face_describe(font_face);
+        ppapi::proxy::SerializedTrueTypeFontDesc desc;
+        desc.family = family;
+        if (::pango_font_description_get_style(font_desc) == PANGO_STYLE_ITALIC)
+          desc.style = PP_TRUETYPEFONTSTYLE_ITALIC;
+        desc.weight = static_cast<PP_TrueTypeFontWeight_Dev>(
+            ::pango_font_description_get_weight(font_desc));
+        desc.width = static_cast<PP_TrueTypeFontWidth_Dev>(
+            ::pango_font_description_get_stretch(font_desc));
+        // Character set is not part of Pango font description.
+        desc.charset = PP_TRUETYPEFONTCHARSET_DEFAULT;
+
+        fonts_in_family->push_back(desc);
+      }
+      g_free(font_faces);
+    }
+  }
+  g_free(font_families);
+}
+
 }  // namespace content
diff --git a/content/browser/renderer_host/pepper/pepper_truetype_font_list_mac.mm b/content/browser/renderer_host/pepper/pepper_truetype_font_list_mac.mm
index 9b79e66..7615723 100644
--- a/content/browser/renderer_host/pepper/pepper_truetype_font_list_mac.mm
+++ b/content/browser/renderer_host/pepper/pepper_truetype_font_list_mac.mm
@@ -7,10 +7,33 @@
 #import <Cocoa/Cocoa.h>
 
 #include "base/mac/scoped_nsautorelease_pool.h"
-#include "base/sys_string_conversions.h"
+#include "base/strings/sys_string_conversions.h"
+#include "ppapi/c/dev/ppb_truetype_font_dev.h"
+#include "ppapi/proxy/serialized_structs.h"
 
 namespace content {
 
+namespace {
+
+// Table to map AppKit weights to Pepper ones.
+const PP_TrueTypeFontWeight_Dev kPepperFontWeights[] = {
+    PP_TRUETYPEFONTWEIGHT_THIN,         // 0 is the minimum AppKit weight.
+    PP_TRUETYPEFONTWEIGHT_ULTRALIGHT,
+    PP_TRUETYPEFONTWEIGHT_ULTRALIGHT,
+    PP_TRUETYPEFONTWEIGHT_LIGHT,
+    PP_TRUETYPEFONTWEIGHT_LIGHT,
+    PP_TRUETYPEFONTWEIGHT_NORMAL,       // 5 is a 'normal' AppKit weight.
+    PP_TRUETYPEFONTWEIGHT_MEDIUM,
+    PP_TRUETYPEFONTWEIGHT_MEDIUM,
+    PP_TRUETYPEFONTWEIGHT_SEMIBOLD,
+    PP_TRUETYPEFONTWEIGHT_BOLD,         // 9 is a 'bold' AppKit weight.
+    PP_TRUETYPEFONTWEIGHT_ULTRABOLD,
+    PP_TRUETYPEFONTWEIGHT_HEAVY,
+};
+const NSInteger kPepperFontWeightsLength = arraysize(kPepperFontWeights);
+
+}  // namespace
+
 void GetFontFamilies_SlowBlocking(std::vector<std::string>* font_families) {
   base::mac::ScopedNSAutoreleasePool autorelease_pool;
   NSFontManager* fontManager = [[[NSFontManager alloc] init] autorelease];
@@ -20,4 +43,40 @@
     font_families->push_back(base::SysNSStringToUTF8(family_name));
 }
 
+void GetFontsInFamily_SlowBlocking(
+    const std::string& family,
+    std::vector<ppapi::proxy::SerializedTrueTypeFontDesc>* fonts_in_family) {
+  base::mac::ScopedNSAutoreleasePool autorelease_pool;
+  NSFontManager* fontManager = [[[NSFontManager alloc] init] autorelease];
+  NSString* ns_family = base::SysUTF8ToNSString(family);
+  NSArray* ns_fonts_in_family =
+      [fontManager availableMembersOfFontFamily:ns_family];
+
+  for (NSArray* font_info in ns_fonts_in_family) {
+    ppapi::proxy::SerializedTrueTypeFontDesc desc;
+    desc.family = family;
+    NSInteger font_weight = [[font_info objectAtIndex:2] intValue];
+    font_weight = std::max(static_cast<NSInteger>(0), font_weight);
+    font_weight = std::min(kPepperFontWeightsLength - 1, font_weight);
+    desc.weight = kPepperFontWeights[font_weight];
+
+    NSFontTraitMask font_traits =
+        [[font_info objectAtIndex:3] unsignedIntValue];
+    desc.style = PP_TRUETYPEFONTSTYLE_NORMAL;
+    if (font_traits & NSItalicFontMask)
+      desc.style = PP_TRUETYPEFONTSTYLE_ITALIC;
+
+    desc.width = PP_TRUETYPEFONTWIDTH_NORMAL;
+    if (font_traits & NSCondensedFontMask)
+      desc.width = PP_TRUETYPEFONTWIDTH_CONDENSED;
+    else if (font_traits & NSExpandedFontMask)
+      desc.width = PP_TRUETYPEFONTWIDTH_EXPANDED;
+
+    // Mac doesn't support requesting non-default character sets.
+    desc.charset = PP_TRUETYPEFONTCHARSET_DEFAULT;
+
+    fonts_in_family->push_back(desc);
+  }
+}
+
 }  // namespace content
diff --git a/content/browser/renderer_host/pepper/pepper_truetype_font_list_win.cc b/content/browser/renderer_host/pepper/pepper_truetype_font_list_win.cc
index 6a3ee0f..37dff9b 100644
--- a/content/browser/renderer_host/pepper/pepper_truetype_font_list_win.cc
+++ b/content/browser/renderer_host/pepper/pepper_truetype_font_list_win.cc
@@ -8,17 +8,21 @@
 
 #include "base/utf_string_conversions.h"
 #include "base/win/scoped_hdc.h"
+#include "ppapi/c/dev/ppb_truetype_font_dev.h"
+#include "ppapi/proxy/serialized_structs.h"
 
 namespace content {
 
 namespace {
 
-static int CALLBACK EnumFontFamExProc(ENUMLOGFONTEXW* logical_font,
-                                      NEWTEXTMETRICEXW* physical_font,
-                                      DWORD font_type,
-                                      LPARAM lparam) {
-  std::vector<std::string>* font_families =
-      reinterpret_cast<std::vector<std::string>*>(lparam);
+typedef std::vector<std::string> FontFamilyList;
+typedef std::vector<ppapi::proxy::SerializedTrueTypeFontDesc> FontDescList;
+
+static int CALLBACK EnumFontFamiliesProc(ENUMLOGFONTEXW* logical_font,
+                                         NEWTEXTMETRICEXW* physical_font,
+                                         DWORD font_type,
+                                         LPARAM lparam) {
+  FontFamilyList* font_families = reinterpret_cast<FontFamilyList*>(lparam);
   if (font_families) {
     const LOGFONTW& lf = logical_font->elfLogFont;
     if (lf.lfFaceName[0] && lf.lfFaceName[0] != '@' &&
@@ -30,15 +34,50 @@
   return 1;
 }
 
+static int CALLBACK EnumFontsInFamilyProc(ENUMLOGFONTEXW* logical_font,
+                                          NEWTEXTMETRICEXW* physical_font,
+                                          DWORD font_type,
+                                          LPARAM lparam) {
+  FontDescList* fonts_in_family = reinterpret_cast<FontDescList*>(lparam);
+  if (fonts_in_family) {
+    const LOGFONTW& lf = logical_font->elfLogFont;
+    if (lf.lfFaceName[0] && lf.lfFaceName[0] != '@' &&
+        lf.lfOutPrecision == OUT_STROKE_PRECIS) {  // Outline fonts only.
+      ppapi::proxy::SerializedTrueTypeFontDesc desc;
+      desc.family = UTF16ToUTF8(lf.lfFaceName);
+      if (lf.lfItalic)
+        desc.style = PP_TRUETYPEFONTSTYLE_ITALIC;
+      desc.weight = static_cast<PP_TrueTypeFontWeight_Dev>(lf.lfWeight);
+      desc.width = PP_TRUETYPEFONTWIDTH_NORMAL;  // TODO(bbudge) support widths.
+      desc.charset =
+          static_cast<PP_TrueTypeFontCharset_Dev>(lf.lfCharSet);
+      fonts_in_family->push_back(desc);
+    }
+  }
+  return 1;
+}
+
 }  // namespace
 
-void GetFontFamilies_SlowBlocking(std::vector<std::string>* font_families) {
+void GetFontFamilies_SlowBlocking(FontFamilyList* font_families) {
   LOGFONTW logfont;
   memset(&logfont, 0, sizeof(logfont));
   logfont.lfCharSet = DEFAULT_CHARSET;
-  base::win::ScopedCreateDC hdc(::GetDC(NULL));
-  ::EnumFontFamiliesExW(hdc, &logfont, (FONTENUMPROCW)&EnumFontFamExProc,
+  base::win::ScopedCreateDC hdc(::CreateCompatibleDC(NULL));
+  ::EnumFontFamiliesExW(hdc, &logfont, (FONTENUMPROCW)&EnumFontFamiliesProc,
                         (LPARAM)font_families, 0);
 }
 
+void GetFontsInFamily_SlowBlocking(const std::string& family,
+                                   FontDescList* fonts_in_family) {
+  LOGFONTW logfont;
+  memset(&logfont, 0, sizeof(logfont));
+  logfont.lfCharSet = DEFAULT_CHARSET;
+  string16 family16 = UTF8ToUTF16(family);
+  memcpy(&logfont.lfFaceName, &family16[0], sizeof(logfont.lfFaceName));
+  base::win::ScopedCreateDC hdc(::CreateCompatibleDC(NULL));
+  ::EnumFontFamiliesExW(hdc, &logfont, (FONTENUMPROCW)&EnumFontsInFamilyProc,
+                        (LPARAM)fonts_in_family, 0);
+}
+
 }  // namespace content
diff --git a/content/browser/renderer_host/pepper/pepper_udp_socket_private_message_filter.cc b/content/browser/renderer_host/pepper/pepper_udp_socket_private_message_filter.cc
index 08384e7..e6563cf 100644
--- a/content/browser/renderer_host/pepper/pepper_udp_socket_private_message_filter.cc
+++ b/content/browser/renderer_host/pepper/pepper_udp_socket_private_message_filter.cc
@@ -165,7 +165,7 @@
   if (closed_)
     return PP_ERROR_FAILED;
 
-  if (recvfrom_buffer_.get())
+  if (recvfrom_buffer_)
     return PP_ERROR_INPROGRESS;
   if (num_bytes > ppapi::proxy::UDPSocketPrivateResource::kMaxReadSize) {
     // |num_bytes| value is checked on the plugin side.
@@ -263,7 +263,7 @@
     return;
   }
 
-  if (sendto_buffer_.get()) {
+  if (sendto_buffer_) {
     SendSendToError(context, PP_ERROR_INPROGRESS);
     return;
   }
@@ -380,7 +380,9 @@
 void PepperUDPSocketPrivateMessageFilter::SendRecvFromError(
     const ppapi::host::ReplyMessageContext& context,
     int32_t result) {
-  SendRecvFromReply(context, result, "",
+  SendRecvFromReply(context,
+                    result,
+                    std::string(),
                     NetAddressPrivateImpl::kInvalidNetAddress);
 }
 
diff --git a/content/browser/renderer_host/popup_menu_helper_mac.mm b/content/browser/renderer_host/popup_menu_helper_mac.mm
index c46d568..4e6d1a1 100644
--- a/content/browser/renderer_host/popup_menu_helper_mac.mm
+++ b/content/browser/renderer_host/popup_menu_helper_mac.mm
@@ -53,7 +53,8 @@
 
   {
     // Make sure events can be pumped while the menu is up.
-    MessageLoop::ScopedNestableTaskAllower allow(MessageLoop::current());
+    base::MessageLoop::ScopedNestableTaskAllower allow(
+        base::MessageLoop::current());
 
     // One of the events that could be pumped is |window.close()|.
     // User-initiated event-tracking loops protect against this by
diff --git a/content/browser/renderer_host/quota_dispatcher_host.cc b/content/browser/renderer_host/quota_dispatcher_host.cc
index 9ba96d2..fd297e7 100644
--- a/content/browser/renderer_host/quota_dispatcher_host.cc
+++ b/content/browser/renderer_host/quota_dispatcher_host.cc
@@ -60,11 +60,11 @@
       QuotaDispatcherHost* dispatcher_host,
       int request_id)
       : RequestDispatcher(dispatcher_host, request_id),
-        weak_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {}
+        weak_factory_(this) {}
   virtual ~QueryUsageAndQuotaDispatcher() {}
 
   void QueryStorageUsageAndQuota(const GURL& origin, StorageType type) {
-    quota_manager()->GetUsageAndQuota(
+    quota_manager()->GetUsageAndQuotaForWebApps(
         origin, type,
         base::Bind(&QueryUsageAndQuotaDispatcher::DidQueryStorageUsageAndQuota,
                    weak_factory_.GetWeakPtr()));
@@ -104,19 +104,20 @@
         current_quota_(0),
         requested_quota_(requested_quota),
         render_view_id_(render_view_id),
-        weak_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {}
+        weak_factory_(this) {}
   virtual ~RequestQuotaDispatcher() {}
 
   void Start() {
     DCHECK(type_ == quota::kStorageTypeTemporary ||
-           type_ == quota::kStorageTypePersistent);
+           type_ == quota::kStorageTypePersistent ||
+           type_ == quota::kStorageTypeSyncable);
     if (type_ == quota::kStorageTypePersistent) {
       quota_manager()->GetPersistentHostQuota(
           host_,
           base::Bind(&self_type::DidGetHostQuota,
                      weak_factory_.GetWeakPtr(), host_, type_));
     } else {
-      quota_manager()->GetUsageAndQuota(
+      quota_manager()->GetUsageAndQuotaForWebApps(
           origin_, type_,
           base::Bind(&self_type::DidGetTemporaryUsageAndQuota,
                      weak_factory_.GetWeakPtr()));
diff --git a/content/browser/renderer_host/render_message_filter.cc b/content/browser/renderer_host/render_message_filter.cc
index 8e2f45a..9bea24c 100644
--- a/content/browser/renderer_host/render_message_filter.cc
+++ b/content/browser/renderer_host/render_message_filter.cc
@@ -12,7 +12,7 @@
 #include "base/debug/alias.h"
 #include "base/file_util.h"
 #include "base/process_util.h"
-#include "base/sys_string_conversions.h"
+#include "base/strings/sys_string_conversions.h"
 #include "base/threading/thread.h"
 #include "base/threading/worker_pool.h"
 #include "base/utf_string_conversions.h"
@@ -83,6 +83,9 @@
 #include "content/browser/renderer_host/backing_store_win.h"
 #include "content/common/font_cache_dispatcher_win.h"
 #endif
+#if defined(OS_ANDROID)
+#include "media/base/android/webaudio_media_codec_bridge.h"
+#endif
 
 using net::CookieStore;
 
@@ -411,9 +414,12 @@
                         OnGetAudioHardwareConfig)
     IPC_MESSAGE_HANDLER(ViewHostMsg_GetMonitorColorProfile,
                         OnGetMonitorColorProfile)
-    IPC_MESSAGE_HANDLER(ViewHostMsg_MediaLogEvent, OnMediaLogEvent)
+    IPC_MESSAGE_HANDLER(ViewHostMsg_MediaLogEvents, OnMediaLogEvents)
     IPC_MESSAGE_HANDLER(ViewHostMsg_Are3DAPIsBlocked, OnAre3DAPIsBlocked)
     IPC_MESSAGE_HANDLER(ViewHostMsg_DidLose3DContext, OnDidLose3DContext)
+#if defined(OS_ANDROID)
+    IPC_MESSAGE_HANDLER(ViewHostMsg_RunWebAudioMediaCodec, OnWebAudioMediaCodec)
+#endif
     IPC_MESSAGE_UNHANDLED(handled = false)
   IPC_END_MESSAGE_MAP_EX()
 
@@ -815,7 +821,7 @@
   save_info->suggested_name = suggested_name;
   scoped_ptr<net::URLRequest> request(
       resource_context_->GetRequestContext()->CreateRequest(url, NULL));
-  request->set_referrer(referrer.url.spec());
+  request->SetReferrer(referrer.url.spec());
   webkit_glue::ConfigureURLRequestForReferrerPolicy(
       request.get(), referrer.policy);
   RecordDownloadSource(INITIATED_BY_RENDERER);
@@ -1007,9 +1013,10 @@
       base::Bind(base::IgnoreResult(&RenderMessageFilter::Send), this, reply));
 }
 
-void RenderMessageFilter::OnMediaLogEvent(const media::MediaLogEvent& event) {
+void RenderMessageFilter::OnMediaLogEvents(
+    const std::vector<media::MediaLogEvent>& events) {
   if (media_internals_)
-    media_internals_->OnMediaEvent(render_process_id_, event);
+    media_internals_->OnMediaEvents(render_process_id_, events);
 }
 
 void RenderMessageFilter::CheckPolicyForCookies(
@@ -1144,4 +1151,19 @@
 }
 #endif
 
+#if defined(OS_ANDROID)
+void RenderMessageFilter::OnWebAudioMediaCodec(
+    base::SharedMemoryHandle encoded_data_handle,
+    base::FileDescriptor pcm_output,
+    size_t data_size) {
+  // Let a WorkerPool handle this request since the WebAudio
+  // MediaCodec bridge is slow and can block while sending the data to
+  // the renderer.
+  base::WorkerPool::PostTask(
+      FROM_HERE,
+      base::Bind(&media::WebAudioMediaCodecBridge::RunWebAudioMediaCodec,
+                 encoded_data_handle, pcm_output, data_size),
+      true);
+}
+#endif
 }  // namespace content
diff --git a/content/browser/renderer_host/render_message_filter.h b/content/browser/renderer_host/render_message_filter.h
index 689b3f6..fb45016 100644
--- a/content/browser/renderer_host/render_message_filter.h
+++ b/content/browser/renderer_host/render_message_filter.h
@@ -33,6 +33,10 @@
 #include "content/common/mac/font_loader.h"
 #endif
 
+#if defined(OS_ANDROID)
+#include "base/threading/worker_pool.h"
+#endif
+
 struct FontDescriptor;
 struct ViewHostMsg_CreateWindow_Params;
 
@@ -227,7 +231,7 @@
                                  int flags,
                                  int message_id,
                                  int routing_id);
-  void OnMediaLogEvent(const media::MediaLogEvent&);
+  void OnMediaLogEvents(const std::vector<media::MediaLogEvent>&);
 
   // Check the policy for getting cookies. Gets the cookies if allowed.
   void CheckPolicyForCookies(const GURL& url,
@@ -256,6 +260,12 @@
                           ThreeDAPIType context_type,
                           int arb_robustness_status_code);
 
+#if defined(OS_ANDROID)
+  void OnWebAudioMediaCodec(base::SharedMemoryHandle encoded_data_handle,
+                            base::FileDescriptor pcm_output,
+                            size_t data_size);
+#endif
+
   // 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
   // by the BrowserProcess, which has a wider scope than we do.
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
index 9e71c1d..51d9298 100644
--- a/content/browser/renderer_host/render_process_host_impl.cc
+++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -56,8 +56,8 @@
 #include "content/browser/gpu/shader_disk_cache.h"
 #include "content/browser/histogram_message_filter.h"
 #include "content/browser/hyphenator/hyphenator_message_filter.h"
-#include "content/browser/in_process_webkit/indexed_db_context_impl.h"
 #include "content/browser/in_process_webkit/indexed_db_dispatcher_host.h"
+#include "content/browser/indexed_db/indexed_db_context_impl.h"
 #include "content/browser/loader/resource_message_filter.h"
 #include "content/browser/loader/resource_scheduler_filter.h"
 #include "content/browser/media/media_internals.h"
@@ -112,6 +112,7 @@
 #include "content/public/common/url_constants.h"
 #include "content/renderer/render_process_impl.h"
 #include "content/renderer/render_thread_impl.h"
+#include "gpu/command_buffer/service/gpu_switches.h"
 #include "ipc/ipc_channel.h"
 #include "ipc/ipc_logging.h"
 #include "ipc/ipc_platform_file.h"
@@ -143,6 +144,8 @@
 namespace content {
 namespace {
 
+base::MessageLoop* g_in_process_thread;
+
 void CacheShaderInfo(int32 id, base::FilePath path) {
   ShaderCacheFactory::GetInstance()->SetCacheInfo(id, path);
 }
@@ -170,9 +173,11 @@
   virtual void Init() OVERRIDE {
     render_process_.reset(new RenderProcessImpl());
     new RenderThreadImpl(channel_id_);
+    g_in_process_thread = message_loop();
   }
 
   virtual void CleanUp() OVERRIDE {
+    g_in_process_thread = NULL;
     render_process_.reset();
 
     // It's a little lame to manually set this flag.  But the single process
@@ -232,6 +237,9 @@
 base::LazyInstance<IDMap<RenderProcessHost> >::Leaky
     g_all_hosts = LAZY_INSTANCE_INITIALIZER;
 
+base::LazyInstance<scoped_refptr<BrowserPluginGeolocationPermissionContext> >
+    g_browser_plugin_geolocation_context = LAZY_INSTANCE_INITIALIZER;
+
 // Map of site to process, to ensure we only have one RenderProcessHost per
 // site in process-per-site mode.  Each map is specific to a BrowserContext.
 class SiteProcessMap : public base::SupportsUserData::Data {
@@ -375,9 +383,9 @@
           pending_views_(0),
           visible_widgets_(0),
           backgrounded_(true),
-          ALLOW_THIS_IN_INITIALIZER_LIST(cached_dibs_cleaner_(
-                FROM_HERE, base::TimeDelta::FromSeconds(5),
-                this, &RenderProcessHostImpl::ClearTransportDIBCache)),
+          cached_dibs_cleaner_(
+              FROM_HERE, base::TimeDelta::FromSeconds(5),
+              this, &RenderProcessHostImpl::ClearTransportDIBCache),
           is_initialized_(false),
           id_(ChildProcessHostImpl::GenerateChildProcessUniqueId()),
           browser_context_(browser_context),
@@ -399,10 +407,12 @@
   // Initialize |child_process_activity_time_| to a reasonable value.
   mark_child_process_activity_time();
 
-  if (!GetBrowserContext()->IsOffTheRecord()) {
+  if (!GetBrowserContext()->IsOffTheRecord() &&
+      !CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kDisableGpuShaderDiskCache)) {
     BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
                             base::Bind(&CacheShaderInfo, GetID(),
-                                       GetBrowserContext()->GetPath()));
+                                       storage_partition_impl_->GetPath()));
   }
 
   // Note: When we create the RenderProcessHostImpl, it's technically
@@ -425,8 +435,11 @@
   ClearTransportDIBCache();
   UnregisterHost(GetID());
 
-  BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
-                          base::Bind(&RemoveShaderInfo, GetID()));
+  if (!CommandLine::ForCurrentProcess()->HasSwitch(
+      switches::kDisableGpuShaderDiskCache)) {
+    BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
+                            base::Bind(&RemoveShaderInfo, GetID()));
+  }
 }
 
 void RenderProcessHostImpl::EnableSendQueue() {
@@ -436,7 +449,7 @@
 bool RenderProcessHostImpl::Init() {
   // calling Init() more than once does nothing, this makes it more convenient
   // for the view host which may not be sure in some cases
-  if (channel_.get())
+  if (channel_)
     return true;
 
   CommandLine::StringType renderer_prefix;
@@ -493,13 +506,13 @@
     in_process_renderer_.reset(new RendererMainThread(channel_id));
 
     base::Thread::Options options;
-#if !defined(TOOLKIT_GTK) && !defined(OS_ANDROID)
+#if defined(OS_WIN) && !defined(OS_MACOSX)
     // In-process plugins require this to be a UI message loop.
-    options.message_loop_type = MessageLoop::TYPE_UI;
+    options.message_loop_type = base::MessageLoop::TYPE_UI;
 #else
-    // We can't have multiple UI loops on GTK and Android, so we don't support
+    // We can't have multiple UI loops on Linux and Android, so we don't support
     // in-process plugins.
-    options.message_loop_type = MessageLoop::TYPE_DEFAULT;
+    options.message_loop_type = base::MessageLoop::TYPE_DEFAULT;
 #endif
     in_process_renderer_->StartWithOptions(options);
 
@@ -594,8 +607,12 @@
           GetID(),
           storage_partition_impl_->GetIndexedDBContext()));
   if (IsGuest()) {
+    if (!g_browser_plugin_geolocation_context.Get()) {
+      g_browser_plugin_geolocation_context.Get() =
+          new BrowserPluginGeolocationPermissionContext();
+    }
     channel_->AddFilter(GeolocationDispatcherHost::New(
-        GetID(), new BrowserPluginGeolocationPermissionContext()));
+        GetID(), g_browser_plugin_geolocation_context.Get()));
   } else {
     channel_->AddFilter(GeolocationDispatcherHost::New(
         GetID(), browser_context->GetGeolocationPermissionContext()));
@@ -786,9 +803,7 @@
     switches::kDisableAcceleratedVideoDecode,
     switches::kDisableApplicationCache,
     switches::kDisableAudio,
-    switches::kDisableAudioOutputResampler,
     switches::kDisableBreakpad,
-    switches::kDisableDataTransferItems,
     switches::kDisableDatabases,
     switches::kDisableDesktopNotifications,
     switches::kDisableDeviceOrientation,
@@ -796,22 +811,26 @@
     switches::kDisableGeolocation,
     switches::kDisableGLMultisampling,
     switches::kDisableGpuVsync,
+    switches::kDisableGpu,
     switches::kDisableHistogramCustomizer,
     switches::kDisableJavaScriptI18NAPI,
     switches::kDisableLocalStorage,
     switches::kDisableLogging,
     switches::kDisableSeccompFilterSandbox,
-    switches::kDisableSeccompSandbox,
     switches::kDisableSessionStorage,
     switches::kDisableSharedWorkers,
     switches::kDisableSpeechInput,
+    switches::kDisableTouchDragDrop,
+    switches::kDisableTouchEditing,
 #if defined(OS_ANDROID)
     switches::kEnableWebAudio,
     switches::kDisableWebRTC,
 #else
     switches::kDisableWebAudio,
 #endif
-    switches::kDisableWebSockets,
+    switches::kEnableWebMIDI,
+    switches::kEnableExperimentalCanvasFeatures,
+    switches::kEnableExperimentalWebSocket,
     switches::kDomAutomationController,
     switches::kEnableAccessibilityLogging,
     switches::kEnableBrowserPluginForAllViewTypes,
@@ -827,22 +846,27 @@
     switches::kEnableGpuBenchmarking,
     switches::kEnableMemoryBenchmarking,
     switches::kEnableLogging,
+    switches::kEnableSpeechSynthesis,
+    switches::kEnableTouchDragDrop,
+    switches::kEnableTouchEditing,
+    switches::kEnableVsyncNotification,
+    switches::kEnableWebPInAcceptHeader,
     switches::kDisableMediaSource,
-    switches::kDisableRendererSideMixing,
     switches::kEnableStrictSiteIsolation,
     switches::kDisableFullScreen,
     switches::kEnableNewDialogStyle,
 #if defined(ENABLE_PLUGINS)
     switches::kEnablePepperTesting,
+    switches::kDisablePepper3d,
 #endif
     switches::kEnablePreparsedJsCaching,
     switches::kEnablePruneGpuCommandBuffers,
     switches::kEnablePinch,
+    switches::kDisablePinch,
 #if defined(OS_MACOSX)
     // Allow this to be set when invoking the browser and relayed along.
     switches::kEnableSandboxLogging,
 #endif
-    switches::kEnableSeccompSandbox,
     switches::kEnableSoftwareCompositingGLAdapter,
     switches::kEnableStatsTable,
     switches::kEnableThreadedCompositing,
@@ -850,7 +874,6 @@
     switches::kEnableHighDpiCompositingForFixedPosition,
     switches::kDisableCompositingForFixedPosition,
     switches::kEnableAcceleratedPainting,
-    switches::kEnableTouchDragDrop,
     switches::kDisableThreadedCompositing,
     switches::kDisableTouchAdjustment,
     switches::kDefaultTileWidth,
@@ -860,6 +883,8 @@
     switches::kEnableViewport,
     switches::kEnableOpusPlayback,
     switches::kEnableVp9Playback,
+    switches::kEnableVp8AlphaPlayback,
+    switches::kEnableEac3Playback,
     switches::kForceDeviceScaleFactor,
     switches::kFullMemoryCrashReport,
 #if !defined (GOOGLE_CHROME_BUILD)
@@ -873,7 +898,7 @@
 #if defined(OS_ANDROID)
     switches::kNetworkCountryIso,
     switches::kDisableGestureRequirementForMediaPlayback,
-    switches::kUseExternalVideoSurface,
+    switches::kUseExternalVideoSurfaceThresholdInPixels,
 #endif
     switches::kNoReferrers,
     switches::kNoSandbox,
@@ -902,18 +927,22 @@
     // also be added to chrome/browser/chromeos/login/chrome_restart_request.cc.
     cc::switches::kBackgroundColorInsteadOfCheckerboard,
     cc::switches::kCompositeToMailbox,
-    cc::switches::kDisableCheapnessEstimator,
+    cc::switches::kDisableColorEstimator,
     cc::switches::kDisableImplSidePainting,
     cc::switches::kDisableThreadedAnimation,
     cc::switches::kEnableCompositorFrameMessage,
     cc::switches::kEnableImplSidePainting,
     cc::switches::kEnablePartialSwap,
     cc::switches::kEnablePerTilePainting,
+    cc::switches::kEnablePinchZoomScrollbars,
+    cc::switches::kDisablePinchZoomScrollbars,
     cc::switches::kEnablePredictionBenchmarking,
     cc::switches::kEnableRightAlignedScheduling,
     cc::switches::kEnableTopControlsPositionCalculation,
     cc::switches::kLowResolutionContentsScaleFactor,
+    cc::switches::kMaxUnusedResourceMemoryUsagePercentage,
     cc::switches::kNumRasterThreads,
+    cc::switches::kMaxTilesForInterestArea,
     cc::switches::kShowCompositedLayerBorders,
     cc::switches::kShowCompositedLayerTree,
     cc::switches::kShowFPSCounter,
@@ -924,12 +953,12 @@
     cc::switches::kShowScreenSpaceRects,
     cc::switches::kShowSurfaceDamageRects,
     cc::switches::kSlowDownRasterScaleFactor,
+    cc::switches::kStrictLayerPropertyChangeChecking,
     cc::switches::kTopControlsHeight,
     cc::switches::kTopControlsHideThreshold,
     cc::switches::kTopControlsShowThreshold,
     cc::switches::kTraceAllRenderedFrames,
     cc::switches::kTraceOverdraw,
-    cc::switches::kUseColorEstimator,
   };
   renderer_cmd->CopySwitchesFrom(browser_cmd, kSwitchNames,
                                  arraysize(kSwitchNames));
@@ -1003,15 +1032,15 @@
                   STANDARD_RIGHTS_REQUIRED | FILE_MAP_READ | FILE_MAP_WRITE,
                   FALSE, 0);
   return TransportDIB::Map(section);
-#elif defined(OS_MACOSX)
-  // On OSX, the browser allocates all DIBs and keeps a file descriptor around
-  // for each.
-  return widget_helper_->MapTransportDIB(dib_id);
+#elif defined(TOOLKIT_GTK) || (defined(OS_LINUX) && defined(USE_AURA))
+  return TransportDIB::Map(dib_id.shmkey);
 #elif defined(OS_ANDROID)
   return TransportDIB::Map(dib_id);
-#elif defined(OS_POSIX)
-  return TransportDIB::Map(dib_id.shmkey);
-#endif  // defined(OS_POSIX)
+#else
+  // On POSIX, the browser allocates all DIBs and keeps a file descriptor around
+  // for each.
+  return widget_helper_->MapTransportDIB(dib_id);
+#endif
 }
 
 TransportDIB* RenderProcessHostImpl::GetTransportDIB(
@@ -1043,7 +1072,7 @@
       }
     }
 
-#if defined(USE_X11)
+#if defined(TOOLKIT_GTK) || (defined(OS_LINUX) && defined(USE_AURA))
     smallest_iterator->second->Detach();
 #else
     delete smallest_iterator->second;
@@ -1057,7 +1086,7 @@
 }
 
 void RenderProcessHostImpl::ClearTransportDIBCache() {
-#if defined(USE_X11)
+#if defined(TOOLKIT_GTK) || (defined(OS_LINUX) && defined(USE_AURA))
   std::map<TransportDIB::Id, TransportDIB*>::const_iterator dib =
       cached_dibs_.begin();
   for (; dib != cached_dibs_.end(); ++dib)
@@ -1070,7 +1099,7 @@
 }
 
 bool RenderProcessHostImpl::Send(IPC::Message* msg) {
-  if (!channel_.get()) {
+  if (!channel_) {
     if (!is_initialized_) {
       queued_messages_.push(msg);
       return true;
@@ -1229,7 +1258,7 @@
         Source<RenderProcessHost>(this),
         NotificationService::NoDetails());
 
-    MessageLoop::current()->DeleteSoon(FROM_HERE, this);
+    base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
     deleting_soon_ = true;
     // It's important not to wait for the DeleteTask to delete the channel
     // proxy. Kill it off now. That way, in case the profile is going away, the
@@ -1519,6 +1548,11 @@
     map->RegisterProcess(site, process);
 }
 
+base::MessageLoop*
+    RenderProcessHostImpl::GetInProcessRendererThreadForTesting() {
+  return g_in_process_thread;
+}
+
 void RenderProcessHostImpl::ProcessDied(bool already_dead) {
   // Our child process has died.  If we didn't expect it, it's a crash.
   // In any case, we need to let everyone know it's gone.
@@ -1663,7 +1697,7 @@
   if (deleting_soon_)
     return;
 
-  if (child_process_launcher_.get()) {
+  if (child_process_launcher_) {
     if (!child_process_launcher_->GetHandle()) {
       OnChannelError();
       return;
diff --git a/content/browser/renderer_host/render_process_host_impl.h b/content/browser/renderer_host/render_process_host_impl.h
index 62abd7b..d1f71e0 100644
--- a/content/browser/renderer_host/render_process_host_impl.h
+++ b/content/browser/renderer_host/render_process_host_impl.h
@@ -21,6 +21,10 @@
 
 class CommandLine;
 
+namespace base {
+class MessageLoop;
+}
+
 namespace gfx {
 class Size;
 }
@@ -174,6 +178,8 @@
       RenderProcessHost* process,
       const GURL& url);
 
+  static base::MessageLoop* GetInProcessRendererThreadForTesting();
+
  protected:
   // A proxy for our IPC::Channel that lives on the IO thread (see
   // browser_process.h)
diff --git a/content/browser/renderer_host/render_sandbox_host_linux.cc b/content/browser/renderer_host/render_sandbox_host_linux.cc
index 07f0b20..97c9304 100644
--- a/content/browser/renderer_host/render_sandbox_host_linux.cc
+++ b/content/browser/renderer_host/render_sandbox_host_linux.cc
@@ -253,7 +253,7 @@
     }
 
     EnsureWebKitInitialized();
-    scoped_array<WebUChar> chars(new WebUChar[num_chars]);
+    scoped_ptr<WebUChar[]> chars(new WebUChar[num_chars]);
 
     for (int i = 0; i < num_chars; ++i) {
       uint32_t c;
@@ -278,7 +278,7 @@
     if (family.name.data()) {
       reply.WriteString(family.name.data());
     } else {
-      reply.WriteString("");
+      reply.WriteString(std::string());
     }
     reply.WriteBool(family.isBold);
     reply.WriteBool(family.isItalic);
@@ -664,12 +664,12 @@
 
 SandboxIPCProcess::~SandboxIPCProcess() {
   paths_.deleteAll();
-  if (webkit_platform_support_.get())
+  if (webkit_platform_support_)
     WebKit::shutdown();
 }
 
 void SandboxIPCProcess::EnsureWebKitInitialized() {
-  if (webkit_platform_support_.get())
+  if (webkit_platform_support_)
     return;
   webkit_platform_support_.reset(new WebKitPlatformSupportImpl);
   WebKit::initializeWithoutV8(webkit_platform_support_.get());
diff --git a/content/browser/renderer_host/render_view_host_browsertest.cc b/content/browser/renderer_host/render_view_host_browsertest.cc
index 335c966..d75dd7a 100644
--- a/content/browser/renderer_host/render_view_host_browsertest.cc
+++ b/content/browser/renderer_host/render_view_host_browsertest.cc
@@ -16,7 +16,7 @@
 #include "content/test/content_browser_test_utils.h"
 #include "net/base/host_port_pair.h"
 #include "net/base/net_util.h"
-#include "net/test/test_server.h"
+#include "net/test/spawned_test_server.h"
 
 namespace content {
 
diff --git a/content/browser/renderer_host/render_view_host_delegate.cc b/content/browser/renderer_host/render_view_host_delegate.cc
index 0d7c523..ddd381f 100644
--- a/content/browser/renderer_host/render_view_host_delegate.cc
+++ b/content/browser/renderer_host/render_view_host_delegate.cc
@@ -37,8 +37,8 @@
   return NULL;
 }
 
-webkit_glue::WebPreferences RenderViewHostDelegate::GetWebkitPrefs() {
-  return webkit_glue::WebPreferences();
+WebPreferences RenderViewHostDelegate::GetWebkitPrefs() {
+  return WebPreferences();
 }
 
 bool RenderViewHostDelegate::IsFullscreenForCurrentTab() const {
diff --git a/content/browser/renderer_host/render_view_host_delegate.h b/content/browser/renderer_host/render_view_host_delegate.h
index 5ee7314..f2be7e1 100644
--- a/content/browser/renderer_host/render_view_host_delegate.h
+++ b/content/browser/renderer_host/render_view_host_delegate.h
@@ -27,10 +27,7 @@
 struct ViewHostMsg_DidFailProvisionalLoadWithError_Params;
 struct ViewHostMsg_FrameNavigate_Params;
 struct ViewMsg_PostMessage_Params;
-
-namespace webkit_glue {
 struct WebPreferences;
-}
 
 namespace base {
 class ListValue;
@@ -62,8 +59,6 @@
 struct Referrer;
 struct RendererPreferences;
 
-typedef base::Callback< void(const MediaStreamDevices&) > MediaResponseCallback;
-
 //
 // RenderViewHostDelegate
 //
@@ -136,9 +131,9 @@
   virtual void RenderViewReady(RenderViewHost* render_view_host) {}
 
   // The RenderView died somehow (crashed or was killed by the user).
-  virtual void RenderViewGone(RenderViewHost* render_view_host,
-                              base::TerminationStatus status,
-                              int error_code) {}
+  virtual void RenderViewTerminated(RenderViewHost* render_view_host,
+                                    base::TerminationStatus status,
+                                    int error_code) {}
 
   // The RenderView is going to be deleted. This is called when each
   // RenderView is going to be destroyed
@@ -219,10 +214,6 @@
   // the window.
   virtual void DidDisownOpener(RenderViewHost* rvh) {}
 
-  // The RenderView has changed its frame hierarchy, so we need to update all
-  // other renderers interested in this event.
-  virtual void DidUpdateFrameTree(RenderViewHost* rvh) {}
-
   // The RenderView's main frame document element is ready. This happens when
   // the document has finished parsing.
   virtual void DocumentAvailableInMainFrame(RenderViewHost* render_view_host) {}
@@ -284,7 +275,7 @@
 
   // Returns a WebPreferences object that will be used by the renderer
   // associated with the owning render view host.
-  virtual webkit_glue::WebPreferences GetWebkitPrefs();
+  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
diff --git a/content/browser/renderer_host/render_view_host_impl.cc b/content/browser/renderer_host/render_view_host_impl.cc
index d48a82b..8424da9 100644
--- a/content/browser/renderer_host/render_view_host_impl.cc
+++ b/content/browser/renderer_host/render_view_host_impl.cc
@@ -13,7 +13,7 @@
 #include "base/command_line.h"
 #include "base/i18n/rtl.h"
 #include "base/json/json_reader.h"
-#include "base/json/json_writer.h"
+#include "base/lazy_instance.h"
 #include "base/message_loop.h"
 #include "base/metrics/histogram.h"
 #include "base/stl_util.h"
@@ -31,9 +31,9 @@
 #include "content/browser/renderer_host/render_view_host_delegate.h"
 #include "content/common/accessibility_messages.h"
 #include "content/common/browser_plugin/browser_plugin_messages.h"
-#include "content/common/content_constants_internal.h"
 #include "content/common/desktop_notification_messages.h"
 #include "content/common/drag_messages.h"
+#include "content/common/input_messages.h"
 #include "content/common/inter_process_time_ticks_converter.h"
 #include "content/common/speech_recognition_messages.h"
 #include "content/common/swapped_out_messages.h"
@@ -76,7 +76,7 @@
 #elif defined(OS_MACOSX)
 #include "content/browser/renderer_host/popup_menu_helper_mac.h"
 #elif defined(OS_ANDROID)
-#include "content/browser/android/media_player_manager_android.h"
+#include "content/browser/android/media_player_manager_impl.h"
 #endif
 
 using base::TimeDelta;
@@ -109,6 +109,9 @@
   }
 }
 
+base::LazyInstance<std::vector<RenderViewHost::CreatedCallback> >
+g_created_callbacks = LAZY_INSTANCE_INITIALIZER;
+
 }  // namespace
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -164,7 +167,7 @@
       enabled_bindings_(0),
       pending_request_id_(-1),
       navigations_suspended_(false),
-      suspended_nav_message_(NULL),
+      suspended_nav_params_(NULL),
       is_swapped_out_(swapped_out),
       is_subframe_(false),
       run_modal_reply_msg_(NULL),
@@ -188,15 +191,11 @@
 
   GetProcess()->EnableSendQueue();
 
-  GetContentClient()->browser()->RenderViewHostCreated(this);
-
-  NotificationService::current()->Notify(
-      NOTIFICATION_RENDER_VIEW_HOST_CREATED,
-      Source<RenderViewHost>(this),
-      NotificationService::NoDetails());
+  for (size_t i = 0; i < g_created_callbacks.Get().size(); i++)
+    g_created_callbacks.Get().at(i).Run(this);
 
 #if defined(OS_ANDROID)
-  media_player_manager_ = new MediaPlayerManagerAndroid(this);
+  media_player_manager_ = new MediaPlayerManagerImpl(this);
 #endif
 }
 
@@ -308,8 +307,6 @@
     }
   }
 
-  ViewMsg_Navigate* nav_message = new ViewMsg_Navigate(GetRoutingID(), params);
-
   // Only send the message if we aren't suspended at the start of a cross-site
   // request.
   if (navigations_suspended_) {
@@ -317,14 +314,14 @@
     // navigations will only be suspended during a cross-site request.  If a
     // second navigation occurs, WebContentsImpl will cancel this pending RVH
     // create a new pending RVH.
-    DCHECK(!suspended_nav_message_.get());
-    suspended_nav_message_.reset(nav_message);
+    DCHECK(!suspended_nav_params_.get());
+    suspended_nav_params_.reset(new ViewMsg_Navigate_Params(params));
   } else {
     // Get back to a clean state, in case we start a new navigation without
     // completing a RVH swap or unload handler.
     SetSwappedOut(false);
 
-    Send(nav_message);
+    Send(new ViewMsg_Navigate(GetRoutingID(), params));
   }
 
   // Force the throbber to start. We do this because WebKit's "started
@@ -356,33 +353,33 @@
   Navigate(params);
 }
 
-void RenderViewHostImpl::SetNavigationsSuspended(bool suspend) {
+void RenderViewHostImpl::SetNavigationsSuspended(
+    bool suspend,
+    const base::TimeTicks& proceed_time) {
   // This should only be called to toggle the state.
   DCHECK(navigations_suspended_ != suspend);
 
   navigations_suspended_ = suspend;
-  if (!suspend && suspended_nav_message_.get()) {
-    // There's a navigation message waiting to be sent.  Now that we're not
-    // suspended anymore, resume navigation by sending it.  If we were swapped
+  if (!suspend && suspended_nav_params_) {
+    // There's navigation message params waiting to be sent.  Now that we're not
+    // suspended anymore, resume navigation by sending them.  If we were swapped
     // out, we should also stop filtering out the IPC messages now.
     SetSwappedOut(false);
 
-    Send(suspended_nav_message_.release());
+    DCHECK(!proceed_time.is_null());
+    suspended_nav_params_->browser_navigation_start = proceed_time;
+    Send(new ViewMsg_Navigate(GetRoutingID(), *suspended_nav_params_.get()));
+    suspended_nav_params_.reset();
   }
 }
 
 void RenderViewHostImpl::CancelSuspendedNavigations() {
   // Clear any state if a pending navigation is canceled or pre-empted.
-  if (suspended_nav_message_.get())
-    suspended_nav_message_.reset();
+  if (suspended_nav_params_)
+    suspended_nav_params_.reset();
   navigations_suspended_ = false;
 }
 
-void RenderViewHostImpl::SetNavigationStartTime(
-    const base::TimeTicks& navigation_start) {
-  Send(new ViewMsg_SetNavigationStartTime(GetRoutingID(), navigation_start));
-}
-
 void RenderViewHostImpl::FirePageBeforeUnload(bool for_cross_site_transition) {
   if (!IsRenderViewLive()) {
     // This RenderViewHostImpl doesn't have a live renderer, so just
@@ -565,7 +562,8 @@
 void RenderViewHostImpl::ActivateNearestFindResult(int request_id,
                                                    float x,
                                                    float y) {
-  Send(new ViewMsg_ActivateNearestFindResult(GetRoutingID(), request_id, x, y));
+  Send(new InputMsg_ActivateNearestFindResult(GetRoutingID(),
+                                              request_id, x, y));
 }
 
 void RenderViewHostImpl::RequestFindMatchRects(int current_version) {
@@ -995,7 +993,6 @@
                         OnDomOperationResponse)
     IPC_MESSAGE_HANDLER(AccessibilityHostMsg_Notifications,
                         OnAccessibilityNotifications)
-    IPC_MESSAGE_HANDLER(ViewHostMsg_FrameTreeUpdated, OnFrameTreeUpdated)
     // Have the super handle all other messages.
     IPC_MESSAGE_UNHANDLED(
         handled = RenderWidgetHostImpl::OnMessageReceived(msg))
@@ -1122,9 +1119,9 @@
   // Our base class RenderWidgetHost needs to reset some stuff.
   RendererExited(render_view_termination_status_, exit_code);
 
-  delegate_->RenderViewGone(this,
-                            static_cast<base::TerminationStatus>(status),
-                            exit_code);
+  delegate_->RenderViewTerminated(this,
+                                  static_cast<base::TerminationStatus>(status),
+                                  exit_code);
 }
 
 void RenderViewHostImpl::OnDidStartProvisionalLoadForFrame(
@@ -1228,9 +1225,6 @@
   FilterURL(policy, process, true, &validated_params.password_form.action);
 
   delegate_->DidNavigate(this, validated_params);
-
-  // TODO(nasko): Send frame tree update for the top level frame, once
-  // http://crbug.com/153701 is fixed.
 }
 
 void RenderViewHostImpl::OnUpdateState(int32 page_id,
@@ -1727,6 +1721,19 @@
   }
 }
 
+void RenderViewHost::AddCreatedCallback(const CreatedCallback& callback) {
+  g_created_callbacks.Get().push_back(callback);
+}
+
+void RenderViewHost::RemoveCreatedCallback(const CreatedCallback& callback) {
+  for (size_t i = 0; i < g_created_callbacks.Get().size(); ++i) {
+    if (g_created_callbacks.Get().at(i).Equals(callback)) {
+      g_created_callbacks.Get().erase(g_created_callbacks.Get().begin() + i);
+      return;
+    }
+  }
+}
+
 void RenderViewHostImpl::SetAltErrorPageURL(const GURL& url) {
   Send(new ViewMsg_SetAltErrorPageURL(GetRoutingID(), url));
 }
@@ -1738,7 +1745,7 @@
   WasResized();
 }
 
-webkit_glue::WebPreferences RenderViewHostImpl::GetWebkitPreferences() {
+WebPreferences RenderViewHostImpl::GetWebkitPreferences() {
   return delegate_->GetWebkitPrefs();
 }
 
@@ -1749,20 +1756,6 @@
   Send(new ViewMsg_DisownOpener(GetRoutingID()));
 }
 
-void RenderViewHostImpl::UpdateFrameTree(
-    int process_id,
-    int route_id,
-    const std::string& frame_tree) {
-  // This should only be called when swapped out.
-  DCHECK(is_swapped_out_);
-
-  frame_tree_ = frame_tree;
-  Send(new ViewMsg_UpdateFrameTree(GetRoutingID(),
-                                   process_id,
-                                   route_id,
-                                   frame_tree_));
-}
-
 void RenderViewHostImpl::SetAccessibilityLayoutCompleteCallbackForTesting(
     const base::Closure& callback) {
   accessibility_layout_callback_ = callback;
@@ -1778,8 +1771,7 @@
   accessibility_other_callback_ = callback;
 }
 
-void RenderViewHostImpl::UpdateWebkitPreferences(
-    const webkit_glue::WebPreferences& prefs) {
+void RenderViewHostImpl::UpdateWebkitPreferences(const WebPreferences& prefs) {
   Send(new ViewMsg_UpdateWebPreferences(GetRoutingID(), prefs));
 }
 
@@ -1983,22 +1975,6 @@
       GetProcess()->GetID(), GetRoutingID(), notification_id);
 }
 
-#if defined(OS_MACOSX) || defined(OS_ANDROID)
-void RenderViewHostImpl::OnShowPopup(
-    const ViewHostMsg_ShowPopup_Params& params) {
-  RenderViewHostDelegateView* view = delegate_->GetDelegateView();
-  if (view) {
-    view->ShowPopupMenu(params.bounds,
-                        params.item_height,
-                        params.item_font_size,
-                        params.selected_item,
-                        params.popup_items,
-                        params.right_aligned,
-                        params.allow_multiple_selection);
-  }
-}
-#endif
-
 void RenderViewHostImpl::OnRunFileChooser(const FileChooserParams& params) {
   delegate_->RunFileChooser(this, params);
 }
@@ -2012,28 +1988,6 @@
       Details<DomOperationNotificationDetails>(&details));
 }
 
-void RenderViewHostImpl::OnFrameTreeUpdated(const std::string& frame_tree) {
-  // TODO(nasko): Remove once http://crbug.com/153701 is fixed.
-  DCHECK(false);
-  frame_tree_ = frame_tree;
-  delegate_->DidUpdateFrameTree(this);
-}
-
-void RenderViewHostImpl::SetSwappedOut(bool is_swapped_out) {
-  is_swapped_out_ = is_swapped_out;
-
-  // Whenever we change swap out state, we should not be waiting for
-  // beforeunload or unload acks.  We clear them here to be safe, since they
-  // can cause navigations to be ignored in OnNavigate.
-  is_waiting_for_beforeunload_ack_ = false;
-  is_waiting_for_unload_ack_ = false;
-  has_timed_out_on_unload_ = false;
-}
-
-void RenderViewHostImpl::ClearPowerSaveBlockers() {
-  STLDeleteValues(&power_save_blockers_);
-}
-
 void RenderViewHostImpl::OnGetWindowSnapshot(const int snapshot_id) {
   std::vector<unsigned char> png;
 
@@ -2057,4 +2011,35 @@
       GetRoutingID(), snapshot_id, gfx::Size(), png));
 }
 
+#if defined(OS_MACOSX) || defined(OS_ANDROID)
+void RenderViewHostImpl::OnShowPopup(
+    const ViewHostMsg_ShowPopup_Params& params) {
+  RenderViewHostDelegateView* view = delegate_->GetDelegateView();
+  if (view) {
+    view->ShowPopupMenu(params.bounds,
+                        params.item_height,
+                        params.item_font_size,
+                        params.selected_item,
+                        params.popup_items,
+                        params.right_aligned,
+                        params.allow_multiple_selection);
+  }
+}
+#endif
+
+void RenderViewHostImpl::SetSwappedOut(bool is_swapped_out) {
+  is_swapped_out_ = is_swapped_out;
+
+  // Whenever we change swap out state, we should not be waiting for
+  // beforeunload or unload acks.  We clear them here to be safe, since they
+  // can cause navigations to be ignored in OnNavigate.
+  is_waiting_for_beforeunload_ack_ = false;
+  is_waiting_for_unload_ack_ = false;
+  has_timed_out_on_unload_ = false;
+}
+
+void RenderViewHostImpl::ClearPowerSaveBlockers() {
+  STLDeleteValues(&power_save_blockers_);
+}
+
 }  // namespace content
diff --git a/content/browser/renderer_host/render_view_host_impl.h b/content/browser/renderer_host/render_view_host_impl.h
index 4b33cc0..baa4b2e 100644
--- a/content/browser/renderer_host/render_view_host_impl.h
+++ b/content/browser/renderer_host/render_view_host_impl.h
@@ -66,7 +66,7 @@
 struct ShowDesktopNotificationHostMsgParams;
 
 #if defined(OS_ANDROID)
-class MediaPlayerManagerAndroid;
+class MediaPlayerManagerImpl;
 #endif
 
 #if defined(COMPILER_MSVC)
@@ -204,9 +204,9 @@
   virtual void Zoom(PageZoom zoom) OVERRIDE;
   virtual void SyncRendererPrefs() OVERRIDE;
   virtual void ToggleSpeechInput() OVERRIDE;
-  virtual webkit_glue::WebPreferences GetWebkitPreferences() OVERRIDE;
+  virtual WebPreferences GetWebkitPreferences() OVERRIDE;
   virtual void UpdateWebkitPreferences(
-      const webkit_glue::WebPreferences& prefs) OVERRIDE;
+      const WebPreferences& prefs) OVERRIDE;
   virtual void NotifyTimezoneChange() OVERRIDE;
 
 #if defined(OS_ANDROID)
@@ -260,17 +260,17 @@
   // method with |suspend| equal to true.  If |suspend| is false and there is
   // a suspended_nav_message_, this will send the message.  This function
   // should only be called to toggle the state; callers should check
-  // are_navigations_suspended() first.
-  void SetNavigationsSuspended(bool suspend);
+  // are_navigations_suspended() first. If |suspend| is false, the time that the
+  // user decided the navigation should proceed should be passed as
+  // |proceed_time|.
+  void SetNavigationsSuspended(bool suspend,
+                               const base::TimeTicks& proceed_time);
 
   // Clears any suspended navigation state after a cross-site navigation is
   // canceled or suspended.  This is important if we later return to this
   // RenderViewHost.
   void CancelSuspendedNavigations();
 
-  // Informs the renderer of when the current navigation was allowed to proceed.
-  void SetNavigationStartTime(const base::TimeTicks& navigation_start);
-
   // Whether this RenderViewHost has been swapped out to be displayed by a
   // different process.
   bool is_swapped_out() const { return is_swapped_out_; }
@@ -378,7 +378,7 @@
 #endif
 
 #if defined(OS_ANDROID)
-  MediaPlayerManagerAndroid* media_player_manager() {
+  MediaPlayerManagerImpl* media_player_manager() {
     return media_player_manager_;
   }
 
@@ -395,20 +395,9 @@
     is_subframe_ = is_subframe;
   }
 
-  const std::string& frame_tree() const {
-    return frame_tree_;
-  }
-
   // Set the opener to null in the renderer process.
   void DisownOpener();
 
-  // Updates the frame tree for this RVH and sends an IPC down to the renderer
-  // process to keep them in sync. For more details, see the comments on
-  // ViewHostMsg_FrameTreeUpdated.
-  void UpdateFrameTree(int process_id,
-                       int route_id,
-                       const std::string& frame_tree);
-
   void set_save_accessibility_tree_for_testing(bool save) {
     save_accessibility_tree_for_testing_ = save;
   }
@@ -558,7 +547,6 @@
   void OnRunFileChooser(const FileChooserParams& params);
   void OnDomOperationResponse(const std::string& json_string,
                               int automation_id);
-  void OnFrameTreeUpdated(const std::string& frame_tree);
   void OnGetWindowSnapshot(const int snapshot_id);
 
 #if defined(OS_MACOSX) || defined(OS_ANDROID)
@@ -603,11 +591,11 @@
   // RenderViewHost.
   bool navigations_suspended_;
 
-  // We only buffer a suspended navigation message while we a pending RVH for a
-  // WebContentsImpl.  There will only ever be one suspended navigation, because
-  // WebContentsImpl will destroy the pending RVH and create a new one if a
-  // second navigation occurs.
-  scoped_ptr<ViewMsg_Navigate> suspended_nav_message_;
+  // We only buffer the params for a suspended navigation while we have a
+  // pending RVH for a WebContentsImpl.  There will only ever be one suspended
+  // navigation, because WebContentsImpl will destroy the pending RVH and create
+  // a new one if a second navigation occurs.
+  scoped_ptr<ViewMsg_Navigate_Params> suspended_nav_params_;
 
   // Whether this RenderViewHost is currently swapped out, such that the view is
   // being rendered by another process.
@@ -664,11 +652,6 @@
   // Whether the accessibility tree should be saved, for unit testing.
   bool save_accessibility_tree_for_testing_;
 
-  // A JSON serialized representation of the frame tree for the current document
-  // in the render view. For more details, see the comments on
-  // ViewHostMsg_FrameTreeUpdated.
-  std::string frame_tree_;
-
   // The most recently received accessibility tree - for unit testing only.
   AccessibilityNodeDataTreeNode accessibility_tree_;
 
@@ -689,7 +672,7 @@
 #if defined(OS_ANDROID)
   // Manages all the android mediaplayer objects and handling IPCs for video.
   // This class inherits from RenderViewHostObserver.
-  MediaPlayerManagerAndroid* media_player_manager_;
+  MediaPlayerManagerImpl* media_player_manager_;
 #endif
 
   DISALLOW_COPY_AND_ASSIGN(RenderViewHostImpl);
diff --git a/content/browser/renderer_host/render_view_host_manager_browsertest.cc b/content/browser/renderer_host/render_view_host_manager_browsertest.cc
index a2ce269..00a2f67 100644
--- a/content/browser/renderer_host/render_view_host_manager_browsertest.cc
+++ b/content/browser/renderer_host/render_view_host_manager_browsertest.cc
@@ -8,10 +8,10 @@
 #include "base/path_service.h"
 #include "base/utf_string_conversions.h"
 #include "base/values.h"
-#include "content/common/content_constants_internal.h"
 #include "content/browser/renderer_host/render_view_host_impl.h"
 #include "content/browser/site_instance_impl.h"
 #include "content/browser/web_contents/web_contents_impl.h"
+#include "content/common/content_constants_internal.h"
 #include "content/public/browser/navigation_controller.h"
 #include "content/public/browser/navigation_entry.h"
 #include "content/public/browser/notification_details.h"
@@ -28,66 +28,9 @@
 #include "content/test/content_browser_test.h"
 #include "content/test/content_browser_test_utils.h"
 #include "net/base/net_util.h"
-#include "net/test/test_server.h"
+#include "net/test/spawned_test_server.h"
 
 namespace content {
-namespace {
-
-bool CompareTrees(base::DictionaryValue* first, base::DictionaryValue* second) {
-  string16 name1;
-  string16 name2;
-  if (!first->GetString(kFrameTreeNodeNameKey, &name1) ||
-      !second->GetString(kFrameTreeNodeNameKey, &name2))
-    return false;
-  if (name1 != name2)
-    return false;
-
-  int id1 = 0;
-  int id2 = 0;
-  if (!first->GetInteger(kFrameTreeNodeIdKey, &id1) ||
-      !second->GetInteger(kFrameTreeNodeIdKey, &id2)) {
-    return false;
-  }
-  if (id1 != id2)
-    return false;
-
-  ListValue* subtree1 = NULL;
-  ListValue* subtree2 = NULL;
-  bool result1 = first->GetList(kFrameTreeNodeSubtreeKey, &subtree1);
-  bool result2 = second->GetList(kFrameTreeNodeSubtreeKey, &subtree2);
-  if (!result1 && !result2)
-    return true;
-  if (!result1 || !result2)
-    return false;
-
-  if (subtree1->GetSize() != subtree2->GetSize())
-    return false;
-
-  base::DictionaryValue* child1 = NULL;
-  base::DictionaryValue* child2 = NULL;
-  for (size_t i = 0; i < subtree1->GetSize(); ++i) {
-    if (!subtree1->GetDictionary(i, &child1) ||
-        !subtree2->GetDictionary(i, &child2)) {
-      return false;
-    }
-    if (!CompareTrees(child1, child2))
-      return false;
-  }
-
-  return true;
-}
-
-base::DictionaryValue* GetTree(RenderViewHostImpl* rvh) {
-  std::string frame_tree = rvh->frame_tree();
-  EXPECT_FALSE(frame_tree.empty());
-  base::Value* v = base::JSONReader::Read(frame_tree);
-  base::DictionaryValue* tree = NULL;
-  EXPECT_TRUE(v->IsType(base::Value::TYPE_DICTIONARY));
-  EXPECT_TRUE(v->GetAsDictionary(&tree));
-  return tree;
-}
-
-} // namespace
 
 class RenderViewHostManagerTest : public ContentBrowserTest {
  public:
@@ -97,10 +40,10 @@
       const std::string& original_file_path,
       const net::HostPortPair& host_port_pair,
       std::string* replacement_path) {
-    std::vector<net::TestServer::StringPair> replacement_text;
+    std::vector<net::SpawnedTestServer::StringPair> replacement_text;
     replacement_text.push_back(
         make_pair("REPLACE_WITH_HOST_AND_PORT", host_port_pair.ToString()));
-    return net::TestServer::GetFilePathWithReplacements(
+    return net::SpawnedTestServer::GetFilePathWithReplacements(
         original_file_path, replacement_text, replacement_path);
   }
 };
@@ -109,9 +52,9 @@
 IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest, NoScriptAccessAfterSwapOut) {
   // Start two servers with different sites.
   ASSERT_TRUE(test_server()->Start());
-  net::TestServer https_server(
-      net::TestServer::TYPE_HTTPS,
-      net::TestServer::kLocalhost,
+  net::SpawnedTestServer https_server(
+      net::SpawnedTestServer::TYPE_HTTPS,
+      net::SpawnedTestServer::kLocalhost,
       base::FilePath(FILE_PATH_LITERAL("content/test/data")));
   ASSERT_TRUE(https_server.Start());
 
@@ -177,9 +120,9 @@
                        SwapProcessWithRelNoreferrerAndTargetBlank) {
   // Start two servers with different sites.
   ASSERT_TRUE(test_server()->Start());
-  net::TestServer https_server(
-      net::TestServer::TYPE_HTTPS,
-      net::TestServer::kLocalhost,
+  net::SpawnedTestServer https_server(
+      net::SpawnedTestServer::TYPE_HTTPS,
+      net::SpawnedTestServer::kLocalhost,
       base::FilePath(FILE_PATH_LITERAL("content/test/data")));
   ASSERT_TRUE(https_server.Start());
 
@@ -230,9 +173,9 @@
                        SwapProcessWithSameSiteRelNoreferrer) {
   // Start two servers with different sites.
   ASSERT_TRUE(test_server()->Start());
-  net::TestServer https_server(
-      net::TestServer::TYPE_HTTPS,
-      net::TestServer::kLocalhost,
+  net::SpawnedTestServer https_server(
+      net::SpawnedTestServer::TYPE_HTTPS,
+      net::SpawnedTestServer::kLocalhost,
       base::FilePath(FILE_PATH_LITERAL("content/test/data")));
   ASSERT_TRUE(https_server.Start());
 
@@ -283,9 +226,9 @@
                        DontSwapProcessWithOnlyTargetBlank) {
   // Start two servers with different sites.
   ASSERT_TRUE(test_server()->Start());
-  net::TestServer https_server(
-      net::TestServer::TYPE_HTTPS,
-      net::TestServer::kLocalhost,
+  net::SpawnedTestServer https_server(
+      net::SpawnedTestServer::TYPE_HTTPS,
+      net::SpawnedTestServer::kLocalhost,
       base::FilePath(FILE_PATH_LITERAL("content/test/data")));
   ASSERT_TRUE(https_server.Start());
 
@@ -331,9 +274,9 @@
                        DontSwapProcessWithOnlyRelNoreferrer) {
   // Start two servers with different sites.
   ASSERT_TRUE(test_server()->Start());
-  net::TestServer https_server(
-      net::TestServer::TYPE_HTTPS,
-      net::TestServer::kLocalhost,
+  net::SpawnedTestServer https_server(
+      net::SpawnedTestServer::TYPE_HTTPS,
+      net::SpawnedTestServer::kLocalhost,
       base::FilePath(FILE_PATH_LITERAL("content/test/data")));
   ASSERT_TRUE(https_server.Start());
 
@@ -377,9 +320,9 @@
                        AllowTargetedNavigationsAfterSwap) {
   // Start two servers with different sites.
   ASSERT_TRUE(test_server()->Start());
-  net::TestServer https_server(
-      net::TestServer::TYPE_HTTPS,
-      net::TestServer::kLocalhost,
+  net::SpawnedTestServer https_server(
+      net::SpawnedTestServer::TYPE_HTTPS,
+      net::SpawnedTestServer::kLocalhost,
       base::FilePath(FILE_PATH_LITERAL("content/test/data")));
   ASSERT_TRUE(https_server.Start());
 
@@ -460,9 +403,9 @@
 IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest, DisownOpener) {
   // Start two servers with different sites.
   ASSERT_TRUE(test_server()->Start());
-  net::TestServer https_server(
-      net::TestServer::TYPE_HTTPS,
-      net::TestServer::kLocalhost,
+  net::SpawnedTestServer https_server(
+      net::SpawnedTestServer::TYPE_HTTPS,
+      net::SpawnedTestServer::kLocalhost,
       base::FilePath(FILE_PATH_LITERAL("content/test/data")));
   ASSERT_TRUE(https_server.Start());
 
@@ -535,6 +478,20 @@
   EXPECT_TRUE(success);
 }
 
+// Test that subframes can disown their openers.  http://crbug.com/225528.
+IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest, DisownSubframeOpener) {
+  const GURL frame_url("data:text/html,<iframe name=\"foo\"></iframe>");
+  NavigateToURL(shell(), frame_url);
+
+  // Give the frame an opener using window.open.
+  EXPECT_TRUE(ExecuteScript(shell()->web_contents(),
+                            "window.open('about:blank','foo');"));
+
+  // Now disown the frame's opener.  Shouldn't crash.
+  EXPECT_TRUE(ExecuteScript(shell()->web_contents(),
+                            "window.frames[0].opener = null;"));
+}
+
 // Test for crbug.com/99202.  PostMessage calls should still work after
 // navigating the source and target windows to different sites.
 // Specifically:
@@ -548,9 +505,9 @@
                        SupportCrossProcessPostMessage) {
   // Start two servers with different sites.
   ASSERT_TRUE(test_server()->Start());
-  net::TestServer https_server(
-      net::TestServer::TYPE_HTTPS,
-      net::TestServer::kLocalhost,
+  net::SpawnedTestServer https_server(
+      net::SpawnedTestServer::TYPE_HTTPS,
+      net::SpawnedTestServer::kLocalhost,
       base::FilePath(FILE_PATH_LITERAL("content/test/data")));
   ASSERT_TRUE(https_server.Start());
 
@@ -686,9 +643,9 @@
                        AllowTargetedNavigationsInOpenerAfterSwap) {
   // Start two servers with different sites.
   ASSERT_TRUE(test_server()->Start());
-  net::TestServer https_server(
-      net::TestServer::TYPE_HTTPS,
-      net::TestServer::kLocalhost,
+  net::SpawnedTestServer https_server(
+      net::SpawnedTestServer::TYPE_HTTPS,
+      net::SpawnedTestServer::kLocalhost,
       base::FilePath(FILE_PATH_LITERAL("content/test/data")));
   ASSERT_TRUE(https_server.Start());
 
@@ -757,9 +714,9 @@
                        ProcessExitWithSwappedOutViews) {
   // Start two servers with different sites.
   ASSERT_TRUE(test_server()->Start());
-  net::TestServer https_server(
-      net::TestServer::TYPE_HTTPS,
-      net::TestServer::kLocalhost,
+  net::SpawnedTestServer https_server(
+      net::SpawnedTestServer::TYPE_HTTPS,
+      net::SpawnedTestServer::kLocalhost,
       base::FilePath(FILE_PATH_LITERAL("content/test/data")));
   ASSERT_TRUE(https_server.Start());
 
@@ -824,9 +781,9 @@
 IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest, ClickLinkAfter204Error) {
   // Start two servers with different sites.
   ASSERT_TRUE(test_server()->Start());
-  net::TestServer https_server(
-      net::TestServer::TYPE_HTTPS,
-      net::TestServer::kLocalhost,
+  net::SpawnedTestServer https_server(
+      net::SpawnedTestServer::TYPE_HTTPS,
+      net::SpawnedTestServer::kLocalhost,
       base::FilePath(FILE_PATH_LITERAL("content/test/data")));
   ASSERT_TRUE(https_server.Start());
 
@@ -887,9 +844,9 @@
 
   // Start two servers with different sites.
   ASSERT_TRUE(test_server()->Start());
-  net::TestServer https_server(
-      net::TestServer::TYPE_HTTPS,
-      net::TestServer::kLocalhost,
+  net::SpawnedTestServer https_server(
+      net::SpawnedTestServer::TYPE_HTTPS,
+      net::SpawnedTestServer::kLocalhost,
       base::FilePath(FILE_PATH_LITERAL("content/test/data")));
   ASSERT_TRUE(https_server.Start());
 
@@ -1002,9 +959,9 @@
                        SwappedOutViewHasCorrectVisibilityState) {
   // Start two servers with different sites.
   ASSERT_TRUE(test_server()->Start());
-  net::TestServer https_server(
-      net::TestServer::TYPE_HTTPS,
-      net::TestServer::kLocalhost,
+  net::SpawnedTestServer https_server(
+      net::SpawnedTestServer::TYPE_HTTPS,
+      net::SpawnedTestServer::kLocalhost,
       base::FilePath(FILE_PATH_LITERAL("content/test/data")));
   ASSERT_TRUE(https_server.Start());
 
@@ -1128,9 +1085,9 @@
 IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest, LeakingRenderViewHosts) {
   // Start two servers with different sites.
   ASSERT_TRUE(test_server()->Start());
-  net::TestServer https_server(
-      net::TestServer::TYPE_HTTPS,
-      net::TestServer::kLocalhost,
+  net::SpawnedTestServer https_server(
+      net::SpawnedTestServer::TYPE_HTTPS,
+      net::SpawnedTestServer::kLocalhost,
       base::FilePath(FILE_PATH_LITERAL("content/test/data")));
   ASSERT_TRUE(https_server.Start());
 
@@ -1186,173 +1143,6 @@
   EXPECT_EQ(0U, rvh_observers.GetNumObservers());
 }
 
-// Test for correct propagation of the frame hierarchy across processes in the
-// same BrowsingInstance. The test starts by navigating to a page that has
-// multiple nested frames. It then opens two windows and navigates each one
-// to a separate site, so at the end we have 3 SiteInstances. The opened
-// windows have swapped out RenderViews corresponding to the opener, so those
-// swapped out views must have a matching frame hierarchy. The test checks
-// that frame hierarchies are kept in sync through navigations, reloading, and
-// JavaScript manipulation of the frame tree.
-//
-// Disable the test until http://crbug.com/153701 is fixed.
-IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest, DISABLED_FrameTreeUpdates) {
-  // Start two servers to allow using different sites.
-  EXPECT_TRUE(test_server()->Start());
-  net::TestServer https_server(
-      net::TestServer::TYPE_HTTPS,
-      net::TestServer::kLocalhost,
-      base::FilePath(FILE_PATH_LITERAL("content/test/data")));
-  EXPECT_TRUE(https_server.Start());
-
-  GURL frame_tree_url(test_server()->GetURL("files/frame_tree/top.html"));
-
-  // Replace the 127.0.0.1 with localhost, which will give us a different
-  // site instance.
-  GURL::Replacements replacements;
-  std::string new_host("localhost");
-  replacements.SetHostStr(new_host);
-  GURL remote_frame = test_server()->GetURL(
-      "files/frame_tree/1-1.html").ReplaceComponents(replacements);
-
-  bool success = false;
-  base::DictionaryValue* frames = NULL;
-  base::ListValue* subtree = NULL;
-
-  // First navigate to a page with no frames and ensure the frame tree has no
-  // subtrees.
-  NavigateToURL(shell(), test_server()->GetURL("files/simple_page.html"));
-  WebContents* opener_contents = shell()->web_contents();
-  RenderViewHostManager* opener_rvhm = static_cast<WebContentsImpl*>(
-      opener_contents)->GetRenderManagerForTesting();
-  frames = GetTree(opener_rvhm->current_host());
-  EXPECT_FALSE(frames->GetList(kFrameTreeNodeSubtreeKey, &subtree));
-
-  NavigateToURL(shell(), frame_tree_url);
-  frames = GetTree(opener_rvhm->current_host());
-  EXPECT_TRUE(frames->GetList(kFrameTreeNodeSubtreeKey, &subtree));
-  EXPECT_TRUE(subtree->GetSize() == 3);
-
-  scoped_refptr<SiteInstance> orig_site_instance(
-      opener_contents->GetSiteInstance());
-  EXPECT_TRUE(orig_site_instance != NULL);
-
-  ShellAddedObserver shell_observer1;
-  EXPECT_TRUE(ExecuteScriptAndExtractBool(
-      opener_contents,
-      "window.domAutomationController.send(openWindow('1-3.html'));",
-      &success));
-  EXPECT_TRUE(success);
-
-  Shell* shell1 = shell_observer1.GetShell();
-  WebContents* contents1 = shell1->web_contents();
-  WaitForLoadStop(contents1);
-  RenderViewHostManager* rvhm1 = static_cast<WebContentsImpl*>(
-      contents1)->GetRenderManagerForTesting();
-  EXPECT_EQ("/files/frame_tree/1-3.html", contents1->GetURL().path());
-
-  // Now navigate the new window to a different SiteInstance.
-  NavigateToURL(shell1, https_server.GetURL("files/title1.html"));
-  EXPECT_EQ("/files/title1.html", contents1->GetURL().path());
-  scoped_refptr<SiteInstance> site_instance1(
-      contents1->GetSiteInstance());
-  EXPECT_NE(orig_site_instance, site_instance1);
-
-  ShellAddedObserver shell_observer2;
-  EXPECT_TRUE(ExecuteScriptAndExtractBool(
-      opener_contents,
-      "window.domAutomationController.send(openWindow('../title2.html'));",
-      &success));
-  EXPECT_TRUE(success);
-
-  Shell* shell2 = shell_observer2.GetShell();
-  WebContents* contents2 = shell2->web_contents();
-  WaitForLoadStop(contents2);
-  EXPECT_EQ("/files/title2.html", contents2->GetURL().path());
-
-  // Navigate the second new window to a different SiteInstance as well.
-  NavigateToURL(shell2, remote_frame);
-  EXPECT_EQ("/files/frame_tree/1-1.html", contents2->GetURL().path());
-  scoped_refptr<SiteInstance> site_instance2(
-      contents2->GetSiteInstance());
-  EXPECT_NE(orig_site_instance, site_instance2);
-  EXPECT_NE(site_instance1, site_instance2);
-
-  RenderViewHostManager* rvhm2 = static_cast<WebContentsImpl*>(
-      contents2)->GetRenderManagerForTesting();
-
-  EXPECT_TRUE(CompareTrees(
-      GetTree(opener_rvhm->current_host()),
-      GetTree(opener_rvhm->GetSwappedOutRenderViewHost(site_instance1))));
-  EXPECT_TRUE(CompareTrees(
-      GetTree(opener_rvhm->current_host()),
-      GetTree(opener_rvhm->GetSwappedOutRenderViewHost(site_instance2))));
-
-  EXPECT_TRUE(CompareTrees(
-      GetTree(rvhm1->current_host()),
-      GetTree(rvhm1->GetSwappedOutRenderViewHost(orig_site_instance))));
-  EXPECT_TRUE(CompareTrees(
-      GetTree(rvhm2->current_host()),
-      GetTree(rvhm2->GetSwappedOutRenderViewHost(orig_site_instance))));
-
-  // Verify that the frame trees from different windows aren't equal.
-  EXPECT_FALSE(CompareTrees(
-      GetTree(opener_rvhm->current_host()), GetTree(rvhm1->current_host())));
-  EXPECT_FALSE(CompareTrees(
-      GetTree(opener_rvhm->current_host()), GetTree(rvhm2->current_host())));
-
-  // Reload the original page, which will cause subframe ids to change. This
-  // will ensure that the ids are properly replicated across reload.
-  NavigateToURL(shell(), frame_tree_url);
-
-  EXPECT_TRUE(CompareTrees(
-      GetTree(opener_rvhm->current_host()),
-      GetTree(opener_rvhm->GetSwappedOutRenderViewHost(site_instance1))));
-  EXPECT_TRUE(CompareTrees(
-      GetTree(opener_rvhm->current_host()),
-      GetTree(opener_rvhm->GetSwappedOutRenderViewHost(site_instance2))));
-
-  EXPECT_FALSE(CompareTrees(
-      GetTree(opener_rvhm->current_host()), GetTree(rvhm1->current_host())));
-  EXPECT_FALSE(CompareTrees(
-      GetTree(opener_rvhm->current_host()), GetTree(rvhm2->current_host())));
-
-  // Now let's ensure that using JS to add/remove frames results in proper
-  // updates.
-  EXPECT_TRUE(ExecuteScriptAndExtractBool(
-      opener_contents,
-      "window.domAutomationController.send(removeFrame());",
-      &success));
-  EXPECT_TRUE(success);
-  frames = GetTree(opener_rvhm->current_host());
-  EXPECT_TRUE(frames->GetList(kFrameTreeNodeSubtreeKey, &subtree));
-  EXPECT_EQ(subtree->GetSize(), 2U);
-
-  // Create a load observer for the iframe that will be created by the
-  // JavaScript code we will execute.
-  WindowedNotificationObserver load_observer(
-      NOTIFICATION_LOAD_STOP,
-      Source<NavigationController>(
-              &opener_contents->GetController()));
-  EXPECT_TRUE(ExecuteScriptAndExtractBool(
-      opener_contents,
-      "window.domAutomationController.send(addFrame());",
-      &success));
-  EXPECT_TRUE(success);
-  load_observer.Wait();
-
-  frames = GetTree(opener_rvhm->current_host());
-  EXPECT_TRUE(frames->GetList(kFrameTreeNodeSubtreeKey, &subtree));
-  EXPECT_EQ(subtree->GetSize(), 3U);
-
-  EXPECT_TRUE(CompareTrees(
-      GetTree(opener_rvhm->current_host()),
-      GetTree(opener_rvhm->GetSwappedOutRenderViewHost(site_instance1))));
-  EXPECT_TRUE(CompareTrees(
-      GetTree(opener_rvhm->current_host()),
-      GetTree(opener_rvhm->GetSwappedOutRenderViewHost(site_instance2))));
-}
-
 // Test for crbug.com/143155.  Frame tree updates during unload should not
 // interrupt the intended navigation and show swappedout:// instead.
 // Specifically:
@@ -1368,9 +1158,9 @@
                        DontPreemptNavigationWithFrameTreeUpdate) {
   // Start two servers with different sites.
   ASSERT_TRUE(test_server()->Start());
-  net::TestServer https_server(
-      net::TestServer::TYPE_HTTPS,
-      net::TestServer::kLocalhost,
+  net::SpawnedTestServer https_server(
+      net::SpawnedTestServer::TYPE_HTTPS,
+      net::SpawnedTestServer::kLocalhost,
       base::FilePath(FILE_PATH_LITERAL("content/test/data")));
   ASSERT_TRUE(https_server.Start());
 
diff --git a/content/browser/renderer_host/render_view_host_unittest.cc b/content/browser/renderer_host/render_view_host_unittest.cc
index 2645f62..f523c06 100644
--- a/content/browser/renderer_host/render_view_host_unittest.cc
+++ b/content/browser/renderer_host/render_view_host_unittest.cc
@@ -6,6 +6,7 @@
 #include "content/browser/child_process_security_policy_impl.h"
 #include "content/browser/renderer_host/test_render_view_host.h"
 #include "content/browser/web_contents/navigation_controller_impl.h"
+#include "content/common/input_messages.h"
 #include "content/common/view_messages.h"
 #include "content/port/browser/render_view_host_delegate_view.h"
 #include "content/public/browser/navigation_entry.h"
@@ -214,11 +215,11 @@
 // Test that OnInputEventAck() detects bad messages.
 TEST_F(RenderViewHostTest, BadMessageHandlerInputEventAck) {
   EXPECT_EQ(0, process()->bad_msg_count());
-  // ViewHostMsg_HandleInputEvent_ACK is defined taking 0 params but
+  // InputHostMsg_HandleInputEvent_ACK is defined taking 0 params but
   // the code actually expects it to have at least one int para, this this
   // bogus message will not fail at de-serialization but should fail in
   // OnInputEventAck() processing.
-  IPC::Message message(0, ViewHostMsg_HandleInputEvent_ACK::ID,
+  IPC::Message message(0, InputHostMsg_HandleInputEvent_ACK::ID,
                        IPC::Message::PRIORITY_NORMAL);
   test_rvh()->OnMessageReceived(message);
   EXPECT_EQ(1, process()->bad_msg_count());
diff --git a/content/browser/renderer_host/render_widget_host_browsertest.cc b/content/browser/renderer_host/render_widget_host_browsertest.cc
new file mode 100644
index 0000000..9f11299
--- /dev/null
+++ b/content/browser/renderer_host/render_widget_host_browsertest.cc
@@ -0,0 +1,68 @@
+// Copyright (c) 2013 The Chromium Authors. 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/path_service.h"
+#include "base/run_loop.h"
+#include "content/public/browser/render_view_host.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/common/content_paths.h"
+#include "content/shell/shell.h"
+#include "content/test/content_browser_test.h"
+#include "content/test/content_browser_test_utils.h"
+#include "net/base/net_util.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+
+namespace content {
+
+class RenderWidgetHostBrowserTest : public ContentBrowserTest {
+ public:
+  RenderWidgetHostBrowserTest() {}
+
+  virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
+    ASSERT_TRUE(PathService::Get(DIR_TEST_DATA, &test_dir_));
+  }
+
+  void GetSnapshotFromRendererCallback(const base::Closure& quit_closure,
+                                       bool* snapshot_valid,
+                                       bool success,
+                                       const SkBitmap& bitmap) {
+    quit_closure.Run();
+    EXPECT_EQ(success, true);
+
+    const int row_bytes = bitmap.rowBytesAsPixels();
+    SkColor* pixels = reinterpret_cast<SkColor*>(bitmap.getPixels());
+    for (int i = 0; i < bitmap.width(); ++i) {
+      for (int j = 0; j < bitmap.height(); ++j) {
+        if (pixels[j * row_bytes + i] != SK_ColorRED) {
+          return;
+        }
+      }
+    }
+    *snapshot_valid = true;
+  }
+
+ protected:
+  base::FilePath test_dir_;
+};
+
+IN_PROC_BROWSER_TEST_F(RenderWidgetHostBrowserTest,
+                       GetSnapshotFromRendererTest) {
+  base::RunLoop run_loop;
+
+  NavigateToURL(shell(), GURL(net::FilePathToFileURL(
+      test_dir_.AppendASCII("rwh_simple.html"))));
+
+  bool snapshot_valid = false;
+  RenderViewHost* const rwh = shell()->web_contents()->GetRenderViewHost();
+  rwh->GetSnapshotFromRenderer(gfx::Rect(), base::Bind(
+      &RenderWidgetHostBrowserTest::GetSnapshotFromRendererCallback,
+      base::Unretained(this),
+      run_loop.QuitClosure(),
+      &snapshot_valid));
+  run_loop.Run();
+
+  EXPECT_EQ(snapshot_valid, true);
+}
+
+}  // namespace content
diff --git a/content/browser/renderer_host/render_widget_host_delegate.cc b/content/browser/renderer_host/render_widget_host_delegate.cc
index 54465b9..73f5325 100644
--- a/content/browser/renderer_host/render_widget_host_delegate.cc
+++ b/content/browser/renderer_host/render_widget_host_delegate.cc
@@ -17,4 +17,11 @@
   return false;
 }
 
+#if defined(OS_WIN) && defined(USE_AURA)
+gfx::NativeViewAccessible
+RenderWidgetHostDelegate::GetParentNativeViewAccessible() {
+  return NULL;
+}
+#endif
+
 }  // namespace content
diff --git a/content/browser/renderer_host/render_widget_host_delegate.h b/content/browser/renderer_host/render_widget_host_delegate.h
index e283756..fa41727 100644
--- a/content/browser/renderer_host/render_widget_host_delegate.h
+++ b/content/browser/renderer_host/render_widget_host_delegate.h
@@ -5,7 +5,9 @@
 #ifndef CONTENT_BROWSER_RENDER_WIDGET_HOST_DELEGATE_H_
 #define CONTENT_BROWSER_RENDER_WIDGET_HOST_DELEGATE_H_
 
+#include "build/build_config.h"
 #include "content/common/content_export.h"
+#include "ui/gfx/native_widget_types.h"
 
 namespace WebKit {
 class WebMouseWheelEvent;
@@ -44,6 +46,11 @@
   // Returns true if the |event| was handled.
   virtual bool PreHandleWheelEvent(const WebKit::WebMouseWheelEvent& event);
 
+#if defined(OS_WIN) && defined(USE_AURA)
+  // Returns the widget's parent's NativeViewAccessible.
+  virtual gfx::NativeViewAccessible GetParentNativeViewAccessible();
+#endif
+
  protected:
   virtual ~RenderWidgetHostDelegate() {}
 };
diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc
index 4b02fda..d0a2d5c 100644
--- a/content/browser/renderer_host/render_widget_host_impl.cc
+++ b/content/browser/renderer_host/render_widget_host_impl.cc
@@ -37,9 +37,9 @@
 #include "content/common/accessibility_messages.h"
 #include "content/common/content_constants_internal.h"
 #include "content/common/gpu/gpu_messages.h"
+#include "content/common/input_messages.h"
 #include "content/common/view_messages.h"
 #include "content/port/browser/render_widget_host_view_port.h"
-#include "content/port/browser/smooth_scroll_gesture.h"
 #include "content/public/browser/compositor_util.h"
 #include "content/public/browser/native_web_keyboard_event.h"
 #include "content/public/browser/notification_service.h"
@@ -90,9 +90,6 @@
 // This timeout impacts the "choppiness" of our window resize perf.
 const int kPaintMsgTimeoutMS = 50;
 
-// How many milliseconds apart synthetic scroll messages should be sent.
-static const int kSyntheticScrollMessageIntervalMs = 8;
-
 // Returns |true| if the two wheel events should be coalesced.
 bool ShouldCoalesceMouseWheelEvents(const WebMouseWheelEvent& last_event,
                                     const WebMouseWheelEvent& new_event) {
@@ -168,8 +165,7 @@
       pending_mouse_lock_request_(false),
       allow_privileged_mouse_lock_(false),
       has_touch_handler_(false),
-      ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)),
-      tick_active_smooth_scroll_gestures_task_posted_(false),
+      weak_factory_(this),
       touch_event_queue_(new TouchEventQueue(this)),
       gesture_event_filter_(new GestureEventFilter(this)) {
   CHECK(delegate_);
@@ -200,11 +196,11 @@
   process_->WidgetRestored();
 
   accessibility_mode_ =
-      BrowserAccessibilityStateImpl::GetInstance()->GetAccessibilityMode();
+      BrowserAccessibilityStateImpl::GetInstance()->accessibility_mode();
 
 #if defined(USE_AURA)
-  bool overscroll_enabled = !CommandLine::ForCurrentProcess()->
-      HasSwitch(switches::kDisableOverscrollHistoryNavigation);
+  bool overscroll_enabled = CommandLine::ForCurrentProcess()->
+      GetSwitchValueASCII(switches::kOverscrollHistoryNavigation) != "0";
   SetOverscrollControllerEnabled(overscroll_enabled);
 #endif
 }
@@ -274,6 +270,10 @@
 
 void RenderWidgetHostImpl::ResetSizeAndRepaintPendingFlags() {
   resize_ack_pending_ = false;
+  if (repaint_ack_pending_) {
+    TRACE_EVENT_ASYNC_END0(
+        "renderer_host", "RenderWidgetHostImpl::repaint_ack_pending_", this);
+  }
   repaint_ack_pending_ = false;
   in_flight_size_.SetSize(0, 0);
 }
@@ -298,14 +298,15 @@
   waiting_for_screen_rects_ack_ = true;
 }
 
-int RenderWidgetHostImpl::SyntheticScrollMessageInterval() const {
-  return kSyntheticScrollMessageIntervalMs;
+base::TimeDelta
+    RenderWidgetHostImpl::GetSyntheticScrollMessageInterval() const {
+  return smooth_scroll_gesture_controller_.GetSyntheticScrollMessageInterval();
 }
 
 void RenderWidgetHostImpl::SetOverscrollControllerEnabled(bool enabled) {
   if (!enabled)
     overscroll_controller_.reset();
-  else if (!overscroll_controller_.get())
+  else if (!overscroll_controller_)
     overscroll_controller_.reset(new OverscrollController(this));
 }
 
@@ -366,7 +367,7 @@
                                 msg_is_ok = OnSwapCompositorFrame(msg))
     IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateRect, OnUpdateRect)
     IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateIsDelayed, OnUpdateIsDelayed)
-    IPC_MESSAGE_HANDLER(ViewHostMsg_HandleInputEvent_ACK, OnInputEventAck)
+    IPC_MESSAGE_HANDLER(InputHostMsg_HandleInputEvent_ACK, OnInputEventAck)
     IPC_MESSAGE_HANDLER(ViewHostMsg_BeginSmoothScroll, OnBeginSmoothScroll)
     IPC_MESSAGE_HANDLER(ViewHostMsg_SelectRange_ACK, OnSelectRangeAck)
     IPC_MESSAGE_HANDLER(ViewHostMsg_MoveCaret_ACK, OnMsgMoveCaretAck)
@@ -533,7 +534,7 @@
 }
 
 void RenderWidgetHostImpl::Focus() {
-  Send(new ViewMsg_SetFocus(routing_id_, true));
+  Send(new InputMsg_SetFocus(routing_id_, true));
 }
 
 void RenderWidgetHostImpl::Blur() {
@@ -543,11 +544,11 @@
   if (IsMouseLocked())
     view_->UnlockMouse();
 
-  Send(new ViewMsg_SetFocus(routing_id_, false));
+  Send(new InputMsg_SetFocus(routing_id_, false));
 }
 
 void RenderWidgetHostImpl::LostCapture() {
-  Send(new ViewMsg_MouseCaptureLost(routing_id_));
+  Send(new InputMsg_MouseCaptureLost(routing_id_));
 }
 
 void RenderWidgetHostImpl::SetActive(bool active) {
@@ -699,6 +700,8 @@
   if (!repaint_ack_pending_ && !resize_ack_pending_ && !view_being_painted_) {
     repaint_start_time_ = TimeTicks::Now();
     repaint_ack_pending_ = true;
+    TRACE_EVENT_ASYNC_BEGIN0(
+        "renderer_host", "RenderWidgetHostImpl::repaint_ack_pending_", this);
     Send(new ViewMsg_Repaint(routing_id_, view_size));
   }
 
@@ -760,7 +763,8 @@
 }
 
 void RenderWidgetHostImpl::ScheduleComposite() {
-  if (is_hidden_ || !is_accelerated_compositing_active_) {
+  if (is_hidden_ || !is_accelerated_compositing_active_ ||
+      current_size_.IsEmpty()) {
       return;
   }
 
@@ -768,6 +772,8 @@
   if (!repaint_ack_pending_ && !resize_ack_pending_ && !view_being_painted_) {
     repaint_start_time_ = TimeTicks::Now();
     repaint_ack_pending_ = true;
+    TRACE_EVENT_ASYNC_BEGIN0(
+        "renderer_host", "RenderWidgetHostImpl::repaint_ack_pending_", this);
     Send(new ViewMsg_Repaint(routing_id_, current_size_));
   }
 }
@@ -1028,7 +1034,7 @@
   // more WM_MOUSEMOVE events than we wish to send to the renderer.
   if (mouse_event.type == WebInputEvent::MouseMove) {
     if (mouse_move_pending_) {
-      if (!next_mouse_move_.get()) {
+      if (!next_mouse_move_) {
         next_mouse_move_.reset(new WebMouseEvent(mouse_event));
       } else {
         // Accumulate movement deltas.
@@ -1137,11 +1143,15 @@
   }
 }
 
+void RenderWidgetHostImpl::SendCursorVisibilityState(bool is_visible) {
+  Send(new InputMsg_CursorVisibilityChange(GetRoutingID(), is_visible));
+}
+
 void RenderWidgetHostImpl::SendInputEvent(const WebInputEvent& input_event,
                                           int event_size,
                                           bool is_keyboard_shortcut) {
   input_event_start_time_ = TimeTicks::Now();
-  Send(new ViewMsg_HandleInputEvent(
+  Send(new InputMsg_HandleInputEvent(
       routing_id_, &input_event, is_keyboard_shortcut));
   increment_in_flight_event_count();
 }
@@ -1232,15 +1242,14 @@
 }
 
 void RenderWidgetHostImpl::AddKeyboardListener(KeyboardListener* listener) {
-  keyboard_listeners_.push_back(listener);
+  keyboard_listeners_.AddObserver(listener);
 }
 
 void RenderWidgetHostImpl::RemoveKeyboardListener(
     KeyboardListener* listener) {
-  // Ensure that the element is actually in the list.
-  DCHECK(std::find(keyboard_listeners_.begin(), keyboard_listeners_.end(),
-                   listener) != keyboard_listeners_.end());
-  keyboard_listeners_.remove(listener);
+  // Ensure that the element is actually an observer.
+  DCHECK(keyboard_listeners_.HasObserver(listener));
+  keyboard_listeners_.RemoveObserver(listener);
 }
 
 void RenderWidgetHostImpl::GetWebScreenInfo(WebKit::WebScreenInfo* result) {
@@ -1250,6 +1259,13 @@
     RenderWidgetHostViewPort::GetDefaultScreenInfo(result);
 }
 
+const NativeWebKeyboardEvent*
+    RenderWidgetHostImpl::GetLastKeyboardEvent() const {
+  if (key_queue_.empty())
+    return NULL;
+  return &key_queue_.front();
+}
+
 void RenderWidgetHostImpl::NotifyScreenInfoChanged() {
   WebKit::WebScreenInfo screen_info;
   GetWebScreenInfo(&screen_info);
@@ -1322,7 +1338,7 @@
   // Must reset these to ensure that gesture events work with a new renderer.
   gesture_event_filter_->Reset();
 
-  if (overscroll_controller_.get())
+  if (overscroll_controller_)
     overscroll_controller_->Reset();
 
   // Must reset these to ensure that keyboard events work with a new renderer.
@@ -1598,18 +1614,6 @@
   param.a.AssignTo(frame.get());
 
   if (view_) {
-#if defined(OS_ANDROID)
-    view_->UpdateFrameInfo(
-        frame->metadata.root_scroll_offset,
-        frame->metadata.page_scale_factor,
-        gfx::Vector2dF(
-            frame->metadata.min_page_scale_factor,
-            frame->metadata.max_page_scale_factor),
-        frame->metadata.root_layer_size,
-        frame->metadata.viewport_size,
-        frame->metadata.location_bar_offset,
-        frame->metadata.location_bar_content_translation);
-#endif
     view_->OnSwapCompositorFrame(frame.Pass());
   } else {
     cc::CompositorFrameAck ack;
@@ -1618,6 +1622,8 @@
       ack.gl_frame_data->sync_point = 0;
     } else if (frame->delegated_frame_data) {
       ack.resources.swap(frame->delegated_frame_data->resource_list);
+    } else if (frame->software_frame_data) {
+      ack.last_dib_id = frame->software_frame_data->dib_id;
     }
     SendSwapCompositorFrameAck(routing_id_, process_->GetID(), ack);
   }
@@ -1648,6 +1654,9 @@
   bool is_repaint_ack =
       ViewHostMsg_UpdateRect_Flags::is_repaint_ack(params.flags);
   if (is_repaint_ack) {
+    DCHECK(repaint_ack_pending_);
+    TRACE_EVENT_ASYNC_END0(
+        "renderer_host", "RenderWidgetHostImpl::repaint_ack_pending_", this);
     repaint_ack_pending_ = false;
     TimeDelta delta = TimeTicks::Now() - repaint_start_time_;
     UMA_HISTOGRAM_TIMES("MPArch.RWH_RepaintDelta", delta);
@@ -1673,9 +1682,11 @@
       GetProcess()->ReceivedBadMessage();
     } else {
       UNSHIPPED_TRACE_EVENT_INSTANT2("test_latency", "UpdateRect",
+          TRACE_EVENT_SCOPE_THREAD,
           "x+y", params.bitmap_rect.x() + params.bitmap_rect.y(),
           "color", 0xffffff & *static_cast<uint32*>(dib->memory()));
       UNSHIPPED_TRACE_EVENT_INSTANT1("test_latency", "UpdateRectWidth",
+          TRACE_EVENT_SCOPE_THREAD,
           "width", params.bitmap_rect.width());
 
       // Scroll the backing store.
@@ -1707,7 +1718,7 @@
     bool post_callback = new_auto_size_.IsEmpty();
     new_auto_size_ = params.view_size;
     if (post_callback) {
-      MessageLoop::current()->PostTask(
+      base::MessageLoop::current()->PostTask(
           FROM_HERE,
           base::Bind(&RenderWidgetHostImpl::DelayedAutoResized,
                      weak_factory_.GetWeakPtr()));
@@ -1788,6 +1799,7 @@
   delta = now - paint_start;
   UMA_HISTOGRAM_TIMES("MPArch.RWH_TotalPaintTime", delta);
   UNSHIPPED_TRACE_EVENT_INSTANT1("test_latency", "UpdateRectComplete",
+      TRACE_EVENT_SCOPE_THREAD,
       "x+y", params.bitmap_rect.x() + params.bitmap_rect.y());
 }
 
@@ -1808,12 +1820,6 @@
   if (decrement_in_flight_event_count() == 0)
     StopHangMonitorTimeout();
 
-  // If an input ack is pending, then hold off ticking the gesture
-  // until we get an input ack.
-  if (in_process_event_types_.empty() &&
-      !active_smooth_scroll_gestures_.empty())
-    TickActiveSmoothScrollGesture();
-
   int type = static_cast<int>(event_type);
   if (type < WebInputEvent::Undefined) {
     RecordAction(UserMetricsAction("BadMessageTerminate_RWH2"));
@@ -1822,7 +1828,7 @@
     mouse_move_pending_ = false;
 
     // now, we can send the next mouse move event
-    if (next_mouse_move_.get()) {
+    if (next_mouse_move_) {
       DCHECK(next_mouse_move_->type == WebInputEvent::MouseMove);
       ForwardMouseEvent(*next_mouse_move_);
     }
@@ -1852,94 +1858,15 @@
 }
 
 void RenderWidgetHostImpl::OnBeginSmoothScroll(
-    int gesture_id, const ViewHostMsg_BeginSmoothScroll_Params &params) {
+    const ViewHostMsg_BeginSmoothScroll_Params& params) {
   if (!view_)
     return;
-  active_smooth_scroll_gestures_.insert(
-      std::make_pair(gesture_id,
-                     view_->CreateSmoothScrollGesture(
-                         params.scroll_down, params.pixels_to_scroll,
-                         params.mouse_event_x, params.mouse_event_y)));
-
-  // If an input ack is pending, then hold off ticking the gesture
-  // until we get an input ack.
-  if (!in_process_event_types_.empty())
-    return;
-  if (tick_active_smooth_scroll_gestures_task_posted_)
-    return;
-  TickActiveSmoothScrollGesture();
-}
-
-void RenderWidgetHostImpl::TickActiveSmoothScrollGesture() {
-  TRACE_EVENT0("input", "RenderWidgetHostImpl::TickActiveSmoothScrollGesture");
-  tick_active_smooth_scroll_gestures_task_posted_ = false;
-  if (active_smooth_scroll_gestures_.empty()) {
-    TRACE_EVENT_INSTANT0("input", "EarlyOut_NoActiveScrollGesture");
-    return;
-  }
-
-  base::TimeTicks now = TimeTicks::HighResNow();
-  base::TimeDelta preferred_interval =
-      base::TimeDelta::FromMilliseconds(kSyntheticScrollMessageIntervalMs);
-  base::TimeDelta time_until_next_ideal_interval =
-      (last_smooth_scroll_gestures_tick_time_ + preferred_interval) -
-      now;
-  if (time_until_next_ideal_interval.InMilliseconds() > 0) {
-    TRACE_EVENT_INSTANT1(
-        "input", "EarlyOut_TickedTooRecently",
-        "delay", time_until_next_ideal_interval.InMilliseconds());
-    // Post a task.
-    tick_active_smooth_scroll_gestures_task_posted_ = true;
-    MessageLoop::current()->PostDelayedTask(
-        FROM_HERE,
-        base::Bind(&RenderWidgetHostImpl::TickActiveSmoothScrollGesture,
-                   weak_factory_.GetWeakPtr()),
-        time_until_next_ideal_interval);
-    return;
-  }
-
-  last_smooth_scroll_gestures_tick_time_ = now;
-
-  // Separate ticking of gestures from sending their completion messages.
-  std::vector<int> ids_that_are_done;
-  for (SmoothScrollGestureMap::iterator it =
-           active_smooth_scroll_gestures_.begin();
-       it != active_smooth_scroll_gestures_.end();
-       ++it) {
-
-    bool active = it->second->ForwardInputEvents(now, this);
-    if (!active)
-      ids_that_are_done.push_back(it->first);
-  }
-
-  // Delete completed gestures and send their completion event.
-  for(size_t i = 0; i < ids_that_are_done.size(); i++) {
-    int id = ids_that_are_done[i];
-    SmoothScrollGestureMap::iterator it =
-        active_smooth_scroll_gestures_.find(id);
-    DCHECK(it != active_smooth_scroll_gestures_.end());
-    active_smooth_scroll_gestures_.erase(it);
-
-    Send(new ViewMsg_SmoothScrollCompleted(routing_id_, id));
-  }
-
-  // No need to post the next tick if an input is in flight.
-  if (!in_process_event_types_.empty())
-    return;
-
-  TRACE_EVENT_INSTANT1("input", "PostTickTask",
-                       "delay", preferred_interval.InMilliseconds());
-  tick_active_smooth_scroll_gestures_task_posted_ = true;
-  MessageLoop::current()->PostDelayedTask(
-      FROM_HERE,
-      base::Bind(&RenderWidgetHostImpl::TickActiveSmoothScrollGesture,
-                 weak_factory_.GetWeakPtr()),
-      preferred_interval);
+  smooth_scroll_gesture_controller_.BeginSmoothScroll(view_, params);
 }
 
 void RenderWidgetHostImpl::OnSelectRangeAck() {
   select_range_pending_ = false;
-  if (next_selection_range_.get()) {
+  if (next_selection_range_) {
     scoped_ptr<SelectionRange> next(next_selection_range_.Pass());
     SelectRange(next->start, next->end);
   }
@@ -1947,7 +1874,7 @@
 
 void RenderWidgetHostImpl::OnMsgMoveCaretAck() {
   move_caret_pending_ = false;
-  if (next_move_caret_.get()) {
+  if (next_move_caret_) {
     scoped_ptr<gfx::Point> next(next_move_caret_.Pass());
     MoveCaret(*next);
   }
@@ -1956,7 +1883,7 @@
 void RenderWidgetHostImpl::ProcessWheelAck(bool processed) {
   mouse_wheel_pending_ = false;
 
-  if (overscroll_controller_.get())
+  if (overscroll_controller_)
     overscroll_controller_->ReceivedEventACK(current_wheel_event_, processed);
 
   // Now send the next (coalesced) mouse wheel event.
@@ -1972,11 +1899,14 @@
 }
 
 void RenderWidgetHostImpl::ProcessGestureAck(bool processed, int type) {
-  if (overscroll_controller_.get()) {
+  if (overscroll_controller_) {
     overscroll_controller_->ReceivedEventACK(
         gesture_event_filter_->GetGestureEventAwaitingAck(), processed);
   }
   gesture_event_filter_->ProcessGestureAck(processed, type);
+
+  if (view_)
+    view_->GestureEventAck(type);
 }
 
 void RenderWidgetHostImpl::ProcessTouchAck(InputEventAckState ack_result) {
@@ -2152,7 +2082,10 @@
                                            &scheduled_completion_callback);
   if (needs_full_paint) {
     repaint_start_time_ = TimeTicks::Now();
+    DCHECK(!repaint_ack_pending_);
     repaint_ack_pending_ = true;
+    TRACE_EVENT_ASYNC_BEGIN0(
+        "renderer_host", "RenderWidgetHostImpl::repaint_ack_pending_", this);
     Send(new ViewMsg_Repaint(routing_id_, view_size));
   }
 
@@ -2180,17 +2113,11 @@
 }
 
 void RenderWidgetHostImpl::Replace(const string16& word) {
-  Send(new ViewMsg_Replace(routing_id_, word));
+  Send(new InputMsg_Replace(routing_id_, word));
 }
 
 void RenderWidgetHostImpl::ReplaceMisspelling(const string16& word) {
-#if defined(OS_MACOSX)
-  // TODO(rouslan): Use ViewMsg_ReplaceMisspelling on Mac after Mac implements
-  // asynchronous spell checking and enables unified text checking.
-  Send(new ViewMsg_Replace(routing_id_, word));
-#else
-  Send(new ViewMsg_ReplaceMisspelling(routing_id_, word));
-#endif
+  Send(new InputMsg_ReplaceMisspelling(routing_id_, word));
 }
 
 void RenderWidgetHostImpl::SetIgnoreInputEvents(bool ignore_input_events) {
@@ -2202,9 +2129,10 @@
   if (event.skip_in_browser || event.type != WebKeyboardEvent::RawKeyDown)
     return false;
 
-  for (std::list<KeyboardListener*>::iterator it = keyboard_listeners_.begin();
-       it != keyboard_listeners_.end(); ++it) {
-    if ((*it)->HandleKeyPressEvent(event))
+  ObserverList<KeyboardListener>::Iterator it(keyboard_listeners_);
+  KeyboardListener* listener;
+  while ((listener = it.GetNext()) != NULL) {
+    if (listener->HandleKeyPressEvent(event))
       return true;
   }
 
@@ -2272,7 +2200,7 @@
 
 void RenderWidgetHostImpl::SetEditCommandsForNextKeyEvent(
     const std::vector<EditCommand>& commands) {
-  Send(new ViewMsg_SetEditCommandsForNextKeyEvent(GetRoutingID(), commands));
+  Send(new InputMsg_SetEditCommandsForNextKeyEvent(GetRoutingID(), commands));
 }
 
 void RenderWidgetHostImpl::SetAccessibilityMode(AccessibilityMode mode) {
@@ -2310,20 +2238,27 @@
   Send(new AccessibilityMsg_FatalError(GetRoutingID()));
 }
 
+#if defined(OS_WIN) && defined(USE_AURA)
+gfx::NativeViewAccessible
+RenderWidgetHostImpl::GetParentNativeViewAccessible() const {
+  return delegate_->GetParentNativeViewAccessible();
+}
+#endif
+
 void RenderWidgetHostImpl::ExecuteEditCommand(const std::string& command,
                                               const std::string& value) {
-  Send(new ViewMsg_ExecuteEditCommand(GetRoutingID(), command, value));
+  Send(new InputMsg_ExecuteEditCommand(GetRoutingID(), command, value));
 }
 
 void RenderWidgetHostImpl::ScrollFocusedEditableNodeIntoRect(
     const gfx::Rect& rect) {
-  Send(new ViewMsg_ScrollFocusedEditableNodeIntoRect(GetRoutingID(), rect));
+  Send(new InputMsg_ScrollFocusedEditableNodeIntoRect(GetRoutingID(), rect));
 }
 
 void RenderWidgetHostImpl::SelectRange(const gfx::Point& start,
                                        const gfx::Point& end) {
   if (select_range_pending_) {
-    if (!next_selection_range_.get()) {
+    if (!next_selection_range_) {
       next_selection_range_.reset(new SelectionRange());
     }
     next_selection_range_->start = start;
@@ -2332,7 +2267,7 @@
   }
 
   select_range_pending_ = true;
-  Send(new ViewMsg_SelectRange(GetRoutingID(), start, end));
+  Send(new InputMsg_SelectRange(GetRoutingID(), start, end));
 }
 
 void RenderWidgetHostImpl::MoveCaret(const gfx::Point& point) {
@@ -2342,54 +2277,54 @@
   }
 
   move_caret_pending_ = true;
-  Send(new ViewMsg_MoveCaret(GetRoutingID(), point));
+  Send(new InputMsg_MoveCaret(GetRoutingID(), point));
 }
 
 void RenderWidgetHostImpl::Undo() {
-  Send(new ViewMsg_Undo(GetRoutingID()));
+  Send(new InputMsg_Undo(GetRoutingID()));
   RecordAction(UserMetricsAction("Undo"));
 }
 
 void RenderWidgetHostImpl::Redo() {
-  Send(new ViewMsg_Redo(GetRoutingID()));
+  Send(new InputMsg_Redo(GetRoutingID()));
   RecordAction(UserMetricsAction("Redo"));
 }
 
 void RenderWidgetHostImpl::Cut() {
-  Send(new ViewMsg_Cut(GetRoutingID()));
+  Send(new InputMsg_Cut(GetRoutingID()));
   RecordAction(UserMetricsAction("Cut"));
 }
 
 void RenderWidgetHostImpl::Copy() {
-  Send(new ViewMsg_Copy(GetRoutingID()));
+  Send(new InputMsg_Copy(GetRoutingID()));
   RecordAction(UserMetricsAction("Copy"));
 }
 
 void RenderWidgetHostImpl::CopyToFindPboard() {
 #if defined(OS_MACOSX)
   // Windows/Linux don't have the concept of a find pasteboard.
-  Send(new ViewMsg_CopyToFindPboard(GetRoutingID()));
+  Send(new InputMsg_CopyToFindPboard(GetRoutingID()));
   RecordAction(UserMetricsAction("CopyToFindPboard"));
 #endif
 }
 
 void RenderWidgetHostImpl::Paste() {
-  Send(new ViewMsg_Paste(GetRoutingID()));
+  Send(new InputMsg_Paste(GetRoutingID()));
   RecordAction(UserMetricsAction("Paste"));
 }
 
 void RenderWidgetHostImpl::PasteAndMatchStyle() {
-  Send(new ViewMsg_PasteAndMatchStyle(GetRoutingID()));
+  Send(new InputMsg_PasteAndMatchStyle(GetRoutingID()));
   RecordAction(UserMetricsAction("PasteAndMatchStyle"));
 }
 
 void RenderWidgetHostImpl::Delete() {
-  Send(new ViewMsg_Delete(GetRoutingID()));
+  Send(new InputMsg_Delete(GetRoutingID()));
   RecordAction(UserMetricsAction("DeleteSelection"));
 }
 
 void RenderWidgetHostImpl::SelectAll() {
-  Send(new ViewMsg_SelectAll(GetRoutingID()));
+  Send(new InputMsg_SelectAll(GetRoutingID()));
   RecordAction(UserMetricsAction("SelectAll"));
 }
 bool RenderWidgetHostImpl::GotResponseToLockMouseRequest(bool allowed) {
diff --git a/content/browser/renderer_host/render_widget_host_impl.h b/content/browser/renderer_host/render_widget_host_impl.h
index e81bc5d..487a9e9 100644
--- a/content/browser/renderer_host/render_widget_host_impl.h
+++ b/content/browser/renderer_host/render_widget_host_impl.h
@@ -17,11 +17,13 @@
 #include "base/gtest_prod_util.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/weak_ptr.h"
+#include "base/observer_list.h"
 #include "base/process_util.h"
 #include "base/string16.h"
 #include "base/time.h"
 #include "base/timer.h"
 #include "build/build_config.h"
+#include "content/browser/renderer_host/smooth_scroll_gesture_controller.h"
 #include "content/common/view_message_enums.h"
 #include "content/port/common/input_event_ack_state.h"
 #include "content/public/browser/render_widget_host.h"
@@ -70,7 +72,7 @@
 class OverscrollController;
 class RenderWidgetHostDelegate;
 class RenderWidgetHostViewPort;
-class SmoothScrollGesture;
+class SmoothScrollGestureController;
 class TouchEventQueue;
 struct EditCommand;
 
@@ -155,6 +157,8 @@
       const gfx::Rect& src_subrect,
       const base::Callback<void(bool, const SkBitmap&)>& callback) OVERRIDE;
 
+  const NativeWebKeyboardEvent* GetLastKeyboardEvent() const;
+
   // Notification that the screen info has changed.
   void NotifyScreenInfoChanged();
 
@@ -195,6 +199,9 @@
   // Called to notify the RenderWidget that it has lost the mouse lock.
   virtual void LostMouseLock();
 
+  // Noifies the RenderWidget of the current mouse cursor visibility state.
+  void SendCursorVisibilityState(bool is_visible);
+
   // Tells us whether the page is rendered directly via the GPU process.
   bool is_accelerated_compositing_active() {
     return is_accelerated_compositing_active_;
@@ -371,6 +378,10 @@
   // Kill the renderer because we got a fatal accessibility error.
   void FatalAccessibilityTreeError();
 
+#if defined(OS_WIN) && defined(USE_AURA)
+  gfx::NativeViewAccessible GetParentNativeViewAccessible() const;
+#endif
+
   // Executes the edit command on the RenderView.
   void ExecuteEditCommand(const std::string& command,
                           const std::string& value);
@@ -449,7 +460,7 @@
     return overscroll_controller_.get();
   }
 
-  int SyntheticScrollMessageInterval() const;
+  base::TimeDelta GetSyntheticScrollMessageInterval() const;
 
   // Sets whether the overscroll controller should be enabled for this page.
   void SetOverscrollControllerEnabled(bool enabled);
@@ -582,8 +593,7 @@
   void OnInputEventAck(WebKit::WebInputEvent::Type event_type,
                        InputEventAckState ack_result);
   void OnBeginSmoothScroll(
-      int gesture_id,
-      const ViewHostMsg_BeginSmoothScroll_Params &params);
+      const ViewHostMsg_BeginSmoothScroll_Params& params);
   void OnSelectRangeAck();
   void OnMsgMoveCaretAck();
   virtual void OnFocus();
@@ -664,9 +674,6 @@
   // which may get in recursive loops).
   void DelayedAutoResized();
 
-  // Called periodically to advance the active scroll gesture after being
-  // initiated by OnBeginSmoothScroll.
-  void TickActiveSmoothScrollGesture();
 
   // Our delegate, which wants to know mainly about keyboard events.
   // It will remain non-NULL until DetachDelegate() is called.
@@ -733,7 +740,7 @@
   gfx::Rect last_window_screen_rect_;
 
   // True if a mouse move event was sent to the render view and we are waiting
-  // for a corresponding ViewHostMsg_HandleInputEvent_ACK message.
+  // for a corresponding InputHostMsg_HandleInputEvent_ACK message.
   bool mouse_move_pending_;
 
   // The next mouse move event to send (only non-null while mouse_move_pending_
@@ -777,7 +784,7 @@
   base::TimeTicks input_event_start_time_;
 
   // Keyboard event listeners.
-  std::list<KeyboardListener*> keyboard_listeners_;
+  ObserverList<KeyboardListener> keyboard_listeners_;
 
   // If true, then we should repaint when restoring even if we have a
   // backingstore.  This flag is set to true if we receive a paint message
@@ -860,12 +867,7 @@
 
   base::WeakPtrFactory<RenderWidgetHostImpl> weak_factory_;
 
-  typedef std::map<int, scoped_refptr<SmoothScrollGesture> >
-      SmoothScrollGestureMap;
-  SmoothScrollGestureMap active_smooth_scroll_gestures_;
-  base::TimeTicks last_smooth_scroll_gestures_tick_time_;
-  bool tick_active_smooth_scroll_gestures_task_posted_;
-
+  SmoothScrollGestureController smooth_scroll_gesture_controller_;
   scoped_ptr<TouchEventQueue> touch_event_queue_;
   scoped_ptr<GestureEventFilter> gesture_event_filter_;
   scoped_ptr<OverscrollController> overscroll_controller_;
diff --git a/content/browser/renderer_host/render_widget_host_unittest.cc b/content/browser/renderer_host/render_widget_host_unittest.cc
index 54e5472..84945b9 100644
--- a/content/browser/renderer_host/render_widget_host_unittest.cc
+++ b/content/browser/renderer_host/render_widget_host_unittest.cc
@@ -8,14 +8,15 @@
 #include "base/timer.h"
 #include "content/browser/browser_thread_impl.h"
 #include "content/browser/renderer_host/backing_store.h"
-#include "content/browser/renderer_host/render_widget_host_delegate.h"
 #include "content/browser/renderer_host/gesture_event_filter.h"
 #include "content/browser/renderer_host/overscroll_controller.h"
 #include "content/browser/renderer_host/overscroll_controller_delegate.h"
+#include "content/browser/renderer_host/render_widget_host_delegate.h"
 #include "content/browser/renderer_host/tap_suppression_controller.h"
 #include "content/browser/renderer_host/tap_suppression_controller_client.h"
 #include "content/browser/renderer_host/test_render_view_host.h"
 #include "content/browser/renderer_host/touch_event_queue.h"
+#include "content/common/input_messages.h"
 #include "content/common/view_messages.h"
 #include "content/port/browser/render_widget_host_view_port.h"
 #include "content/public/browser/notification_details.h"
@@ -657,13 +658,13 @@
 #endif
 
     // Process all pending tasks to avoid leaks.
-    MessageLoop::current()->RunUntilIdle();
+    base::MessageLoop::current()->RunUntilIdle();
   }
 
   void SendInputEventACK(WebInputEvent::Type type,
                          InputEventAckState ack_result) {
     scoped_ptr<IPC::Message> response(
-        new ViewHostMsg_HandleInputEvent_ACK(0, type, ack_result));
+        new InputHostMsg_HandleInputEvent_ACK(0, type, ack_result));
     host_->OnMessageReceived(*response);
   }
 
@@ -821,7 +822,7 @@
     return reinterpret_cast<const WebInputEvent*>(data);
   }
 
-  MessageLoopForUI message_loop_;
+  base::MessageLoopForUI message_loop_;
 
   scoped_ptr<TestBrowserContext> browser_context_;
   RenderWidgetHostProcess* process_;  // Deleted automatically by the widget.
@@ -1096,7 +1097,7 @@
 // Test that we don't paint when we're hidden, but we still send the ACK. Most
 // of the rest of the painting is tested in the GetBackingStore* ones.
 TEST_F(RenderWidgetHostTest, HiddenPaint) {
-  BrowserThreadImpl ui_thread(BrowserThread::UI, MessageLoop::current());
+  BrowserThreadImpl ui_thread(BrowserThread::UI, base::MessageLoop::current());
   // Hide the widget, it should have sent out a message to the renderer.
   EXPECT_FALSE(host_->is_hidden_);
   host_->WasHidden();
@@ -1160,7 +1161,7 @@
 
   // Make sure we sent the input event to the renderer.
   EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
-                  ViewMsg_HandleInputEvent::ID));
+                  InputMsg_HandleInputEvent::ID));
   process_->sink().ClearMessages();
 
   // Send the simulated response from the renderer back.
@@ -1186,7 +1187,7 @@
 
   // Make sure we sent the input event to the renderer.
   EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
-                  ViewMsg_HandleInputEvent::ID));
+                  InputMsg_HandleInputEvent::ID));
   process_->sink().ClearMessages();
 
   // Send the simulated response from the renderer back.
@@ -1225,7 +1226,7 @@
 
   // Make sure only KeyUp was sent to the renderer.
   EXPECT_EQ(1U, process_->sink().message_count());
-  EXPECT_EQ(ViewMsg_HandleInputEvent::ID,
+  EXPECT_EQ(InputMsg_HandleInputEvent::ID,
             process_->sink().GetMessageAt(0)->type());
   process_->sink().ClearMessages();
 
@@ -1249,7 +1250,7 @@
   // Check that only the first event was sent.
   EXPECT_EQ(1U, process_->sink().message_count());
   EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
-                  ViewMsg_HandleInputEvent::ID));
+                  InputMsg_HandleInputEvent::ID));
   process_->sink().ClearMessages();
 
   // Check that the ACK sends the second message.
@@ -1258,25 +1259,25 @@
   // The coalesced events can queue up a delayed ack
   // so that additional input events can be processed before
   // we turn off coalescing.
-  MessageLoop::current()->RunUntilIdle();
+  base::MessageLoop::current()->RunUntilIdle();
   EXPECT_EQ(1U, process_->sink().message_count());
   EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
-                  ViewMsg_HandleInputEvent::ID));
+                  InputMsg_HandleInputEvent::ID));
   process_->sink().ClearMessages();
 
   // One more time.
   SendInputEventACK(WebInputEvent::MouseWheel,
                     INPUT_EVENT_ACK_STATE_CONSUMED);
-  MessageLoop::current()->RunUntilIdle();
+  base::MessageLoop::current()->RunUntilIdle();
   EXPECT_EQ(1U, process_->sink().message_count());
   EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
-                  ViewMsg_HandleInputEvent::ID));
+                  InputMsg_HandleInputEvent::ID));
   process_->sink().ClearMessages();
 
   // After the final ack, the queue should be empty.
   SendInputEventACK(WebInputEvent::MouseWheel,
                     INPUT_EVENT_ACK_STATE_CONSUMED);
-  MessageLoop::current()->RunUntilIdle();
+  base::MessageLoop::current()->RunUntilIdle();
   EXPECT_EQ(0U, process_->sink().message_count());
 
   SimulateGestureFlingStartEvent(0.f, 0.f, WebGestureEvent::Touchpad);
@@ -1292,7 +1293,7 @@
   EXPECT_EQ(1U, process_->sink().message_count());
   SendInputEventACK(WebInputEvent::GestureScrollBegin,
                     INPUT_EVENT_ACK_STATE_CONSUMED);
-  MessageLoop::current()->RunUntilIdle();
+  base::MessageLoop::current()->RunUntilIdle();
 
   // Send a wheel event, should get sent directly.
   SimulateWheelEvent(0, -5, 0, false);
@@ -1365,40 +1366,40 @@
   // Check that only the first event was sent.
   EXPECT_EQ(1U, process_->sink().message_count());
   EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
-              ViewMsg_HandleInputEvent::ID));
+              InputMsg_HandleInputEvent::ID));
   process_->sink().ClearMessages();
 
   // Check that the ACK sends the second message.
   SendInputEventACK(WebInputEvent::GestureScrollBegin,
                     INPUT_EVENT_ACK_STATE_CONSUMED);
-  MessageLoop::current()->RunUntilIdle();
+  base::MessageLoop::current()->RunUntilIdle();
   EXPECT_EQ(1U, process_->sink().message_count());
   EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
-              ViewMsg_HandleInputEvent::ID));
+              InputMsg_HandleInputEvent::ID));
   process_->sink().ClearMessages();
 
   // Ack for queued coalesced event.
   SendInputEventACK(WebInputEvent::GestureScrollUpdate,
                     INPUT_EVENT_ACK_STATE_CONSUMED);
-  MessageLoop::current()->RunUntilIdle();
+  base::MessageLoop::current()->RunUntilIdle();
   EXPECT_EQ(1U, process_->sink().message_count());
   EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
-              ViewMsg_HandleInputEvent::ID));
+              InputMsg_HandleInputEvent::ID));
   process_->sink().ClearMessages();
 
   // Ack for queued uncoalesced event.
   SendInputEventACK(WebInputEvent::GestureScrollUpdate,
                     INPUT_EVENT_ACK_STATE_CONSUMED);
-  MessageLoop::current()->RunUntilIdle();
+  base::MessageLoop::current()->RunUntilIdle();
   EXPECT_EQ(1U, process_->sink().message_count());
   EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
-              ViewMsg_HandleInputEvent::ID));
+              InputMsg_HandleInputEvent::ID));
   process_->sink().ClearMessages();
 
   // After the final ack, the queue should be empty.
   SendInputEventACK(WebInputEvent::GestureScrollEnd,
                     INPUT_EVENT_ACK_STATE_CONSUMED);
-  MessageLoop::current()->RunUntilIdle();
+  base::MessageLoop::current()->RunUntilIdle();
   EXPECT_EQ(0U, process_->sink().message_count());
 }
 
@@ -1487,16 +1488,16 @@
   // Check that only the first event was sent.
   EXPECT_EQ(1U, process_->sink().message_count());
   EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
-              ViewMsg_HandleInputEvent::ID));
+              InputMsg_HandleInputEvent::ID));
   process_->sink().ClearMessages();
 
   // Check that the ACK sends the second message.
   SendInputEventACK(WebInputEvent::GestureScrollBegin,
                     INPUT_EVENT_ACK_STATE_CONSUMED);
-  MessageLoop::current()->RunUntilIdle();
+  base::MessageLoop::current()->RunUntilIdle();
   EXPECT_EQ(1U, process_->sink().message_count());
   EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
-              ViewMsg_HandleInputEvent::ID));
+              InputMsg_HandleInputEvent::ID));
   process_->sink().ClearMessages();
 
   // Enqueued.
@@ -1520,12 +1521,12 @@
   // Check that the ACK sends both scroll and pinch updates.
   SendInputEventACK(WebInputEvent::GesturePinchBegin,
                     INPUT_EVENT_ACK_STATE_CONSUMED);
-  MessageLoop::current()->RunUntilIdle();
+  base::MessageLoop::current()->RunUntilIdle();
   EXPECT_EQ(2U, process_->sink().message_count());
   EXPECT_TRUE(process_->sink().GetFirstMessageMatching(
-              ViewMsg_HandleInputEvent::ID));
+              InputMsg_HandleInputEvent::ID));
   EXPECT_FALSE(process_->sink().GetUniqueMessageMatching(
-              ViewMsg_HandleInputEvent::ID));
+              InputMsg_HandleInputEvent::ID));
   process_->sink().ClearMessages();
 
   // The next ACK should be getting ignored.
@@ -1579,7 +1580,7 @@
   // Check that the ACK gets ignored.
   SendInputEventACK(WebInputEvent::GestureScrollUpdate,
                     INPUT_EVENT_ACK_STATE_CONSUMED);
-  MessageLoop::current()->RunUntilIdle();
+  base::MessageLoop::current()->RunUntilIdle();
   EXPECT_EQ(0U, process_->sink().message_count());
   // The flag should have been flipped back to false.
   EXPECT_FALSE(host_->WillIgnoreNextACK());
@@ -1602,33 +1603,33 @@
   // Check that the ACK sends the next scroll pinch pair.
   SendInputEventACK(WebInputEvent::GesturePinchUpdate,
                     INPUT_EVENT_ACK_STATE_CONSUMED);
-  MessageLoop::current()->RunUntilIdle();
+  base::MessageLoop::current()->RunUntilIdle();
   EXPECT_EQ(2U, process_->sink().message_count());
   EXPECT_TRUE(process_->sink().GetFirstMessageMatching(
-              ViewMsg_HandleInputEvent::ID));
+              InputMsg_HandleInputEvent::ID));
   EXPECT_FALSE(process_->sink().GetUniqueMessageMatching(
-              ViewMsg_HandleInputEvent::ID));
+              InputMsg_HandleInputEvent::ID));
   process_->sink().ClearMessages();
 
   // Check that the ACK sends the second message.
   SendInputEventACK(WebInputEvent::GestureScrollUpdate,
                     INPUT_EVENT_ACK_STATE_CONSUMED);
-  MessageLoop::current()->RunUntilIdle();
+  base::MessageLoop::current()->RunUntilIdle();
   EXPECT_EQ(0U, process_->sink().message_count());
 
   // Check that the ACK sends the second message.
   SendInputEventACK(WebInputEvent::GesturePinchUpdate,
                     INPUT_EVENT_ACK_STATE_CONSUMED);
-  MessageLoop::current()->RunUntilIdle();
+  base::MessageLoop::current()->RunUntilIdle();
   EXPECT_EQ(1U, process_->sink().message_count());
   EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
-              ViewMsg_HandleInputEvent::ID));
+              InputMsg_HandleInputEvent::ID));
   process_->sink().ClearMessages();
 
   // Check that the queue is empty after ACK and no messages get sent.
   SendInputEventACK(WebInputEvent::GestureScrollUpdate,
                     INPUT_EVENT_ACK_STATE_CONSUMED);
-  MessageLoop::current()->RunUntilIdle();
+  base::MessageLoop::current()->RunUntilIdle();
   EXPECT_EQ(0U, process_->sink().message_count());
   EXPECT_EQ(0U, host_->GestureEventLastQueueEventSize());
 }
@@ -1651,13 +1652,13 @@
   EXPECT_TRUE(host_->FlingInProgress());
   SendInputEventACK(WebInputEvent::GestureFlingStart,
                     INPUT_EVENT_ACK_STATE_CONSUMED);
-  MessageLoop::current()->RunUntilIdle();
+  base::MessageLoop::current()->RunUntilIdle();
   SimulateGestureEvent(WebInputEvent::GestureFlingCancel, source_device);
   EXPECT_FALSE(host_->FlingInProgress());
   EXPECT_EQ(2U, process_->sink().message_count());
   SendInputEventACK(WebInputEvent::GestureFlingCancel,
                     INPUT_EVENT_ACK_STATE_CONSUMED);
-  MessageLoop::current()->RunUntilIdle();
+  base::MessageLoop::current()->RunUntilIdle();
   EXPECT_EQ(0U, host_->GestureEventLastQueueEventSize());
 
   // GFC before previous GFS is acked.
@@ -1672,10 +1673,10 @@
   // Advance state realistically.
   SendInputEventACK(WebInputEvent::GestureFlingStart,
                     INPUT_EVENT_ACK_STATE_CONSUMED);
-  MessageLoop::current()->RunUntilIdle();
+  base::MessageLoop::current()->RunUntilIdle();
   SendInputEventACK(WebInputEvent::GestureFlingCancel,
                     INPUT_EVENT_ACK_STATE_CONSUMED);
-  MessageLoop::current()->RunUntilIdle();
+  base::MessageLoop::current()->RunUntilIdle();
   EXPECT_EQ(0U, host_->GestureEventLastQueueEventSize());
 
   // GFS is added to the queue if another event is pending
@@ -1742,9 +1743,11 @@
   EXPECT_EQ(0U, host_->GestureEventLastQueueEventSize());
 
   // Wait long enough for first timeout and see if it fired.
-  MessageLoop::current()->PostDelayedTask(
-      FROM_HERE, MessageLoop::QuitClosure(), TimeDelta::FromMilliseconds(10));
-  MessageLoop::current()->Run();
+  base::MessageLoop::current()->PostDelayedTask(
+      FROM_HERE,
+      base::MessageLoop::QuitClosure(),
+      TimeDelta::FromMilliseconds(10));
+  base::MessageLoop::current()->Run();
 
   EXPECT_EQ(1U, process_->sink().message_count());
   EXPECT_EQ(1U, host_->GestureEventLastQueueEventSize());
@@ -1771,9 +1774,11 @@
   EXPECT_EQ(WebInputEvent::GestureTap,
             host_->GestureEventLastQueueEvent().type);
 
-  MessageLoop::current()->PostDelayedTask(
-      FROM_HERE, MessageLoop::QuitClosure(), TimeDelta::FromMilliseconds(10));
-  MessageLoop::current()->Run();
+  base::MessageLoop::current()->PostDelayedTask(
+      FROM_HERE,
+      base::MessageLoop::QuitClosure(),
+      TimeDelta::FromMilliseconds(10));
+  base::MessageLoop::current()->Run();
 
   // If the deferral timer incorrectly fired, it sent an extra message.
   EXPECT_EQ(1U, process_->sink().message_count());
@@ -1793,9 +1798,11 @@
   EXPECT_EQ(0U, host_->GestureEventLastQueueEventSize());
 
   // Wait long enough for the timeout and verify it fired.
-  MessageLoop::current()->PostDelayedTask(
-      FROM_HERE, MessageLoop::QuitClosure(), TimeDelta::FromMilliseconds(10));
-  MessageLoop::current()->Run();
+  base::MessageLoop::current()->PostDelayedTask(
+      FROM_HERE,
+      base::MessageLoop::QuitClosure(),
+      TimeDelta::FromMilliseconds(10));
+  base::MessageLoop::current()->Run();
 
   EXPECT_EQ(1U, process_->sink().message_count());
   EXPECT_EQ(1U, host_->GestureEventLastQueueEventSize());
@@ -1830,9 +1837,11 @@
   EXPECT_EQ(WebInputEvent::GestureScrollBegin,
             host_->GestureEventLastQueueEvent().type);
 
-  MessageLoop::current()->PostDelayedTask(
-      FROM_HERE, MessageLoop::QuitClosure(), TimeDelta::FromMilliseconds(10));
-  MessageLoop::current()->Run();
+  base::MessageLoop::current()->PostDelayedTask(
+      FROM_HERE,
+      base::MessageLoop::QuitClosure(),
+      TimeDelta::FromMilliseconds(10));
+  base::MessageLoop::current()->Run();
 
   // If the deferral timer incorrectly fired, it will send an extra message.
   EXPECT_EQ(1U, process_->sink().message_count());
@@ -1856,9 +1865,11 @@
   EXPECT_EQ(0U, process_->sink().message_count());
   EXPECT_EQ(0U, host_->GestureEventLastQueueEventSize());
 
-  MessageLoop::current()->PostDelayedTask(
-      FROM_HERE, MessageLoop::QuitClosure(), TimeDelta::FromMilliseconds(10));
-  MessageLoop::current()->Run();
+  base::MessageLoop::current()->PostDelayedTask(
+      FROM_HERE,
+      base::MessageLoop::QuitClosure(),
+      TimeDelta::FromMilliseconds(10));
+  base::MessageLoop::current()->Run();
 
   // If the deferral timer incorrectly fired, it will send an extra message.
   EXPECT_EQ(0U, process_->sink().message_count());
@@ -1877,9 +1888,11 @@
   EXPECT_EQ(0U, process_->sink().message_count());
   EXPECT_EQ(0U, host_->GestureEventLastQueueEventSize());
 
-  MessageLoop::current()->PostDelayedTask(
-      FROM_HERE, MessageLoop::QuitClosure(), TimeDelta::FromMilliseconds(10));
-  MessageLoop::current()->Run();
+  base::MessageLoop::current()->PostDelayedTask(
+      FROM_HERE,
+      base::MessageLoop::QuitClosure(),
+      TimeDelta::FromMilliseconds(10));
+  base::MessageLoop::current()->Run();
 
   EXPECT_EQ(1U, process_->sink().message_count());
   EXPECT_EQ(1U, host_->GestureEventLastQueueEventSize());
@@ -1929,9 +1942,11 @@
   EXPECT_EQ(2U, host_->GestureEventLastQueueEventSize());
   EXPECT_EQ(3U, host_->GestureEventDebouncingQueueSize());
 
-  MessageLoop::current()->PostDelayedTask(
-      FROM_HERE, MessageLoop::QuitClosure(), TimeDelta::FromMilliseconds(5));
-  MessageLoop::current()->Run();
+  base::MessageLoop::current()->PostDelayedTask(
+      FROM_HERE,
+      base::MessageLoop::QuitClosure(),
+      TimeDelta::FromMilliseconds(5));
+  base::MessageLoop::current()->Run();
 
   // The deferred events are correctly queued in coalescing queue.
   EXPECT_EQ(1U, process_->sink().message_count());
@@ -2976,9 +2991,11 @@
   host_->StartHangMonitorTimeout(TimeDelta::FromSeconds(30));
 
   // Wait long enough for first timeout and see if it fired.
-  MessageLoop::current()->PostDelayedTask(
-      FROM_HERE, MessageLoop::QuitClosure(), TimeDelta::FromMilliseconds(10));
-  MessageLoop::current()->Run();
+  base::MessageLoop::current()->PostDelayedTask(
+      FROM_HERE,
+      base::MessageLoop::QuitClosure(),
+      TimeDelta::FromMilliseconds(10));
+  base::MessageLoop::current()->Run();
   EXPECT_TRUE(host_->unresponsive_timer_fired());
 }
 
@@ -2994,9 +3011,11 @@
   host_->StartHangMonitorTimeout(TimeDelta::FromMilliseconds(10));
 
   // Wait long enough for first timeout and see if it fired.
-  MessageLoop::current()->PostDelayedTask(
-      FROM_HERE, MessageLoop::QuitClosure(), TimeDelta::FromMilliseconds(40));
-  MessageLoop::current()->Run();
+  base::MessageLoop::current()->PostDelayedTask(
+      FROM_HERE,
+      base::MessageLoop::QuitClosure(),
+      TimeDelta::FromMilliseconds(40));
+  base::MessageLoop::current()->Run();
   EXPECT_TRUE(host_->unresponsive_timer_fired());
 }
 
@@ -3011,9 +3030,11 @@
   host_->StartHangMonitorTimeout(TimeDelta::FromMilliseconds(20));
 
   // Wait long enough for the second timeout and see if it fired.
-  MessageLoop::current()->PostDelayedTask(
-      FROM_HERE, MessageLoop::QuitClosure(), TimeDelta::FromMilliseconds(25));
-  MessageLoop::current()->Run();
+  base::MessageLoop::current()->PostDelayedTask(
+      FROM_HERE,
+      base::MessageLoop::QuitClosure(),
+      TimeDelta::FromMilliseconds(25));
+  base::MessageLoop::current()->Run();
   EXPECT_TRUE(host_->unresponsive_timer_fired());
 }
 
@@ -3032,9 +3053,11 @@
                     INPUT_EVENT_ACK_STATE_CONSUMED);
 
   // Wait long enough for first timeout and see if it fired.
-  MessageLoop::current()->PostDelayedTask(
-      FROM_HERE, MessageLoop::QuitClosure(), TimeDelta::FromMilliseconds(40));
-  MessageLoop::current()->Run();
+  base::MessageLoop::current()->PostDelayedTask(
+      FROM_HERE,
+      base::MessageLoop::QuitClosure(),
+      TimeDelta::FromMilliseconds(40));
+  base::MessageLoop::current()->Run();
   EXPECT_TRUE(host_->unresponsive_timer_fired());
 }
 
@@ -3492,9 +3515,11 @@
   // enough overscroll to complete the gesture, the overscroll controller
   // will reset the state. The scroll-end should therefore be dispatched to the
   // renderer, and the gesture-event-filter should await an ACK for it.
-  MessageLoop::current()->PostDelayedTask(
-      FROM_HERE, MessageLoop::QuitClosure(), TimeDelta::FromMilliseconds(15));
-  MessageLoop::current()->Run();
+  base::MessageLoop::current()->PostDelayedTask(
+      FROM_HERE,
+      base::MessageLoop::QuitClosure(),
+      TimeDelta::FromMilliseconds(15));
+  base::MessageLoop::current()->Run();
 
   EXPECT_EQ(OVERSCROLL_NONE, host_->overscroll_mode());
   EXPECT_EQ(OVERSCROLL_NONE, host_->overscroll_delegate()->current_mode());
@@ -3596,15 +3621,26 @@
   EXPECT_EQ(205.f, host_->overscroll_delegate()->delta_x());
   EXPECT_EQ(0.f, host_->overscroll_delegate()->delta_y());
 
+  // The touch-end/cancel event should always reach the renderer if the page has
+  // touch handlers.
   ReleaseTouchPoint(0);
   SendTouchEvent();
+  EXPECT_EQ(1U, process_->sink().message_count());
+  EXPECT_EQ(1U, host_->TouchEventQueueSize());
+  process_->sink().ClearMessages();
+
+  SendInputEventACK(WebInputEvent::TouchEnd,
+                    INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
   EXPECT_EQ(0U, process_->sink().message_count());
+  EXPECT_EQ(0U, host_->TouchEventQueueSize());
 
   SimulateGestureEvent(WebKit::WebInputEvent::GestureScrollEnd,
                        WebGestureEvent::Touchscreen);
-  MessageLoop::current()->PostDelayedTask(
-      FROM_HERE, MessageLoop::QuitClosure(), TimeDelta::FromMilliseconds(10));
-  MessageLoop::current()->Run();
+  base::MessageLoop::current()->PostDelayedTask(
+      FROM_HERE,
+      base::MessageLoop::QuitClosure(),
+      TimeDelta::FromMilliseconds(10));
+  base::MessageLoop::current()->Run();
   EXPECT_EQ(1U, process_->sink().message_count());
   EXPECT_EQ(0U, host_->TouchEventQueueSize());
   EXPECT_EQ(OVERSCROLL_NONE, host_->overscroll_mode());
@@ -3664,9 +3700,11 @@
   EXPECT_EQ(OVERSCROLL_NONE, host_->overscroll_delegate()->completed_mode());
   EXPECT_EQ(0U, host_->GestureEventLastQueueEventSize());
   EXPECT_EQ(1U, host_->GestureEventDebouncingQueueSize());
-  MessageLoop::current()->PostDelayedTask(
-      FROM_HERE, MessageLoop::QuitClosure(), TimeDelta::FromMilliseconds(10));
-  MessageLoop::current()->Run();
+  base::MessageLoop::current()->PostDelayedTask(
+      FROM_HERE,
+      base::MessageLoop::QuitClosure(),
+      TimeDelta::FromMilliseconds(10));
+  base::MessageLoop::current()->Run();
   EXPECT_EQ(1U, process_->sink().message_count());
   process_->sink().ClearMessages();
   EXPECT_EQ(1U, host_->GestureEventLastQueueEventSize());
@@ -3721,9 +3759,11 @@
   EXPECT_EQ(0U, host_->GestureEventLastQueueEventSize());
   EXPECT_EQ(1U, host_->GestureEventDebouncingQueueSize());
 
-  MessageLoop::current()->PostDelayedTask(
-      FROM_HERE, MessageLoop::QuitClosure(), TimeDelta::FromMilliseconds(10));
-  MessageLoop::current()->Run();
+  base::MessageLoop::current()->PostDelayedTask(
+      FROM_HERE,
+      base::MessageLoop::QuitClosure(),
+      TimeDelta::FromMilliseconds(10));
+  base::MessageLoop::current()->Run();
   EXPECT_EQ(1U, process_->sink().message_count());
   process_->sink().ClearMessages();
   EXPECT_EQ(1U, host_->GestureEventLastQueueEventSize());
diff --git a/content/browser/renderer_host/render_widget_host_view_android.cc b/content/browser/renderer_host/render_widget_host_view_android.cc
index 1ebece6..dce6a51 100644
--- a/content/browser/renderer_host/render_widget_host_view_android.cc
+++ b/content/browser/renderer_host/render_widget_host_view_android.cc
@@ -22,6 +22,7 @@
 #include "content/browser/renderer_host/surface_texture_transport_client_android.h"
 #include "content/common/gpu/client/gl_helper.h"
 #include "content/common/gpu/gpu_messages.h"
+#include "content/common/input_messages.h"
 #include "content/common/view_messages.h"
 #include "third_party/WebKit/Source/Platform/chromium/public/Platform.h"
 #include "third_party/WebKit/Source/Platform/chromium/public/WebExternalTextureLayer.h"
@@ -75,19 +76,19 @@
     : host_(widget_host),
       is_layer_attached_(true),
       content_view_core_(NULL),
-      ime_adapter_android_(ALLOW_THIS_IN_INITIALIZER_LIST(this)),
+      ime_adapter_android_(this),
       cached_background_color_(SK_ColorWHITE),
       texture_id_in_layer_(0) {
   if (CompositorImpl::UsesDirectGL()) {
     surface_texture_transport_.reset(new SurfaceTextureTransportClient());
     layer_ = surface_texture_transport_->Initialize();
+    layer_->SetIsDrawable(true);
   } else {
-    texture_layer_ = cc::TextureLayer::Create(NULL);
+    texture_layer_ = cc::TextureLayer::Create(this);
     layer_ = texture_layer_;
   }
 
   layer_->SetContentsOpaque(true);
-  layer_->SetIsDrawable(true);
 
   host_->SetView(this);
   SetContentViewCore(content_view_core);
@@ -95,10 +96,23 @@
 
 RenderWidgetHostViewAndroid::~RenderWidgetHostViewAndroid() {
   SetContentViewCore(NULL);
-  if (texture_id_in_layer_) {
-    ImageTransportFactoryAndroid::GetInstance()->DeleteTexture(
-        texture_id_in_layer_);
+  DCHECK(ack_callbacks_.empty());
+  if (texture_id_in_layer_ || !last_mailbox_.IsZero()) {
+    ImageTransportFactoryAndroid* factory =
+        ImageTransportFactoryAndroid::GetInstance();
+    // TODO: crbug.com/230137 - make workaround obsolete with refcounting.
+    // Don't let the last frame we sent leak in the mailbox.
+    if (!last_mailbox_.IsZero()) {
+      if (!texture_id_in_layer_)
+        texture_id_in_layer_ = factory->CreateTexture();
+      factory->AcquireTexture(texture_id_in_layer_, last_mailbox_.name);
+      factory->GetContext3D()->getError();  // Clear error if mailbox was empty.
+    }
+    factory->DeleteTexture(texture_id_in_layer_);
   }
+
+  if (texture_layer_)
+    texture_layer_->ClearClient();
 }
 
 
@@ -111,6 +125,8 @@
     IPC_MESSAGE_HANDLER(ViewHostMsg_StartContentIntent, OnStartContentIntent)
     IPC_MESSAGE_HANDLER(ViewHostMsg_DidChangeBodyBackgroundColor,
                         OnDidChangeBodyBackgroundColor)
+    IPC_MESSAGE_HANDLER(ViewHostMsg_SetVSyncNotificationEnabled,
+                        OnSetVSyncNotificationEnabled)
     IPC_MESSAGE_UNHANDLED(handled = false)
   IPC_END_MESSAGE_MAP()
   return handled;
@@ -143,6 +159,8 @@
 }
 
 void RenderWidgetHostViewAndroid::WasHidden() {
+  RunAckCallbacks();
+
   if (host_->is_hidden())
     return;
 
@@ -233,7 +251,7 @@
 }
 
 gfx::NativeView RenderWidgetHostViewAndroid::GetNativeView() const {
-  return content_view_core_;
+  return content_view_core_->GetViewAndroid();
 }
 
 gfx::NativeViewId RenderWidgetHostViewAndroid::GetNativeViewId() const {
@@ -258,10 +276,11 @@
 void RenderWidgetHostViewAndroid::Focus() {
   host_->Focus();
   host_->SetInputMethodActive(true);
+  ResetClipping();
 }
 
 void RenderWidgetHostViewAndroid::Blur() {
-  host_->Send(new ViewMsg_ExecuteEditCommand(
+  host_->Send(new InputMsg_ExecuteEditCommand(
       host_->GetRoutingID(), "Unselect", ""));
   host_->SetInputMethodActive(false);
   host_->Blur();
@@ -314,7 +333,11 @@
   if (GetPhysicalBackingSize().IsEmpty())
     return gfx::Rect();
 
-  return gfx::Rect(content_view_core_->GetViewportSizeDip());
+  gfx::Size size = content_view_core_->GetViewportSizeDip();
+  gfx::Size offset = content_view_core_->GetViewportSizeOffsetDip();
+  size.Enlarge(-offset.width(), -offset.height());
+
+  return gfx::Rect(size);
 }
 
 gfx::Size RenderWidgetHostViewAndroid::GetPhysicalBackingSize() const {
@@ -372,6 +395,15 @@
     content_view_core_->OnBackgroundColorChanged(color);
 }
 
+void RenderWidgetHostViewAndroid::SendVSync(base::TimeTicks frame_time) {
+  host_->Send(new ViewMsg_DidVSync(host_->GetRoutingID(), frame_time));
+}
+
+void RenderWidgetHostViewAndroid::OnSetVSyncNotificationEnabled(bool enabled) {
+  if (content_view_core_)
+    content_view_core_->SetVSyncNotificationEnabled(enabled);
+}
+
 void RenderWidgetHostViewAndroid::OnStartContentIntent(
     const GURL& content_url) {
   if (content_view_core_)
@@ -491,6 +523,22 @@
 
 void RenderWidgetHostViewAndroid::OnSwapCompositorFrame(
     scoped_ptr<cc::CompositorFrame> frame) {
+  // Always let ContentViewCore know about the new frame first, so it can decide
+  // to schedule a Draw immediately when it sees the texture layer invalidation.
+  if (content_view_core_) {
+    // All offsets and sizes are in CSS pixels.
+    content_view_core_->UpdateFrameInfo(
+        frame->metadata.root_scroll_offset,
+        frame->metadata.page_scale_factor,
+        gfx::Vector2dF(frame->metadata.min_page_scale_factor,
+                       frame->metadata.max_page_scale_factor),
+        frame->metadata.root_layer_size,
+        frame->metadata.viewport_size,
+        frame->metadata.location_bar_offset,
+        frame->metadata.location_bar_content_translation,
+        frame->metadata.overdraw_bottom_height);
+  }
+
   if (!frame->gl_frame_data || frame->gl_frame_data->mailbox.IsZero())
     return;
 
@@ -503,14 +551,16 @@
       frame->gl_frame_data->sync_point);
   const gfx::Size& texture_size = frame->gl_frame_data->size;
 
+  last_mailbox_ = current_mailbox_;
+
   // Calculate the content size.  This should be 0 if the texture_size is 0.
   float dp2px = frame->metadata.device_scale_factor;
   gfx::Vector2dF offset;
   if (texture_size.GetArea() > 0)
     offset = frame->metadata.location_bar_content_translation;
+  offset.set_y(offset.y() + frame->metadata.overdraw_bottom_height);
   gfx::SizeF content_size(texture_size.width() - offset.x() * dp2px,
                           texture_size.height() - offset.y() * dp2px);
-
   BuffersSwapped(frame->gl_frame_data->mailbox,
                  texture_size,
                  content_size,
@@ -564,33 +614,24 @@
         texture_id_in_layer_, current_mailbox_.name);
   } else {
     texture_id_in_layer_ = factory->CreateTexture();
-    texture_layer_->SetTextureId(texture_id_in_layer_);
+    texture_layer_->SetIsDrawable(true);
   }
 
   ImageTransportFactoryAndroid::GetInstance()->AcquireTexture(
       texture_id_in_layer_, mailbox.name);
 
-  // We need to tell ContentViewCore about the new frame before calling
-  // setNeedsDisplay() below so that it has the needed information schedule the
-  // next compositor frame.
-  if (content_view_core_)
-    content_view_core_->DidProduceRendererFrame();
-
-  texture_layer_->SetNeedsDisplay();
-  texture_layer_->SetBounds(gfx::Size(content_size.width(),
-                                      content_size.height()));
-
-  // Calculate the uv_max based on the content size relative to the texture
-  // size.
-  gfx::PointF uv_max;
-  if (texture_size.GetArea() > 0) {
-    uv_max.SetPoint(content_size.width() / texture_size.width(),
-                    content_size.height() / texture_size.height());
-  }
-  texture_layer_->SetUV(gfx::PointF(0, 0), uv_max);
   texture_size_in_layer_ = texture_size;
+  content_size_in_layer_ = gfx::Size(content_size.width(),
+                                     content_size.height());
+
+  ResetClipping();
+
   current_mailbox_ = mailbox;
-  ack_callback.Run();
+
+  if (host_->is_hidden())
+    ack_callback.Run();
+  else
+    ack_callbacks_.push(ack_callback);
 }
 
 void RenderWidgetHostViewAndroid::AcceleratedSurfacePostSubBuffer(
@@ -607,6 +648,7 @@
   // This tells us we should free the frontbuffer.
   if (texture_id_in_layer_) {
     texture_layer_->SetTextureId(0);
+    texture_layer_->SetIsDrawable(false);
     ImageTransportFactoryAndroid::GetInstance()->DeleteTexture(
         texture_id_in_layer_);
     texture_id_in_layer_ = 0;
@@ -632,7 +674,7 @@
 }
 
 gfx::GLSurfaceHandle RenderWidgetHostViewAndroid::GetCompositingSurface() {
-  if (surface_texture_transport_.get()) {
+  if (surface_texture_transport_) {
     return surface_texture_transport_->GetCompositingSurface(
         host_->surface_id());
   } else {
@@ -726,28 +768,58 @@
     host_->MoveCaret(point);
 }
 
+void RenderWidgetHostViewAndroid::RequestContentClipping(
+    const gfx::Rect& clipping,
+    const gfx::Size& content_size) {
+  // A focused view provides its own clipping.
+  if (HasFocus())
+    return;
+
+  ClipContents(clipping, content_size);
+}
+
+void RenderWidgetHostViewAndroid::ResetClipping() {
+  ClipContents(gfx::Rect(gfx::Point(), content_size_in_layer_),
+               content_size_in_layer_);
+}
+
+void RenderWidgetHostViewAndroid::ClipContents(const gfx::Rect& clipping,
+                                               const gfx::Size& content_size) {
+  if (!texture_id_in_layer_ || content_size_in_layer_.IsEmpty())
+    return;
+
+  gfx::Size clipped_content(content_size_in_layer_);
+  clipped_content.ClampToMax(clipping.size());
+  texture_layer_->SetBounds(clipped_content);
+  texture_layer_->SetNeedsDisplay();
+
+  if (texture_size_in_layer_.IsEmpty()) {
+    texture_layer_->SetUV(gfx::PointF(), gfx::PointF());
+    return;
+  }
+
+  gfx::PointF offset(
+      clipping.x() + content_size_in_layer_.width() - content_size.width(),
+      clipping.y() + content_size_in_layer_.height() - content_size.height());
+  offset.ClampToMin(gfx::PointF());
+
+  gfx::Vector2dF uv_scale(1.f / texture_size_in_layer_.width(),
+                          1.f / texture_size_in_layer_.height());
+  texture_layer_->SetUV(
+      gfx::PointF(offset.x() * uv_scale.x(),
+                  offset.y() * uv_scale.y()),
+      gfx::PointF((offset.x() + clipped_content.width()) * uv_scale.x(),
+                  (offset.y() + clipped_content.height()) * uv_scale.y()));
+}
+
 SkColor RenderWidgetHostViewAndroid::GetCachedBackgroundColor() const {
   return cached_background_color_;
 }
 
-void RenderWidgetHostViewAndroid::UpdateFrameInfo(
-    const gfx::Vector2dF& scroll_offset,
-    float page_scale_factor,
-    const gfx::Vector2dF& page_scale_factor_limits,
-    const gfx::SizeF& content_size,
-    const gfx::SizeF& viewport_size,
-    const gfx::Vector2dF& controls_offset,
-    const gfx::Vector2dF& content_offset) {
-  if (content_view_core_) {
-    // All offsets and sizes are in CSS pixels.
-    content_view_core_->UpdateFrameInfo(
-        scroll_offset, page_scale_factor, page_scale_factor_limits,
-        content_size, viewport_size, controls_offset, content_offset);
-  }
-}
-
 void RenderWidgetHostViewAndroid::SetContentViewCore(
     ContentViewCoreImpl* content_view_core) {
+  RunAckCallbacks();
+
   if (content_view_core_ && is_layer_attached_)
     content_view_core_->RemoveLayer(layer_);
 
@@ -756,12 +828,34 @@
     content_view_core_->AttachLayer(layer_);
 }
 
+void RenderWidgetHostViewAndroid::RunAckCallbacks() {
+  while (!ack_callbacks_.empty()) {
+    ack_callbacks_.front().Run();
+    ack_callbacks_.pop();
+  }
+}
+
 void RenderWidgetHostViewAndroid::HasTouchEventHandlers(
     bool need_touch_events) {
   if (content_view_core_)
     content_view_core_->HasTouchEventHandlers(need_touch_events);
 }
 
+unsigned RenderWidgetHostViewAndroid::PrepareTexture(
+    cc::ResourceUpdateQueue* queue) {
+  RunAckCallbacks();
+  return texture_id_in_layer_;
+}
+
+WebKit::WebGraphicsContext3D* RenderWidgetHostViewAndroid::Context3d() {
+  return ImageTransportFactoryAndroid::GetInstance()->GetContext3D();
+}
+
+bool RenderWidgetHostViewAndroid::PrepareTextureMailbox(
+    cc::TextureMailbox* mailbox) {
+  return false;
+}
+
 // static
 void RenderWidgetHostViewPort::GetDefaultScreenInfo(
     WebKit::WebScreenInfo* results) {
diff --git a/content/browser/renderer_host/render_widget_host_view_android.h b/content/browser/renderer_host/render_widget_host_view_android.h
index aec43cf..f0c65ada 100644
--- a/content/browser/renderer_host/render_widget_host_view_android.h
+++ b/content/browser/renderer_host/render_widget_host_view_android.h
@@ -6,12 +6,14 @@
 #define CONTENT_BROWSER_RENDERER_HOST_RENDER_WIDGET_HOST_VIEW_ANDROID_H_
 
 #include <map>
+#include <queue>
 
 #include "base/callback.h"
 #include "base/compiler_specific.h"
 #include "base/i18n/rtl.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/process.h"
+#include "cc/layers/texture_layer_client.h"
 #include "content/browser/renderer_host/ime_adapter_android.h"
 #include "content/browser/renderer_host/render_widget_host_view_base.h"
 #include "gpu/command_buffer/common/mailbox.h"
@@ -46,7 +48,8 @@
 // -----------------------------------------------------------------------------
 // See comments in render_widget_host_view.h about this class and its members.
 // -----------------------------------------------------------------------------
-class RenderWidgetHostViewAndroid : public RenderWidgetHostViewBase {
+class RenderWidgetHostViewAndroid : public RenderWidgetHostViewBase,
+                                    public cc::TextureLayerClient {
  public:
   RenderWidgetHostViewAndroid(RenderWidgetHostImpl* widget,
                               ContentViewCoreImpl* content_view_core);
@@ -144,16 +147,14 @@
   virtual void HasTouchEventHandlers(bool need_touch_events) OVERRIDE;
   virtual void OnSwapCompositorFrame(
       scoped_ptr<cc::CompositorFrame> frame) OVERRIDE;
-  virtual void UpdateFrameInfo(const gfx::Vector2dF& scroll_offset,
-                               float page_scale_factor,
-                               const gfx::Vector2dF& page_scale_factor_limits,
-                               const gfx::SizeF& content_size,
-                               const gfx::SizeF& viewport_size,
-                               const gfx::Vector2dF& controls_offset,
-                               const gfx::Vector2dF& content_offset) OVERRIDE;
   virtual void ShowDisambiguationPopup(const gfx::Rect& target_rect,
                                        const SkBitmap& zoomed_bitmap) OVERRIDE;
 
+  // cc::TextureLayerClient implementation.
+  virtual unsigned PrepareTexture(cc::ResourceUpdateQueue* queue) OVERRIDE;
+  virtual WebKit::WebGraphicsContext3D* Context3d() OVERRIDE;
+  virtual bool PrepareTextureMailbox(cc::TextureMailbox* mailbox) OVERRIDE;
+
   // Non-virtual methods
   void SetContentViewCore(ContentViewCoreImpl* content_view_core);
   SkColor GetCachedBackgroundColor() const;
@@ -162,10 +163,12 @@
   void SendMouseEvent(const WebKit::WebMouseEvent& event);
   void SendMouseWheelEvent(const WebKit::WebMouseWheelEvent& event);
   void SendGestureEvent(const WebKit::WebGestureEvent& event);
+  void SendVSync(base::TimeTicks frame_time);
 
   void OnProcessImeBatchStateAck(bool is_begin);
   void OnDidChangeBodyBackgroundColor(SkColor color);
   void OnStartContentIntent(const GURL& content_url);
+  void OnSetVSyncNotificationEnabled(bool enabled);
 
   int GetNativeImeAdapter();
 
@@ -181,12 +184,20 @@
 
   void MoveCaret(const gfx::Point& point);
 
+  void RequestContentClipping(const gfx::Rect& clipping,
+                              const gfx::Size& content_size);
+
  private:
   void BuffersSwapped(const gpu::Mailbox& mailbox,
                       const gfx::Size texture_size,
                       const gfx::SizeF content_size,
                       const base::Closure& ack_callback);
 
+  void RunAckCallbacks();
+
+  void ResetClipping();
+  void ClipContents(const gfx::Rect& clipping, const gfx::Size& content_size);
+
   // The model object.
   RenderWidgetHostImpl* host_;
 
@@ -218,12 +229,20 @@
   // The most recent texture size that was pushed to the texture layer.
   gfx::Size texture_size_in_layer_;
 
+  // The most recent content size that was pushed to the texture layer.
+  gfx::Size content_size_in_layer_;
+
   // Used for image transport when needing to share resources across threads.
   scoped_ptr<SurfaceTextureTransportClient> surface_texture_transport_;
 
   // The mailbox of the previously received frame.
   gpu::Mailbox current_mailbox_;
 
+  // The mailbox of the frame we last returned.
+  gpu::Mailbox last_mailbox_;
+
+  std::queue<base::Closure> ack_callbacks_;
+
   DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewAndroid);
 };
 
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.cc b/content/browser/renderer_host/render_widget_host_view_aura.cc
index c7d3aff..c28c9ee 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura.cc
+++ b/content/browser/renderer_host/render_widget_host_view_aura.cc
@@ -25,6 +25,7 @@
 #include "content/common/gpu/client/gl_helper.h"
 #include "content/common/gpu/gpu_messages.h"
 #include "content/common/view_messages.h"
+#include "content/port/browser/render_widget_host_view_frame_subscriber.h"
 #include "content/port/browser/render_widget_host_view_port.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/browser_thread.h"
@@ -40,6 +41,7 @@
 #include "ui/aura/client/activation_client.h"
 #include "ui/aura/client/aura_constants.h"
 #include "ui/aura/client/cursor_client.h"
+#include "ui/aura/client/cursor_client_observer.h"
 #include "ui/aura/client/focus_client.h"
 #include "ui/aura/client/screen_position_client.h"
 #include "ui/aura/client/stacking_client.h"
@@ -67,6 +69,7 @@
 #include "ui/gfx/skia_util.h"
 
 #if defined(OS_WIN)
+#include "base/win/windows_version.h"
 #include "content/browser/accessibility/browser_accessibility_manager_win.h"
 #include "content/browser/accessibility/browser_accessibility_win.h"
 #include "ui/base/win/hidden_window.h"
@@ -265,6 +268,10 @@
 }
 
 bool ShouldSendPinchGesture() {
+#if defined(OS_WIN)
+  if (base::win::GetVersion() >= base::win::VERSION_WIN8)
+    return true;
+#endif
   static bool pinch_allowed =
       CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableViewport) ||
       CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnablePinch);
@@ -393,18 +400,15 @@
 
 void RenderWidgetHostViewAura::ApplyEventFilterForPopupExit(
     ui::MouseEvent* event) {
-  if (in_shutdown_) {
-    event_filter_for_popup_exit_.reset();
+  if (in_shutdown_ || is_fullscreen_)
     return;
-  }
-  if (is_fullscreen_ || event->type() != ui::ET_MOUSE_PRESSED ||
-      !event->target())
+
+  if (event->type() != ui::ET_MOUSE_PRESSED || !event->target())
     return;
 
   DCHECK(popup_parent_host_view_);
   aura::Window* target = static_cast<aura::Window*>(event->target());
   if (target != window_ && target != popup_parent_host_view_->window_) {
-    event_filter_for_popup_exit_.reset();
     in_shutdown_ = true;
     host_->Shutdown();
   }
@@ -558,6 +562,9 @@
                          root_window_->compositor()->GetCompositorLock()),
         weak_ptr_factory_(this),
         defer_compositor_lock_(defer_compositor_lock) {
+    TRACE_EVENT_ASYNC_BEGIN2("ui", "ResizeLock", this,
+                             "width", new_size_.width(),
+                             "height", new_size_.height());
     root_window_->HoldMouseMoves();
 
     BrowserThread::PostDelayedTask(
@@ -569,6 +576,9 @@
 
   ~ResizeLock() {
     CancelLock();
+    TRACE_EVENT_ASYNC_END2("ui", "ResizeLock", this,
+                           "width", new_size_.width(),
+                           "height", new_size_.height());
   }
 
   void UnlockCompositor() {
@@ -612,7 +622,7 @@
 
 RenderWidgetHostViewAura::RenderWidgetHostViewAura(RenderWidgetHost* host)
     : host_(RenderWidgetHostImpl::From(host)),
-      ALLOW_THIS_IN_INITIALIZER_LIST(window_(new aura::Window(this))),
+      window_(new aura::Window(this)),
       in_shutdown_(false),
       is_fullscreen_(false),
       popup_parent_host_view_(NULL),
@@ -625,8 +635,9 @@
       synthetic_move_sent_(false),
       accelerated_compositing_state_changed_(false),
       can_lock_compositor_(YES),
+      cursor_visibility_state_in_renderer_(UNKNOWN),
       paint_observer_(NULL),
-      accessible_parent_(NULL) {
+      touch_editing_client_(NULL) {
   host_->SetView(this);
   window_observer_.reset(new WindowObserver(this));
   aura::client::SetTooltipText(window_, &tooltip_);
@@ -721,6 +732,11 @@
     return;
   host_->WasShown();
 
+  aura::client::CursorClient* cursor_client =
+      aura::client::GetCursorClient(window_->GetRootWindow());
+  if (cursor_client)
+    NotifyRendererOfCursorVisibilityState(cursor_client->IsCursorVisible());
+
   if (!current_surface_ && host_->is_accelerated_compositing_active() &&
       !released_front_lock_.get()) {
     released_front_lock_ = GetCompositor()->GetCompositorLock();
@@ -756,7 +772,19 @@
 }
 
 void RenderWidgetHostViewAura::SetBounds(const gfx::Rect& rect) {
-  if (window_->bounds().size() != rect.size() &&
+  window_->SetBounds(rect);
+  host_->WasResized();
+  MaybeCreateResizeLock();
+  if (touch_editing_client_) {
+    touch_editing_client_->OnSelectionOrCursorChanged(selection_anchor_rect_,
+        selection_focus_rect_);
+  }
+}
+
+void RenderWidgetHostViewAura::MaybeCreateResizeLock() {
+  gfx::Size desired_size = window_->bounds().size();
+  if (!resize_lock_.get() &&
+      desired_size != current_frame_size_ &&
       host_->is_accelerated_compositing_active()) {
     aura::RootWindow* root_window = window_->GetRootWindow();
     ui::Compositor* compositor = root_window ?
@@ -766,6 +794,14 @@
       if (!compositor->HasObserver(this))
         compositor->AddObserver(this);
 
+// On Windows while resizing, the the resize locks makes us mis-paint a white
+// vertical strip (including the non-client area) if the content composition is
+// lagging the UI composition. So here we disable the throttling so that the UI
+// bits can draw ahead of the content thereby reducing the amount of whiteout.
+// Because this causes the content to be drawn at wrong sizes while resizing
+// we compensate by blocking the UI thread in Compositor::Draw() by issuing a
+// FinishAllRendering() if we are resizing.
+#if !defined (OS_WIN)
       bool defer_compositor_lock =
          can_lock_compositor_ == NO_PENDING_RENDERER_FRAME ||
          can_lock_compositor_ == NO_PENDING_COMMIT;
@@ -773,12 +809,11 @@
       if (can_lock_compositor_ == YES)
         can_lock_compositor_ = YES_DID_LOCK;
 
-      resize_locks_.push_back(make_linked_ptr(
-          new ResizeLock(root_window, rect.size(), defer_compositor_lock)));
+      resize_lock_.reset(new ResizeLock(root_window, desired_size,
+                                        defer_compositor_lock));
+#endif
     }
   }
-  window_->SetBounds(rect);
-  host_->WasResized();
 }
 
 gfx::NativeView RenderWidgetHostViewAura::GetNativeView() const {
@@ -825,8 +860,12 @@
     return NULL;
   HWND hwnd = root_window->GetAcceleratedWidget();
 
+  gfx::NativeViewAccessible accessible_parent =
+      host_->GetParentNativeViewAccessible();
+  DCHECK(accessible_parent);
+
   manager = new BrowserAccessibilityManagerWin(
-      hwnd, accessible_parent_,
+      hwnd, accessible_parent,
       BrowserAccessibilityManagerWin::GetEmptyDocument(), this);
 #else
   manager = BrowserAccessibilityManager::Create(AccessibilityNodeData(), this);
@@ -913,7 +952,7 @@
 }
 
 bool RenderWidgetHostViewAura::IsSurfaceAvailableForCopy() const {
-  return current_surface_ || !!host_->GetBackingStore(false);
+  return current_surface_ || current_dib_ || !!host_->GetBackingStore(false);
 }
 
 void RenderWidgetHostViewAura::Show() {
@@ -929,7 +968,14 @@
 }
 
 gfx::Rect RenderWidgetHostViewAura::GetViewBounds() const {
-  return window_->GetBoundsInScreen();
+  // This is the size that we want the renderer to produce. While we're waiting
+  // for the correct frame (i.e. during a resize), don't change the size so that
+  // we don't pipeline more resizes than we can handle.
+  gfx::Rect bounds(window_->GetBoundsInScreen());
+  if (resize_lock_.get())
+    return gfx::Rect(bounds.origin(), resize_lock_->expected_size());
+  else
+    return bounds;
 }
 
 void RenderWidgetHostViewAura::SetBackground(const SkBitmap& background) {
@@ -939,17 +985,16 @@
 }
 
 #if defined(OS_WIN)
-void RenderWidgetHostViewAura::SetParentNativeViewAccessible(
-    gfx::NativeViewAccessible accessible_parent) {
-  accessible_parent_ = accessible_parent;
-
+gfx::NativeViewAccessible
+RenderWidgetHostViewAura::AccessibleObjectFromChildId(long child_id) {
   BrowserAccessibilityManager* manager = GetBrowserAccessibilityManager();
-  if (manager) {
-    static_cast<BrowserAccessibilityManagerWin*>(manager)->
-        set_parent_iaccessible(accessible_parent);
-  }
+  if (!manager)
+    return NULL;
+
+  return manager->ToBrowserAccessibilityManagerWin()->GetFromUniqueIdWin(
+      child_id);
 }
-#endif
+#endif  // defined(OS_WIN)
 
 void RenderWidgetHostViewAura::UpdateCursor(const WebCursor& cursor) {
   current_cursor_ = cursor;
@@ -974,6 +1019,8 @@
     can_compose_inline_ = params.can_compose_inline;
     if (GetInputMethod())
       GetInputMethod()->OnTextInputTypeChanged(this);
+    if (touch_editing_client_)
+      touch_editing_client_->OnTextInputTypeChanged(text_input_type_);
   }
 }
 
@@ -1089,6 +1136,11 @@
 
   if (GetInputMethod())
     GetInputMethod()->OnCaretBoundsChanged(this);
+
+  if (touch_editing_client_) {
+    touch_editing_client_->OnSelectionOrCursorChanged(selection_anchor_rect_,
+        selection_focus_rect_);
+  }
 }
 
 void RenderWidgetHostViewAura::ScrollOffsetChanged() {
@@ -1199,9 +1251,23 @@
 }
 
 bool RenderWidgetHostViewAura::CanCopyToVideoFrame() const {
-  return current_surface_ != NULL;
+  return current_surface_ != NULL && host_->is_accelerated_compositing_active();
 }
 
+bool RenderWidgetHostViewAura::CanSubscribeFrame() const {
+  return true;
+}
+
+void RenderWidgetHostViewAura::BeginFrameSubscription(
+    scoped_ptr<RenderWidgetHostViewFrameSubscriber> subscriber) {
+  frame_subscriber_ = subscriber.Pass();
+}
+
+void RenderWidgetHostViewAura::EndFrameSubscription() {
+  frame_subscriber_.reset();
+}
+
+
 void RenderWidgetHostViewAura::OnAcceleratedCompositingStateChange() {
   // Delay processing the state change until we either get a software frame if
   // switching to software mode or receive a buffers swapped notification
@@ -1214,50 +1280,27 @@
   accelerated_compositing_state_changed_ = true;
 }
 
-bool RenderWidgetHostViewAura::ShouldSkipFrame(gfx::Size size_in_dip) {
+bool RenderWidgetHostViewAura::ShouldSkipFrame(gfx::Size size_in_dip) const {
   if (can_lock_compositor_ == NO_PENDING_RENDERER_FRAME ||
       can_lock_compositor_ == NO_PENDING_COMMIT ||
-      resize_locks_.empty())
+      !resize_lock_.get())
     return false;
 
-  ResizeLockList::iterator it = resize_locks_.begin();
-  while (it != resize_locks_.end()) {
-    if ((*it)->expected_size() == size_in_dip)
-      break;
-    ++it;
-  }
-
-  // We could be getting an unexpected frame due to an animation
-  // (i.e. we start resizing but we get an old size frame first).
-  return it == resize_locks_.end() || ++it != resize_locks_.end();
+  return size_in_dip != resize_lock_->expected_size();
 }
 
-void RenderWidgetHostViewAura::CheckResizeLocks(gfx::Size size_in_dip) {
-  ResizeLockList::iterator it = resize_locks_.begin();
-  while (it != resize_locks_.end()) {
-    if ((*it)->expected_size() == size_in_dip)
-      break;
-    ++it;
-  }
-  if (it != resize_locks_.end()) {
-    ++it;
-    ui::Compositor* compositor = GetCompositor();
-    if (compositor) {
-      // Delay the release of the lock until we've kicked a frame with the
-      // new texture, to avoid resizing the UI before we have a chance to
-      // draw a "good" frame.
-      locks_pending_commit_.insert(
-          locks_pending_commit_.begin(), resize_locks_.begin(), it);
-      // However since we got the size we were looking for, unlock the
-      // compositor.
-      for (ResizeLockList::iterator it2 = resize_locks_.begin();
-           it2 !=it; ++it2) {
-        it2->get()->UnlockCompositor();
-      }
-      if (!compositor->HasObserver(this))
-        compositor->AddObserver(this);
-    }
-    resize_locks_.erase(resize_locks_.begin(), it);
+void RenderWidgetHostViewAura::CheckResizeLock() {
+  if (!resize_lock_ || resize_lock_->expected_size() != current_frame_size_)
+    return;
+
+  // Since we got the size we were looking for, unlock the compositor. But delay
+  // the release of the lock until we've kicked a frame with the new texture, to
+  // avoid resizing the UI before we have a chance to draw a "good" frame.
+  resize_lock_->UnlockCompositor();
+  ui::Compositor* compositor = GetCompositor();
+  if (compositor) {
+    if (!compositor->HasObserver(this))
+      compositor->AddObserver(this);
   }
 }
 
@@ -1268,13 +1311,19 @@
   if (accelerated_compositing_state_changed_)
     accelerated_compositing_state_changed_ = false;
 
-  if (current_surface_ && host_->is_accelerated_compositing_active()) {
+  bool is_compositing_active = host_->is_accelerated_compositing_active();
+  if (is_compositing_active && current_surface_) {
     window_->SetExternalTexture(current_surface_.get());
-    gfx::Size container_size = ConvertSizeToDIP(this, current_surface_->size());
-    CheckResizeLocks(container_size);
+    current_frame_size_ = ConvertSizeToDIP(this, current_surface_->size());
+    CheckResizeLock();
+  } else if (is_compositing_active && current_dib_) {
+    window_->SetExternalTexture(NULL);
+    current_frame_size_ = ConvertSizeToDIP(this, last_swapped_surface_size_);
+    CheckResizeLock();
   } else {
     window_->SetExternalTexture(NULL);
-    resize_locks_.clear();
+    resize_lock_.reset();
+    host_->WasResized();
   }
 }
 
@@ -1318,15 +1367,25 @@
     const BufferPresentedCallback& ack_callback,
     const scoped_refptr<ui::Texture>& texture_to_return) {
   ui::Compositor* compositor = GetCompositor();
+
+  if (frame_subscriber() && current_surface_ != NULL) {
+    const base::Time present_time = base::Time::Now();
+    scoped_refptr<media::VideoFrame> frame;
+    RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback callback;
+    if (frame_subscriber()->ShouldCaptureFrame(present_time,
+                                               &frame, &callback)) {
+      CopyFromCompositingSurfaceToVideoFrame(
+          gfx::Rect(ConvertSizeToDIP(this, current_surface_->size())),
+          frame,
+          base::Bind(callback, present_time));
+    }
+  }
+
   if (!compositor) {
     ack_callback.Run(false, texture_to_return);
   } else {
-    // Add sending an ACK to the list of things to do OnCompositingDidCommit
-    can_lock_compositor_ = NO_PENDING_COMMIT;
-    on_compositing_did_commit_callbacks_.push_back(
+    AddOnCommitCallbackAndDisableLocks(
         base::Bind(ack_callback, false, texture_to_return));
-    if (!compositor->HasObserver(this))
-      compositor->AddObserver(this);
   }
 }
 
@@ -1381,12 +1440,16 @@
         1.f/frame_device_scale_factor));
   }
   if (ShouldSkipFrame(frame_size_in_dip)) {
-    SendDelegatedFrameAck();
+    cc::CompositorFrameAck ack;
+    ack.resources.swap(frame_data->resource_list);
+    RenderWidgetHostImpl::SendSwapCompositorFrameAck(
+        host_->GetRoutingID(), host_->GetProcess()->GetID(), ack);
     return;
   }
   window_->layer()->SetDelegatedFrame(frame_data.Pass(), frame_size_in_dip);
   released_front_lock_ = NULL;
-  CheckResizeLocks(frame_size_in_dip);
+  current_frame_size_ = frame_size_in_dip;
+  CheckResizeLock();
 
   if (paint_observer_)
     paint_observer_->OnUpdateCompositorContent();
@@ -1395,12 +1458,9 @@
   if (!compositor) {
     SendDelegatedFrameAck();
   } else {
-    can_lock_compositor_ = NO_PENDING_COMMIT;
-    on_compositing_did_commit_callbacks_.push_back(
+    AddOnCommitCallbackAndDisableLocks(
         base::Bind(&RenderWidgetHostViewAura::SendDelegatedFrameAck,
-                   base::Unretained(this)));
-    if (!compositor->HasObserver(this))
-      compositor->AddObserver(this);
+                   AsWeakPtr()));
   }
 }
 
@@ -1411,6 +1471,78 @@
       host_->GetRoutingID(), host_->GetProcess()->GetID(), ack);
 }
 
+void RenderWidgetHostViewAura::SwapSoftwareFrame(
+    scoped_ptr<cc::SoftwareFrameData> frame_data,
+    float frame_device_scale_factor) {
+  const gfx::Size& frame_size = frame_data->size;
+  const gfx::Rect& damage_rect = frame_data->damage_rect;
+  const TransportDIB::Id& dib_id = frame_data->dib_id;
+
+  scoped_ptr<TransportDIB> dib;
+#if defined(OS_WIN)
+  TransportDIB::Handle my_handle = TransportDIB::DefaultHandleValue();
+  ::DuplicateHandle(host_->GetProcess()->GetHandle(), dib_id.handle,
+                    ::GetCurrentProcess(), &my_handle,
+                    0, FALSE, DUPLICATE_SAME_ACCESS);
+  dib.reset(TransportDIB::Map(my_handle));
+#elif defined(USE_X11)
+  dib.reset(TransportDIB::Map(dib_id.shmkey));
+#else
+  NOTIMPLEMENTED();
+#endif
+
+  // Validate the received DIB.
+  size_t expected_size = 4 * frame_size.GetArea();
+  if (!dib || dib->size() < expected_size) {
+    host_->GetProcess()->ReceivedBadMessage();
+    return;
+  }
+
+  if (last_swapped_surface_size_ != frame_size) {
+    DLOG_IF(ERROR, damage_rect != gfx::Rect(frame_size))
+      << "Expected full damage rect";
+  }
+
+  TransportDIB::Id last_dib_id = current_dib_id_;
+  current_dib_.reset(dib.release());
+  current_dib_id_ = dib_id;
+  last_swapped_surface_size_ = frame_size;
+
+  ui::Compositor* compositor = GetCompositor();
+  if (!compositor) {
+    SendSoftwareFrameAck(last_dib_id);
+    return;
+  }
+
+  gfx::Size frame_size_in_dip = gfx::ToFlooredSize(
+      gfx::ScaleSize(frame_size, 1.0f / frame_device_scale_factor));
+  if (ShouldSkipFrame(frame_size_in_dip)) {
+    can_lock_compositor_ = NO_PENDING_COMMIT;
+    SendSoftwareFrameAck(last_dib_id);
+  } else {
+    AddOnCommitCallbackAndDisableLocks(
+        base::Bind(&RenderWidgetHostViewAura::SendSoftwareFrameAck,
+                   AsWeakPtr(), last_dib_id));
+  }
+
+  current_frame_size_ = frame_size_in_dip;
+  CheckResizeLock();
+  released_front_lock_ = NULL;
+  window_->SetExternalTexture(NULL);
+  window_->SchedulePaintInRect(ConvertRectToDIP(this, damage_rect));
+
+  if (paint_observer_)
+    paint_observer_->OnUpdateCompositorContent();
+}
+
+void RenderWidgetHostViewAura::SendSoftwareFrameAck(
+    const TransportDIB::Id& id) {
+  cc::CompositorFrameAck ack;
+  ack.last_dib_id = id;
+  RenderWidgetHostImpl::SendSwapCompositorFrameAck(
+      host_->GetRoutingID(), host_->GetProcess()->GetID(), ack);
+}
+
 void RenderWidgetHostViewAura::OnSwapCompositorFrame(
     scoped_ptr<cc::CompositorFrame> frame) {
   if (frame->delegated_frame_data) {
@@ -1418,6 +1550,13 @@
                        frame->metadata.device_scale_factor);
     return;
   }
+
+  if (frame->software_frame_data) {
+    SwapSoftwareFrame(frame->software_frame_data.Pass(),
+                      frame->metadata.device_scale_factor);
+    return;
+  }
+
   if (!frame->gl_frame_data || frame->gl_frame_data->mailbox.IsZero())
     return;
 
@@ -1447,7 +1586,7 @@
     const std::string& mailbox_name,
     const BufferPresentedCallback& ack_callback) {
   scoped_refptr<ui::Texture> texture_to_return(current_surface_);
-  const gfx::Rect surface_rect = gfx::Rect(gfx::Point(), size);
+  const gfx::Rect surface_rect = gfx::Rect(size);
   if (!SwapBuffersPrepare(
       surface_rect, surface_rect, mailbox_name, ack_callback)) {
     return;
@@ -1473,7 +1612,7 @@
     int gpu_host_id) {
   scoped_refptr<ui::Texture> previous_texture(current_surface_);
   const gfx::Rect surface_rect =
-      gfx::Rect(gfx::Point(), params_in_pixel.surface_size);
+      gfx::Rect(params_in_pixel.surface_size);
   gfx::Rect damage_rect(params_in_pixel.x,
                         params_in_pixel.y,
                         params_in_pixel.width,
@@ -1547,15 +1686,12 @@
     if (compositor) {
       // We need to wait for a commit to clear to guarantee that all we
       // will not issue any more GL referencing the previous surface.
-      can_lock_compositor_ = NO_PENDING_COMMIT;
-      on_compositing_did_commit_callbacks_.push_back(
+      AddOnCommitCallbackAndDisableLocks(
           base::Bind(&RenderWidgetHostViewAura::
                      SetSurfaceNotInUseByCompositor,
                      AsWeakPtr(),
                      current_surface_));  // Hold a ref so the texture will not
                                           // get deleted until after commit.
-      if (!compositor->HasObserver(this))
-        compositor->AddObserver(this);
     }
     current_surface_ = NULL;
     UpdateExternalTexture();
@@ -1581,7 +1717,7 @@
     bool result) {
   callback.Run(result, bitmap);
 
-  if (!render_widget_host_view.get())
+  if (!render_widget_host_view)
     return;
   --render_widget_host_view->pending_thumbnail_tasks_;
 }
@@ -1594,6 +1730,11 @@
   return window_->GetToplevelWindow()->GetBoundsInScreen();
 }
 
+void RenderWidgetHostViewAura::GestureEventAck(int gesture_event_type) {
+  if (touch_editing_client_)
+    touch_editing_client_->GestureEventAck(gesture_event_type);
+}
+
 void RenderWidgetHostViewAura::ProcessAckedTouchEvent(
     const WebKit::WebTouchEvent& touch_event, InputEventAckState ack_result) {
   ScopedVector<ui::TouchEvent> events;
@@ -1653,8 +1794,11 @@
   window_->SetCapture();
   aura::client::CursorClient* cursor_client =
       aura::client::GetCursorClient(root_window);
-  if (cursor_client)
+  if (cursor_client) {
     cursor_client->HideCursor();
+    cursor_client->LockCursor();
+  }
+
   synthetic_move_sent_ = true;
   window_->MoveCursorTo(gfx::Rect(window_->bounds().size()).CenterPoint());
   if (aura::client::GetTooltipClient(root_window))
@@ -1673,8 +1817,11 @@
   window_->MoveCursorTo(unlocked_mouse_position_);
   aura::client::CursorClient* cursor_client =
       aura::client::GetCursorClient(root_window);
-  if (cursor_client)
+  if (cursor_client) {
+    cursor_client->UnlockCursor();
     cursor_client->ShowCursor();
+  }
+
   if (aura::client::GetTooltipClient(root_window))
     aura::client::GetTooltipClient(root_window)->SetTooltipsEnabled(true);
 
@@ -1773,6 +1920,26 @@
   return rect;
 }
 
+gfx::Rect RenderWidgetHostViewAura::ConvertRectFromScreen(
+    const gfx::Rect& rect) {
+  gfx::Point origin = rect.origin();
+  gfx::Point end = gfx::Point(rect.right(), rect.bottom());
+
+  aura::RootWindow* root_window = window_->GetRootWindow();
+  if (root_window) {
+    aura::client::ScreenPositionClient* screen_position_client =
+        aura::client::GetScreenPositionClient(root_window);
+    screen_position_client->ConvertPointFromScreen(window_, &origin);
+    screen_position_client->ConvertPointFromScreen(window_, &end);
+    return gfx::Rect(origin.x(),
+                     origin.y(),
+                     end.x() - origin.x(),
+                     end.y() - origin.y());
+  }
+
+  return rect;
+}
+
 gfx::Rect RenderWidgetHostViewAura::GetCaretBounds() {
   const gfx::Rect rect =
       gfx::UnionRects(selection_anchor_rect_, selection_focus_rect_);
@@ -1868,9 +2035,19 @@
 
 void RenderWidgetHostViewAura::ExtendSelectionAndDelete(
     size_t before, size_t after) {
-  // TODO(horo): implement this method if it is required.
-  // http://crbug.com/149155
-  NOTIMPLEMENTED();
+  if (host_)
+    host_->ExtendSelectionAndDelete(before, after);
+}
+
+void RenderWidgetHostViewAura::EnsureCaretInRect(const gfx::Rect& rect) {
+  gfx::Rect intersected_rect(
+      gfx::IntersectRects(rect, window_->GetBoundsInScreen()));
+
+  if (intersected_rect.IsEmpty())
+    return;
+
+  host_->ScrollFocusedEditableNodeIntoRect(
+      ConvertRectFromScreen(intersected_rect));
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -1935,15 +2112,47 @@
 
 void RenderWidgetHostViewAura::OnCaptureLost() {
   host_->LostCapture();
+  if (touch_editing_client_)
+    touch_editing_client_->EndTouchEditing();
 }
 
 void RenderWidgetHostViewAura::OnPaint(gfx::Canvas* canvas) {
-  paint_canvas_ = canvas;
-  BackingStore* backing_store = host_->GetBackingStore(true);
-  paint_canvas_ = NULL;
-  if (backing_store) {
-    static_cast<BackingStoreAura*>(backing_store)->SkiaShowRect(gfx::Point(),
-                                                                canvas);
+  bool is_compositing_active = host_->is_accelerated_compositing_active();
+  bool has_backing_store = !!host_->GetBackingStore(false);
+  if (is_compositing_active && current_dib_) {
+    const gfx::Size window_size = window_->bounds().size();
+    const gfx::Size& frame_size = last_swapped_surface_size_;
+
+    SkBitmap bitmap;
+    bitmap.setConfig(SkBitmap::kARGB_8888_Config,
+                     frame_size.width(),
+                     frame_size.height());
+    bitmap.setPixels(current_dib_->memory());
+
+    SkCanvas* sk_canvas = canvas->sk_canvas();
+    sk_canvas->drawBitmap(bitmap, 0, 0);
+
+    if (frame_size != window_size) {
+      SkRegion region;
+      region.op(0, 0, window_size.width(), window_size.height(),
+                SkRegion::kUnion_Op);
+      region.op(0, 0, frame_size.width(), frame_size.height(),
+                SkRegion::kDifference_Op);
+      SkPaint paint;
+      paint.setColor(SK_ColorWHITE);
+      for (SkRegion::Iterator it(region); !it.done(); it.next())
+        sk_canvas->drawIRect(it.rect(), paint);
+    }
+
+    if (paint_observer_)
+      paint_observer_->OnPaintComplete();
+  } else if (!is_compositing_active && has_backing_store) {
+    paint_canvas_ = canvas;
+    BackingStoreAura* backing_store = static_cast<BackingStoreAura*>(
+        host_->GetBackingStore(true));
+    paint_canvas_ = NULL;
+    backing_store->SkiaShowRect(gfx::Point(), canvas);
+
     if (paint_observer_)
       paint_observer_->OnPaintComplete();
   } else if (aura::Env::GetInstance()->render_white_bg()) {
@@ -2024,6 +2233,9 @@
 
 void RenderWidgetHostViewAura::OnKeyEvent(ui::KeyEvent* event) {
   TRACE_EVENT0("browser", "RenderWidgetHostViewAura::OnKeyEvent");
+  if (touch_editing_client_ && touch_editing_client_->HandleInputEvent(event))
+    return;
+
   if (popup_child_host_view_ && popup_child_host_view_->NeedsInputGrab()) {
     popup_child_host_view_->OnKeyEvent(event);
     if (event->handled())
@@ -2073,12 +2285,13 @@
 void RenderWidgetHostViewAura::OnMouseEvent(ui::MouseEvent* event) {
   TRACE_EVENT0("browser", "RenderWidgetHostViewAura::OnMouseEvent");
 
+  if (touch_editing_client_ && touch_editing_client_->HandleInputEvent(event))
+    return;
+
   if (mouse_locked_) {
-    // Hide the cursor if someone else has shown it.
     aura::client::CursorClient* cursor_client =
         aura::client::GetCursorClient(window_->GetRootWindow());
-    if (cursor_client && cursor_client->IsCursorVisible())
-      cursor_client->DisableMouseEvents();
+    DCHECK(!cursor_client || !cursor_client->IsCursorVisible());
 
     WebKit::WebMouseEvent mouse_event = MakeWebMouseEvent(event);
     gfx::Point center(gfx::Rect(window_->bounds().size()).CenterPoint());
@@ -2164,7 +2377,11 @@
 
   // Needed to propagate mouse event to native_tab_contents_view_aura.
   // TODO(pkotwicz): Find a better way of doing this.
-  if (window_->parent()->delegate() && !(event->flags() & ui::EF_FROM_TOUCH))
+  // In fullscreen mode which is typically used by flash, don't forward
+  // the mouse events to the parent. The renderer and the plugin process
+  // handle these events.
+  if (!is_fullscreen_ && window_->parent()->delegate() &&
+      !(event->flags() & ui::EF_FROM_TOUCH))
     window_->parent()->delegate()->OnMouseEvent(event);
 
   if (!IsXButtonUpEvent(event))
@@ -2173,6 +2390,9 @@
 
 void RenderWidgetHostViewAura::OnScrollEvent(ui::ScrollEvent* event) {
   TRACE_EVENT0("browser", "RenderWidgetHostViewAura::OnScrollEvent");
+  if (touch_editing_client_ && touch_editing_client_->HandleInputEvent(event))
+    return;
+
   if (event->type() == ui::ET_SCROLL) {
     if (event->finger_count() != 2)
       return;
@@ -2197,6 +2417,9 @@
 
 void RenderWidgetHostViewAura::OnTouchEvent(ui::TouchEvent* event) {
   TRACE_EVENT0("browser", "RenderWidgetHostViewAura::OnTouchEvent");
+  if (touch_editing_client_ && touch_editing_client_->HandleInputEvent(event))
+    return;
+
   // Update the touch event first.
   WebKit::WebTouchPoint* point = UpdateWebTouchEventFromUIEvent(*event,
                                                                 &touch_event_);
@@ -2227,6 +2450,9 @@
     return;
   }
 
+  if (touch_editing_client_ && touch_editing_client_->HandleInputEvent(event))
+    return;
+
   RenderViewHostDelegate* delegate = NULL;
   if (popup_type_ == WebKit::WebPopupTypeNone && !is_fullscreen_)
     delegate = RenderViewHost::From(host_)->GetDelegate();
@@ -2296,6 +2522,13 @@
 }
 
 ////////////////////////////////////////////////////////////////////////////////
+// RenderWidgetHostViewAura, aura::client::CursorClientObserver implementation:
+
+void RenderWidgetHostViewAura::OnCursorVisibilityChanged(bool is_visible) {
+  NotifyRendererOfCursorVisibilityState(is_visible);
+}
+
+////////////////////////////////////////////////////////////////////////////////
 // RenderWidgetHostViewAura, aura::client::FocusChangeObserver implementation:
 
 void RenderWidgetHostViewAura::OnWindowFocused(aura::Window* gained_focus,
@@ -2332,9 +2565,18 @@
     DetachFromInputMethod();
     host_->SetInputMethodActive(false);
 
+    if (touch_editing_client_)
+      touch_editing_client_->EndTouchEditing();
+
     // If we lose the focus while fullscreen, close the window; Pepper Flash
-    // won't do it for us (unlike NPAPI Flash).
-    if (is_fullscreen_ && !in_shutdown_) {
+    // won't do it for us (unlike NPAPI Flash). However, we do not close the
+    // window if we lose the focus to a window on another display.
+    gfx::Screen* screen = gfx::Screen::GetScreenFor(window_);
+    bool focusing_other_display =
+        gained_focus && screen->GetNumDisplays() > 1 &&
+        (screen->GetDisplayNearestWindow(window_).id() !=
+         screen->GetDisplayNearestWindow(gained_focus).id());
+    if (is_fullscreen_ && !in_shutdown_ && !focusing_other_display) {
       in_shutdown_ = true;
       host_->Shutdown();
     }
@@ -2356,13 +2598,18 @@
     ui::Compositor* compositor) {
   if (can_lock_compositor_ == NO_PENDING_COMMIT) {
     can_lock_compositor_ = YES;
-    for (ResizeLockList::iterator it = resize_locks_.begin();
-        it != resize_locks_.end(); ++it)
-      if ((*it)->GrabDeferredLock())
-        can_lock_compositor_ = YES_DID_LOCK;
+    if (resize_lock_.get() && resize_lock_->GrabDeferredLock())
+      can_lock_compositor_ = YES_DID_LOCK;
   }
-  RunCompositingDidCommitCallbacks();
-  locks_pending_commit_.clear();
+  RunOnCommitCallbacks();
+  if (resize_lock_ && resize_lock_->expected_size() == current_frame_size_) {
+    resize_lock_.reset();
+    host_->WasResized();
+    // We may have had a resize while we had the lock (e.g. if the lock expired,
+    // or if the UI still gave us some resizes), so make sure we grab a new lock
+    // if necessary.
+    MaybeCreateResizeLock();
+  }
 }
 
 void RenderWidgetHostViewAura::OnCompositingStarted(
@@ -2455,12 +2702,11 @@
 void RenderWidgetHostViewAura::OnLostResources() {
   current_surface_ = NULL;
   UpdateExternalTexture();
-  locks_pending_commit_.clear();
 
   // Make sure all ImageTransportClients are deleted now that the context those
   // are using is becoming invalid. This sends pending ACKs and needs to happen
   // after calling UpdateExternalTexture() which syncs with the impl thread.
-  RunCompositingDidCommitCallbacks();
+  RunOnCommitCallbacks();
 
   DCHECK(!shared_surface_handle_.is_null());
   ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
@@ -2476,6 +2722,8 @@
 RenderWidgetHostViewAura::~RenderWidgetHostViewAura() {
   if (paint_observer_)
     paint_observer_->OnViewDestroyed();
+  if (touch_editing_client_)
+    touch_editing_client_->OnViewDestroyed();
   if (!shared_surface_handle_.is_null()) {
     ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
     factory->DestroySharedSurfaceHandle(shared_surface_handle_);
@@ -2593,6 +2841,17 @@
   }
 }
 
+void RenderWidgetHostViewAura::NotifyRendererOfCursorVisibilityState(
+    bool is_visible) {
+  if (host_->is_hidden() ||
+      (cursor_visibility_state_in_renderer_ == VISIBLE && is_visible) ||
+      (cursor_visibility_state_in_renderer_ == NOT_VISIBLE && !is_visible))
+    return;
+
+  cursor_visibility_state_in_renderer_ = is_visible ? VISIBLE : NOT_VISIBLE;
+  host_->SendCursorVisibilityState(is_visible);
+}
+
 void RenderWidgetHostViewAura::SchedulePaintIfNotInClip(
     const gfx::Rect& rect,
     const gfx::Rect& clip) {
@@ -2616,7 +2875,7 @@
       global_mouse_position_.y() > rect.bottom() - border_y;
 }
 
-void RenderWidgetHostViewAura::RunCompositingDidCommitCallbacks() {
+void RenderWidgetHostViewAura::RunOnCommitCallbacks() {
   for (std::vector<base::Closure>::const_iterator
       it = on_compositing_did_commit_callbacks_.begin();
       it != on_compositing_did_commit_callbacks_.end(); ++it) {
@@ -2625,15 +2884,39 @@
   on_compositing_did_commit_callbacks_.clear();
 }
 
+void RenderWidgetHostViewAura::AddOnCommitCallbackAndDisableLocks(
+    const base::Closure& callback) {
+  ui::Compositor* compositor = GetCompositor();
+  DCHECK(compositor);
+
+  if (!compositor->HasObserver(this))
+    compositor->AddObserver(this);
+
+  can_lock_compositor_ = NO_PENDING_COMMIT;
+  on_compositing_did_commit_callbacks_.push_back(callback);
+}
+
 void RenderWidgetHostViewAura::AddedToRootWindow() {
   window_->GetRootWindow()->AddRootWindowObserver(this);
   host_->ParentChanged(GetNativeViewId());
   UpdateScreenInfo(window_);
   if (popup_type_ != WebKit::WebPopupTypeNone)
     event_filter_for_popup_exit_.reset(new EventFilterForPopupExit(this));
+
+  aura::client::CursorClient* cursor_client =
+      aura::client::GetCursorClient(window_->GetRootWindow());
+  if (cursor_client) {
+    cursor_client->AddObserver(this);
+    NotifyRendererOfCursorVisibilityState(cursor_client->IsCursorVisible());
+  }
 }
 
 void RenderWidgetHostViewAura::RemovingFromRootWindow() {
+  aura::client::CursorClient* cursor_client =
+      aura::client::GetCursorClient(window_->GetRootWindow());
+  if (cursor_client)
+    cursor_client->RemoveObserver(this);
+
   event_filter_for_popup_exit_.reset();
   window_->GetRootWindow()->RemoveRootWindowObserver(this);
   host_->ParentChanged(0);
@@ -2644,11 +2927,11 @@
   // frame though, because we will reissue a new frame right away without that
   // composited data.
   ui::Compositor* compositor = GetCompositor();
-  RunCompositingDidCommitCallbacks();
-  locks_pending_commit_.clear();
+  RunOnCommitCallbacks();
+  resize_lock_.reset();
+  host_->WasResized();
   if (compositor && compositor->HasObserver(this))
     compositor->RemoveObserver(this);
-  DetachFromInputMethod();
 }
 
 ui::Compositor* RenderWidgetHostViewAura::GetCompositor() {
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.h b/content/browser/renderer_host/render_widget_host_view_aura.h
index 52c6376..b1e3a7e 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura.h
+++ b/content/browser/renderer_host/render_widget_host_view_aura.h
@@ -22,6 +22,7 @@
 #include "third_party/skia/include/core/SkRegion.h"
 #include "ui/aura/client/activation_change_observer.h"
 #include "ui/aura/client/activation_delegate.h"
+#include "ui/aura/client/cursor_client_observer.h"
 #include "ui/aura/client/focus_change_observer.h"
 #include "ui/aura/root_window_observer.h"
 #include "ui/aura/window_delegate.h"
@@ -66,6 +67,7 @@
       public aura::client::ActivationDelegate,
       public aura::client::ActivationChangeObserver,
       public aura::client::FocusChangeObserver,
+      public aura::client::CursorClientObserver,
       public ImageTransportFactoryObserver,
       public BrowserAccessibilityDelegate,
       public base::SupportsWeakPtr<RenderWidgetHostViewAura> {
@@ -93,10 +95,47 @@
     virtual void OnViewDestroyed() = 0;
   };
 
+  // Displays and controls touch editing elements such as selection handles.
+  class TouchEditingClient {
+   public:
+    TouchEditingClient() {}
+
+    // Tells the client to start showing touch editing handles.
+    virtual void StartTouchEditing() = 0;
+
+    // Notifies the client that touch editing is no longer needed.
+    virtual void EndTouchEditing() = 0;
+
+    // Notifies the client that the selection bounds need to be updated.
+    virtual void OnSelectionOrCursorChanged(const gfx::Rect& anchor,
+                                            const gfx::Rect& focus) = 0;
+
+    // Notifies the client that the current text input type as changed.
+    virtual void OnTextInputTypeChanged(ui::TextInputType type) = 0;
+
+    // Notifies the client that an input event is about to be sent to the
+    // renderer. Returns true if the client wants to stop event propagation.
+    virtual bool HandleInputEvent(const ui::Event* event) = 0;
+
+    // Notifies the client that a gesture event ack was received.
+    virtual void GestureEventAck(int gesture_event_type) = 0;
+
+    // This is called when the view is destroyed, so that the client can
+    // perform any necessary clean-up.
+    virtual void OnViewDestroyed() = 0;
+
+   protected:
+    virtual ~TouchEditingClient() {}
+  };
+
   void set_paint_observer(PaintObserver* observer) {
     paint_observer_ = observer;
   }
 
+  void set_touch_editing_client(TouchEditingClient* client) {
+    touch_editing_client_ = client;
+  }
+
   // RenderWidgetHostView implementation.
   virtual void InitAsChild(gfx::NativeView parent_view) OVERRIDE;
   virtual RenderWidgetHost* GetRenderWidgetHost() const OVERRIDE;
@@ -113,8 +152,8 @@
   virtual gfx::Rect GetViewBounds() const OVERRIDE;
   virtual void SetBackground(const SkBitmap& background) OVERRIDE;
 #if defined(OS_WIN)
-  virtual void SetParentNativeViewAccessible(
-      gfx::NativeViewAccessible accessible_parent) OVERRIDE;
+  virtual gfx::NativeViewAccessible AccessibleObjectFromChildId(long child_id)
+      OVERRIDE;
 #endif
 
   // Overridden from RenderWidgetHostViewPort:
@@ -161,6 +200,10 @@
       const scoped_refptr<media::VideoFrame>& target,
       const base::Callback<void(bool)>& callback) OVERRIDE;
   virtual bool CanCopyToVideoFrame() const OVERRIDE;
+  virtual bool CanSubscribeFrame() const OVERRIDE;
+  virtual void BeginFrameSubscription(
+      scoped_ptr<RenderWidgetHostViewFrameSubscriber> subscriber) OVERRIDE;
+  virtual void EndFrameSubscription() OVERRIDE;
   virtual void OnAcceleratedCompositingStateChange() OVERRIDE;
   virtual void AcceleratedSurfaceBuffersSwapped(
       const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params_in_pixel,
@@ -173,6 +216,7 @@
   virtual bool HasAcceleratedSurface(const gfx::Size& desired_size) OVERRIDE;
   virtual void GetScreenInfo(WebKit::WebScreenInfo* results) OVERRIDE;
   virtual gfx::Rect GetBoundsInRootWindow() OVERRIDE;
+  virtual void GestureEventAck(int gesture_event_type) OVERRIDE;
   virtual void ProcessAckedTouchEvent(
       const WebKit::WebTouchEvent& touch,
       InputEventAckState ack_result) OVERRIDE;
@@ -213,6 +257,7 @@
   virtual bool ChangeTextDirectionAndLayoutAlignment(
       base::i18n::TextDirection direction) OVERRIDE;
   virtual void ExtendSelectionAndDelete(size_t before, size_t after) OVERRIDE;
+  virtual void EnsureCaretInRect(const gfx::Rect& rect) OVERRIDE;
 
   // Overridden from gfx::DisplayObserver:
   virtual void OnDisplayBoundsChanged(const gfx::Display& display) OVERRIDE;
@@ -254,6 +299,9 @@
   virtual void OnWindowActivated(aura::Window* gained_activation,
                                  aura::Window* lost_activation) OVERRIDE;
 
+  // Overridden from aura::client::CursorClientObserver:
+  virtual void OnCursorVisibilityChanged(bool is_visible) OVERRIDE;
+
   // Overridden from aura::client::FocusChangeObserver:
   virtual void OnWindowFocused(aura::Window* gained_focus,
                                aura::Window* lost_focus) OVERRIDE;
@@ -275,6 +323,10 @@
   // Should construct only via RenderWidgetHostView::CreateViewForWidget.
   explicit RenderWidgetHostViewAura(RenderWidgetHost* host);
 
+  RenderWidgetHostViewFrameSubscriber* frame_subscriber() const {
+    return frame_subscriber_.get();
+  }
+
  private:
   FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraTest, TouchEventState);
   FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraTest, TouchEventSyncAsync);
@@ -316,8 +368,15 @@
   virtual ~RenderWidgetHostViewAura();
 
   void UpdateCursorIfOverSelf();
-  bool ShouldSkipFrame(gfx::Size size_in_dip);
-  void CheckResizeLocks(gfx::Size size_in_dip);
+  bool ShouldSkipFrame(gfx::Size size_in_dip) const;
+
+  // Lazily grab a resize lock if the aura window size doesn't match the current
+  // frame size, to give time to the renderer.
+  void MaybeCreateResizeLock();
+
+  // Checks if the resize lock can be released because we received an new frame.
+  void CheckResizeLock();
+
   void UpdateExternalTexture();
   ui::InputMethod* GetInputMethod() const;
 
@@ -332,6 +391,10 @@
   // mouse lock on all mouse move events.
   void ModifyEventMovementAndCoords(WebKit::WebMouseEvent* event);
 
+  // Sends an IPC to the renderer process to communicate whether or not
+  // the mouse cursor is visible anywhere on the screen.
+  void NotifyRendererOfCursorVisibilityState(bool is_visible);
+
   // If |clip| is non-empty and and doesn't contain |rect| or |clip| is empty
   // SchedulePaint() is invoked for |rect|.
   void SchedulePaintIfNotInClip(const gfx::Rect& rect, const gfx::Rect& clip);
@@ -340,8 +403,11 @@
   // moved to center.
   bool ShouldMoveToCenter();
 
-  // Run the compositing callbacks.
-  void RunCompositingDidCommitCallbacks();
+  // Run all on compositing commit callbacks.
+  void RunOnCommitCallbacks();
+
+  // Add on compositing commit callback.
+  void AddOnCommitCallbackAndDisableLocks(const base::Closure& callback);
 
   // Called after |window_| is parented to a RootWindow.
   void AddedToRootWindow();
@@ -372,6 +438,9 @@
   // Converts |rect| from window coordinate to screen coordinate.
   gfx::Rect ConvertRectToScreen(const gfx::Rect& rect);
 
+  // Converts |rect| from screen coordinate to window coordinate.
+  gfx::Rect ConvertRectFromScreen(const gfx::Rect& rect);
+
   typedef base::Callback<void(bool, const scoped_refptr<ui::Texture>&)>
       BufferPresentedCallback;
 
@@ -391,10 +460,15 @@
       const scoped_refptr<ui::Texture>& texture_to_return);
 
   void SwapDelegatedFrame(
-      scoped_ptr<cc::DelegatedFrameData> frame,
-      float device_scale_factor);
+      scoped_ptr<cc::DelegatedFrameData> frame_data,
+      float frame_device_scale_factor);
   void SendDelegatedFrameAck();
 
+  void SwapSoftwareFrame(
+      scoped_ptr<cc::SoftwareFrameData> frame_data,
+      float frame_device_scale_factor);
+  void SendSoftwareFrameAck(const TransportDIB::Id& id);
+
   BrowserAccessibilityManager* GetOrCreateBrowserAccessibilityManager();
 
 #if defined(OS_WIN)
@@ -471,6 +545,13 @@
   // The current frontbuffer texture.
   scoped_refptr<ui::Texture> current_surface_;
 
+  // The current frontbuffer DIB.
+  scoped_ptr<TransportDIB> current_dib_;
+
+  // The current DIB id as it was received from the renderer. Note that on
+  // some platforms (e.g. Windows) this is different from current_dib_->id().
+  TransportDIB::Id current_dib_id_;
+
   // The damage in the previously presented buffer.
   SkRegion previous_damage_;
 
@@ -511,13 +592,17 @@
 
   // Used to prevent further resizes while a resize is pending.
   class ResizeLock;
-  typedef std::vector<linked_ptr<ResizeLock> > ResizeLockList;
 
-  // These locks are the ones waiting for a texture of the right size to come
-  // back from the renderer/GPU process.
-  ResizeLockList resize_locks_;
-  // These locks are the ones waiting for a frame to be committed.
-  ResizeLockList locks_pending_commit_;
+  // This lock is the one waiting for a frame of the right size to come back
+  // from the renderer/GPU process. It is set from the moment the aura window
+  // got resized, to the moment we committed the renderer frame of the same
+  // size. It keeps track of the size we expect from the renderer, and locks the
+  // compositor, as well as the UI for a short time to give a chance to the
+  // renderer of producing a frame of the right size.
+  scoped_ptr<ResizeLock> resize_lock_;
+
+  // Keeps track of the current frame size.
+  gfx::Size current_frame_size_;
 
   // This lock is for waiting for a front surface to become available to draw.
   scoped_refptr<ui::CompositorLock> released_front_lock_;
@@ -537,6 +622,15 @@
   };
   CanLockCompositorState can_lock_compositor_;
 
+  // Used to track the last cursor visibility update that was sent to the
+  // renderer via NotifyRendererOfCursorVisibilityState().
+  enum CursorVisibilityState {
+    UNKNOWN,
+    VISIBLE,
+    NOT_VISIBLE,
+  };
+  CursorVisibilityState cursor_visibility_state_in_renderer_;
+
   // An observer to notify that the paint content of the view has changed. The
   // observer is not owned by the view, and must remove itself as an oberver
   // when it is being destroyed.
@@ -560,7 +654,10 @@
 
   base::TimeTicks last_draw_ended_;
 
-  gfx::NativeViewAccessible accessible_parent_;
+  // Subscriber that listens to frame presentation events.
+  scoped_ptr<RenderWidgetHostViewFrameSubscriber> frame_subscriber_;
+
+  TouchEditingClient* touch_editing_client_;
 
   DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewAura);
 };
diff --git a/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc b/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
index cfacd0c..9ad65fc 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
+++ b/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
@@ -110,7 +110,7 @@
   }
 
  protected:
-  MessageLoopForUI message_loop_;
+  base::MessageLoopForUI message_loop_;
   scoped_ptr<aura::test::AuraTestHelper> aura_test_helper_;
   scoped_ptr<BrowserContext> browser_context_;
   MockRenderWidgetHostDelegate delegate_;
diff --git a/content/browser/renderer_host/render_widget_host_view_base.cc b/content/browser/renderer_host/render_widget_host_view_base.cc
index 0efb448..43d496b 100644
--- a/content/browser/renderer_host/render_widget_host_view_base.cc
+++ b/content/browser/renderer_host/render_widget_host_view_base.cc
@@ -84,7 +84,7 @@
     // it's most likely the one for this plugin, try a few more times after a
     // delay.
     if (tries > 0) {
-      MessageLoop::current()->PostDelayedTask(
+      base::MessageLoop::current()->PostDelayedTask(
           FROM_HERE,
           base::Bind(&NotifyPluginProcessHostHelper, window, parent, tries - 1),
           base::TimeDelta::FromMilliseconds(kTryDelayMs));
@@ -422,6 +422,9 @@
   return INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
 }
 
+void RenderWidgetHostViewBase::GestureEventAck(int gesture_event_type) {
+}
+
 void RenderWidgetHostViewBase::SetPopupType(WebKit::WebPopupType popup_type) {
   popup_type_ = popup_type;
 }
diff --git a/content/browser/renderer_host/render_widget_host_view_base.h b/content/browser/renderer_host/render_widget_host_view_base.h
index ae58a59..662dbab 100644
--- a/content/browser/renderer_host/render_widget_host_view_base.h
+++ b/content/browser/renderer_host/render_widget_host_view_base.h
@@ -61,6 +61,7 @@
       const WebKit::WebMouseWheelEvent& event) OVERRIDE;
   virtual InputEventAckState FilterInputEvent(
       const WebKit::WebInputEvent& input_event) OVERRIDE;
+  virtual void GestureEventAck(int gesture_event_type) OVERRIDE;
   virtual void SetPopupType(WebKit::WebPopupType popup_type) OVERRIDE;
   virtual WebKit::WebPopupType GetPopupType() OVERRIDE;
   virtual BrowserAccessibilityManager*
diff --git a/content/browser/renderer_host/render_widget_host_view_browsertest.cc b/content/browser/renderer_host/render_widget_host_view_browsertest.cc
index d158e6f..45cdd4b 100644
--- a/content/browser/renderer_host/render_widget_host_view_browsertest.cc
+++ b/content/browser/renderer_host/render_widget_host_view_browsertest.cc
@@ -77,7 +77,7 @@
     // not be available immediately so wait for it.
     while (!CheckCompositingSurface()) {
       base::RunLoop run_loop;
-      MessageLoop::current()->PostDelayedTask(
+      base::MessageLoop::current()->PostDelayedTask(
           FROM_HERE,
           run_loop.QuitClosure(),
           base::TimeDelta::FromMilliseconds(10));
@@ -126,10 +126,19 @@
   }
 
   virtual bool ShouldCaptureFrame(
+      base::Time present_time,
       scoped_refptr<media::VideoFrame>* storage,
       DeliverFrameCallback* callback) OVERRIDE {
+    // Only allow one frame capture to be made.  Otherwise, the compositor could
+    // start multiple captures, unbounded, and eventually its own limiter logic
+    // will begin invoking |callback| with a |false| result.  This flakes out
+    // the unit tests, since they receive a "failed" callback before the later
+    // "success" callbacks.
+    if (callback_.is_null())
+      return false;
     *storage = media::VideoFrame::CreateBlackFrame(gfx::Size(100, 100));
     *callback = callback_;
+    callback_.Reset();
     return true;
   }
 
@@ -247,8 +256,14 @@
 }
 
 // Test copying from backing store when page is non-accelerated-composited.
+// Flaky. http://crbug.com/224351
+#if defined(OS_MACOSX) || defined(OS_WIN)
+#define MAYBE_CopyFromBackingStore DISABLED_CopyFromBackingStore
+#else
+#define MAYBE_CopyFromBackingStore CopyFromBackingStore
+#endif
 IN_PROC_BROWSER_TEST_F(RenderWidgetHostViewBrowserTest,
-                       CopyFromBackingStore) {
+                       MAYBE_CopyFromBackingStore) {
   SetupNonCompositing();
   base::RunLoop run_loop;
 
diff --git a/content/browser/renderer_host/render_widget_host_view_gtk.cc b/content/browser/renderer_host/render_widget_host_view_gtk.cc
index c137096..ece0421 100644
--- a/content/browser/renderer_host/render_widget_host_view_gtk.cc
+++ b/content/browser/renderer_host/render_widget_host_view_gtk.cc
@@ -4,11 +4,6 @@
 
 #include "content/browser/renderer_host/render_widget_host_view_gtk.h"
 
-// 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 net::URLRequestStatus::Status.
-#include "content/common/view_messages.h"
-
 #include <cairo/cairo.h>
 #include <gdk/gdk.h>
 #include <gdk/gdkkeysyms.h>
@@ -37,6 +32,8 @@
 #include "content/browser/renderer_host/render_view_host_delegate.h"
 #include "content/browser/renderer_host/render_view_host_impl.h"
 #include "content/common/gpu/gpu_messages.h"
+#include "content/common/input_messages.h"
+#include "content/common/view_messages.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/native_web_keyboard_event.h"
 #include "content/public/common/content_switches.h"
@@ -712,6 +709,8 @@
   // If we have a renderer, then inform it that we are being hidden so it can
   // reduce its resource utilization.
   host_->WasHidden();
+
+  web_contents_switch_paint_time_ = base::TimeTicks();
 }
 
 void RenderWidgetHostViewGtk::SetSize(const gfx::Size& size) {
@@ -929,7 +928,7 @@
   // The RenderWidgetHost's destruction led here, so don't call it.
   host_ = NULL;
 
-  MessageLoop::current()->DeleteSoon(FROM_HERE, this);
+  base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
 }
 
 void RenderWidgetHostViewGtk::SetTooltipText(const string16& tooltip_text) {
@@ -1369,7 +1368,7 @@
   EditCommands edit_commands;
   if (!event.skip_in_browser &&
       key_bindings_handler_->Match(event, &edit_commands)) {
-    Send(new ViewMsg_SetEditCommandsForNextKeyEvent(
+    Send(new InputMsg_SetEditCommandsForNextKeyEvent(
         host_->GetRoutingID(), edit_commands));
     NativeWebKeyboardEvent copy_event(event);
     copy_event.match_edit_command = true;
@@ -1545,7 +1544,7 @@
 
 void RenderWidgetHostViewGtk::OnAccessibilityNotifications(
     const std::vector<AccessibilityHostMsg_NotificationParams>& params) {
-  if (!browser_accessibility_manager_.get()) {
+  if (!browser_accessibility_manager_) {
     GtkWidget* parent = gtk_widget_get_parent(view_.get());
     browser_accessibility_manager_.reset(
         new BrowserAccessibilityManagerGtk(
@@ -1557,7 +1556,7 @@
 }
 
 AtkObject* RenderWidgetHostViewGtk::GetAccessible() {
-  if (!browser_accessibility_manager_.get()) {
+  if (!browser_accessibility_manager_) {
     GtkWidget* parent = gtk_widget_get_parent(view_.get());
     browser_accessibility_manager_.reset(
         new BrowserAccessibilityManagerGtk(
diff --git a/content/browser/renderer_host/render_widget_host_view_guest.cc b/content/browser/renderer_host/render_widget_host_view_guest.cc
index 5e414cb..6f02367 100644
--- a/content/browser/renderer_host/render_widget_host_view_guest.cc
+++ b/content/browser/renderer_host/render_widget_host_view_guest.cc
@@ -76,11 +76,12 @@
 }
 
 void RenderWidgetHostViewGuest::SetSize(const gfx::Size& size) {
-  platform_view_->SetSize(size);
+  size_ = size;
+  host_->WasResized();
 }
 
 gfx::Rect RenderWidgetHostViewGuest::GetBoundsInRootWindow() {
-  return platform_view_->GetBoundsInRootWindow();
+  return gfx::Rect(size_);
 }
 
 gfx::GLSurfaceHandle RenderWidgetHostViewGuest::GetCompositingSurface() {
@@ -124,7 +125,7 @@
 }
 
 gfx::Rect RenderWidgetHostViewGuest::GetViewBounds() const {
-  return platform_view_->GetViewBounds();
+  return gfx::Rect(size_);
 }
 
 void RenderWidgetHostViewGuest::RenderViewGone(base::TerminationStatus status,
@@ -166,8 +167,19 @@
   NOTREACHED();
 }
 
+void RenderWidgetHostViewGuest::OnSwapCompositorFrame(
+    scoped_ptr<cc::CompositorFrame> frame) {
+  guest_->clear_damage_buffer();
+  guest_->SendMessageToEmbedder(
+      new BrowserPluginMsg_CompositorFrameSwapped(
+          guest_->instance_id(),
+          *frame,
+          host_->GetRoutingID(),
+          host_->GetProcess()->GetID()));
+}
+
 void RenderWidgetHostViewGuest::SetBounds(const gfx::Rect& rect) {
-  platform_view_->SetBounds(rect);
+  SetSize(rect.size());
 }
 
 bool RenderWidgetHostViewGuest::OnMessageReceived(const IPC::Message& msg) {
@@ -308,8 +320,10 @@
 #endif
 
 #if defined(OS_WIN) && defined(USE_AURA)
-void RenderWidgetHostViewGuest::SetParentNativeViewAccessible(
-    gfx::NativeViewAccessible accessible_parent) {
+gfx::NativeViewAccessible
+RenderWidgetHostViewGuest::AccessibleObjectFromChildId(long child_id) {
+  NOTIMPLEMENTED();
+  return NULL;
 }
 #endif
 
@@ -336,7 +350,10 @@
 }
 
 void RenderWidgetHostViewGuest::GetScreenInfo(WebKit::WebScreenInfo* results) {
-  platform_view_->GetScreenInfo(results);
+  RenderWidgetHostViewPort* embedder_view =
+      static_cast<RenderWidgetHostViewPort*>(
+          guest_->GetEmbedderRenderWidgetHostView());
+  embedder_view->GetScreenInfo(results);
 }
 
 void RenderWidgetHostViewGuest::OnAccessibilityNotifications(
@@ -397,16 +414,6 @@
     const SkBitmap& zoomed_bitmap) {
 }
 
-void RenderWidgetHostViewGuest::UpdateFrameInfo(
-    const gfx::Vector2dF& scroll_offset,
-    float page_scale_factor,
-    const gfx::Vector2dF& page_scale_factor_limits,
-    const gfx::SizeF& content_size,
-    const gfx::SizeF& viewport_size,
-    const gfx::Vector2dF& controls_offset,
-    const gfx::Vector2dF& content_offset) {
-}
-
 void RenderWidgetHostViewGuest::HasTouchEventHandlers(bool need_touch_events) {
 }
 #endif  // defined(OS_ANDROID)
@@ -428,7 +435,7 @@
 
 void RenderWidgetHostViewGuest::DestroyGuestView() {
   host_ = NULL;
-  MessageLoop::current()->DeleteSoon(FROM_HERE, this);
+  base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
 }
 
 bool RenderWidgetHostViewGuest::DispatchLongPressGestureEvent(
diff --git a/content/browser/renderer_host/render_widget_host_view_guest.h b/content/browser/renderer_host/render_widget_host_view_guest.h
index a0949a7..b1c2816 100644
--- a/content/browser/renderer_host/render_widget_host_view_guest.h
+++ b/content/browser/renderer_host/render_widget_host_view_guest.h
@@ -66,8 +66,8 @@
   virtual void SetClickthroughRegion(SkRegion* region) OVERRIDE;
 #endif
 #if defined(OS_WIN) && defined(USE_AURA)
-  virtual void SetParentNativeViewAccessible(
-      gfx::NativeViewAccessible accessible_parent) OVERRIDE;
+  virtual gfx::NativeViewAccessible AccessibleObjectFromChildId(long child_id)
+      OVERRIDE;
 #endif
 
   // RenderWidgetHostViewPort implementation.
@@ -119,6 +119,8 @@
   virtual void AcceleratedSurfacePostSubBuffer(
       const GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params& params,
       int gpu_host_id) OVERRIDE;
+  virtual void OnSwapCompositorFrame(
+      scoped_ptr<cc::CompositorFrame> frame) OVERRIDE;
   virtual void AcceleratedSurfaceSuspend() OVERRIDE;
   virtual void AcceleratedSurfaceRelease() OVERRIDE;
   virtual bool HasAcceleratedSurface(const gfx::Size& desired_size) OVERRIDE;
@@ -161,13 +163,6 @@
   // RenderWidgetHostViewPort implementation.
   virtual void ShowDisambiguationPopup(const gfx::Rect& target_rect,
                                        const SkBitmap& zoomed_bitmap) OVERRIDE;
-  virtual void UpdateFrameInfo(const gfx::Vector2dF& scroll_offset,
-                               float page_scale_factor,
-                               const gfx::Vector2dF& page_scale_factor_limits,
-                               const gfx::SizeF& content_size,
-                               const gfx::SizeF& viewport_size,
-                               const gfx::Vector2dF& controls_offset,
-                               const gfx::Vector2dF& content_offset) OVERRIDE;
   virtual void HasTouchEventHandlers(bool need_touch_events) OVERRIDE;
 #endif  // defined(OS_ANDROID)
 
@@ -202,6 +197,7 @@
 
   BrowserPluginGuest *guest_;
   bool is_hidden_;
+  gfx::Size size_;
   // The platform view for this RenderWidgetHostView.
   // RenderWidgetHostViewGuest mostly only cares about stuff related to
   // compositing, the rest are directly forwared to this |platform_view_|.
diff --git a/content/browser/renderer_host/render_widget_host_view_guest_unittest.cc b/content/browser/renderer_host/render_widget_host_view_guest_unittest.cc
index fbe45b7..5cac690 100644
--- a/content/browser/renderer_host/render_widget_host_view_guest_unittest.cc
+++ b/content/browser/renderer_host/render_widget_host_view_guest_unittest.cc
@@ -51,7 +51,7 @@
   }
 
  protected:
-  MessageLoopForUI message_loop_;
+  base::MessageLoopForUI message_loop_;
   scoped_ptr<BrowserContext> browser_context_;
   MockRenderWidgetHostDelegate delegate_;
 
diff --git a/content/browser/renderer_host/render_widget_host_view_mac.h b/content/browser/renderer_host/render_widget_host_view_mac.h
index a02f379..a38cd47 100644
--- a/content/browser/renderer_host/render_widget_host_view_mac.h
+++ b/content/browser/renderer_host/render_widget_host_view_mac.h
@@ -408,6 +408,8 @@
     return frame_subscriber_.get();
   }
 
+  int window_number() const;
+
  private:
   friend class RenderWidgetHostView;
   friend class RenderWidgetHostViewMacTest;
diff --git a/content/browser/renderer_host/render_widget_host_view_mac.mm b/content/browser/renderer_host/render_widget_host_view_mac.mm
index e13bbdf..2a72354 100644
--- a/content/browser/renderer_host/render_widget_host_view_mac.mm
+++ b/content/browser/renderer_host/render_widget_host_view_mac.mm
@@ -16,10 +16,10 @@
 #import "base/memory/scoped_nsobject.h"
 #include "base/message_loop.h"
 #include "base/metrics/histogram.h"
-#include "base/stringprintf.h"
 #include "base/string_util.h"
+#include "base/stringprintf.h"
+#include "base/strings/sys_string_conversions.h"
 #include "base/sys_info.h"
-#include "base/sys_string_conversions.h"
 #include "base/utf_string_conversions.h"
 #import "content/browser/accessibility/browser_accessibility_cocoa.h"
 #include "content/browser/accessibility/browser_accessibility_manager_mac.h"
@@ -32,6 +32,7 @@
 #include "content/common/accessibility_messages.h"
 #include "content/common/edit_command.h"
 #include "content/common/gpu/gpu_messages.h"
+#include "content/common/input_messages.h"
 #include "content/common/plugin_messages.h"
 #include "content/common/view_messages.h"
 #include "content/port/browser/render_widget_host_view_frame_subscriber.h"
@@ -50,8 +51,8 @@
 #include "ui/base/layout.h"
 #include "ui/gfx/point.h"
 #include "ui/gfx/rect_conversions.h"
-#include "ui/gfx/size_conversions.h"
 #include "ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h"
+#include "ui/gfx/size_conversions.h"
 #include "ui/surface/io_surface_support_mac.h"
 #include "webkit/plugins/npapi/webplugin.h"
 
@@ -133,10 +134,11 @@
 @interface RenderWidgetHostViewCocoa ()
 @property(nonatomic, assign) NSRange selectedRange;
 @property(nonatomic, assign) NSRange markedRange;
+@property(nonatomic, assign)
+    NSObject<RenderWidgetHostViewMacDelegate>* delegate;
 
 + (BOOL)shouldAutohideCursorForEvent:(NSEvent*)event;
 - (id)initWithRenderWidgetHostViewMac:(RenderWidgetHostViewMac*)r;
-- (void)setRWHVDelegate:(NSObject<RenderWidgetHostViewMacDelegate>*)delegate;
 - (void)gotUnhandledWheelEvent;
 - (void)scrollOffsetPinnedToLeft:(BOOL)left toRight:(BOOL)right;
 - (void)setHasHorizontalScrollbar:(BOOL)has_horizontal_scrollbar;
@@ -389,7 +391,7 @@
 
 void RenderWidgetHostViewMac::SetDelegate(
     NSObject<RenderWidgetHostViewMacDelegate>* delegate) {
-  [cocoa_view_ setRWHVDelegate:delegate];
+  [cocoa_view_ setDelegate:delegate];
 }
 
 void RenderWidgetHostViewMac::SetAllowOverlappingViews(bool overlapping) {
@@ -471,6 +473,10 @@
   [cocoa_view_ setCanBeKeyView:YES];
   [cocoa_view_ setFrame:[[pepper_fullscreen_window_ contentView] bounds]];
   [cocoa_view_ setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
+  // If the pepper fullscreen window isn't opaque then there are performance
+  // issues when it's on the discrete GPU and the Chrome window is being drawn
+  // to. http://crbug.com/171911
+  [pepper_fullscreen_window_ setOpaque:YES];
 
   // Note that this forms a reference cycle between the fullscreen window and
   // the rwhvmac: The PepperFlashFullscreenWindow retains cocoa_view_,
@@ -500,6 +506,13 @@
   pepper_fullscreen_window_.reset();
 }
 
+int RenderWidgetHostViewMac::window_number() const {
+  NSWindow* window = [cocoa_view_ window];
+  if (!window)
+    return -1;
+  return [window windowNumber];
+}
+
 RenderWidgetHost* RenderWidgetHostViewMac::GetRenderWidgetHost() const {
   return render_widget_host_;
 }
@@ -890,7 +903,7 @@
                                       location:location
                                  modifierFlags:0
                                      timestamp:0
-                                  windowNumber:[window windowNumber]
+                                  windowNumber:window_number()
                                        context:nil
                                    eventNumber:0
                                     clickCount:0
@@ -1004,7 +1017,7 @@
 void RenderWidgetHostViewMac::KillSelf() {
   if (!weak_factory_.HasWeakPtrs()) {
     [cocoa_view_ setHidden:YES];
-    MessageLoop::current()->PostTask(FROM_HERE,
+    base::MessageLoop::current()->PostTask(FROM_HERE,
         base::Bind(&RenderWidgetHostViewMac::ShutdownHost,
                    weak_factory_.GetWeakPtr()));
   }
@@ -1036,14 +1049,30 @@
   if (is_hidden_)
     return true;
 
-  // TODO(shess) If the view does not have a window, or the window
-  // does not have backing, the IOSurface will log "invalid drawable"
-  // in -setView:.  It is not clear how this code is reached with such
-  // a case, so record some info into breakpad (some subset of
-  // browsers are likely to crash later for unrelated reasons).
-  // http://crbug.com/148882
   NSWindow* window = [cocoa_view_ window];
-  if ([window windowNumber] <= 0) {
+  if (window_number() <= 0) {
+    // There is no window to present so capturing during present won't work.
+    // We check if frame subscriber wants this frame and capture manually.
+    if (compositing_iosurface_.get() && frame_subscriber_) {
+      const base::Time present_time = base::Time::Now();
+      scoped_refptr<media::VideoFrame> frame;
+      RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback callback;
+      if (frame_subscriber_->ShouldCaptureFrame(present_time,
+                                                &frame, &callback)) {
+        compositing_iosurface_->SetIOSurface(surface_handle, size);
+        compositing_iosurface_->CopyToVideoFrame(
+            gfx::Rect(size), ScaleFactor(cocoa_view_), frame,
+            base::Bind(callback, present_time));
+        return true;
+      }
+    }
+
+    // TODO(shess) If the view does not have a window, or the window
+    // does not have backing, the IOSurface will log "invalid drawable"
+    // in -setView:.  It is not clear how this code is reached with such
+    // a case, so record some info into breakpad (some subset of
+    // browsers are likely to crash later for unrelated reasons).
+    // http://crbug.com/148882
     const char* const kCrashKey = "rwhvm_window";
     if (!window) {
       base::debug::SetCrashKeyValue(kCrashKey, "Missing window");
@@ -1059,14 +1088,17 @@
     return true;
   }
 
-  if (!compositing_iosurface_.get()) {
+  bool should_post_notification = false;
+  if (!compositing_iosurface_) {
     CompositingIOSurfaceMac::SurfaceOrder order = allow_overlapping_views_ ?
         CompositingIOSurfaceMac::SURFACE_ORDER_BELOW_WINDOW :
         CompositingIOSurfaceMac::SURFACE_ORDER_ABOVE_WINDOW;
-    compositing_iosurface_.reset(CompositingIOSurfaceMac::Create(order));
+    compositing_iosurface_.reset(
+        CompositingIOSurfaceMac::Create(window_number(), order));
+    should_post_notification = true;
   }
 
-  if (!compositing_iosurface_.get())
+  if (!compositing_iosurface_)
     return true;
 
   compositing_iosurface_->SetIOSurface(surface_handle, size);
@@ -1085,8 +1117,15 @@
   if (!about_to_validate_and_paint_) {
     compositing_iosurface_->DrawIOSurface(cocoa_view_,
                                           ScaleFactor(cocoa_view_),
+                                          window_number(),
                                           frame_subscriber_.get());
   }
+
+  if (should_post_notification && [[cocoa_view_ delegate]
+          respondsToSelector:@selector(compositingIOSurfaceCreated)]) {
+    [[cocoa_view_ delegate] compositingIOSurfaceCreated];
+  }
+
   return true;
 }
 
@@ -1096,7 +1135,7 @@
     if (pending_swap_buffers_acks_.front().first != 0) {
       AcceleratedSurfaceMsg_BufferPresented_Params ack_params;
       ack_params.sync_point = 0;
-      if (compositing_iosurface_.get())
+      if (compositing_iosurface_)
         ack_params.renderer_id = compositing_iosurface_->GetRendererID();
       RenderWidgetHostImpl::AcknowledgeBufferPresent(
           pending_swap_buffers_acks_.front().first,
@@ -1106,7 +1145,7 @@
         render_widget_host_->AcknowledgeSwapBuffersToRenderer();
 
         // Send VSync parameters to compositor thread.
-        if (compositing_iosurface_.get()) {
+        if (compositing_iosurface_) {
           base::TimeTicks timebase;
           uint32 numerator = 0, denominator = 0;
           compositing_iosurface_->GetVSyncParameters(&timebase,
@@ -1279,7 +1318,7 @@
 }
 
 void RenderWidgetHostViewMac::AcceleratedSurfaceSuspend() {
-  if (compositing_iosurface_.get())
+  if (compositing_iosurface_)
     compositing_iosurface_->UnrefIOSurface();
 }
 
@@ -1406,7 +1445,7 @@
     // Forget IOSurface since we are drawing a software frame now.
     if (compositing_iosurface_.get() &&
         compositing_iosurface_->HasIOSurface()) {
-      compositing_iosurface_->UnrefIOSurface();
+      compositing_iosurface_->ClearDrawable();
     }
   }
 }
@@ -1538,6 +1577,7 @@
 @synthesize selectedRange = selectedRange_;
 @synthesize suppressNextEscapeKeyUp = suppressNextEscapeKeyUp_;
 @synthesize markedRange = markedRange_;
+@synthesize delegate = delegate_;
 
 - (id)initWithRenderWidgetHostViewMac:(RenderWidgetHostViewMac*)r {
   self = [super initWithFrame:NSZeroRect];
@@ -1580,10 +1620,6 @@
   }
 }
 
-- (void)setRWHVDelegate:(NSObject<RenderWidgetHostViewMacDelegate>*)delegate {
-  delegate_ = delegate;
-}
-
 - (void)gotUnhandledWheelEvent {
   if (delegate_ &&
       [delegate_ respondsToSelector:@selector(gotUnhandledWheelEvent)]) {
@@ -1916,7 +1952,7 @@
       delayEventUntilAfterImeCompostion = YES;
   } else {
     if (!editCommands_.empty()) {
-      widgetHost->Send(new ViewMsg_SetEditCommandsForNextKeyEvent(
+      widgetHost->Send(new InputMsg_SetEditCommandsForNextKeyEvent(
           widgetHost->GetRoutingID(), editCommands_));
     }
     widgetHost->ForwardKeyboardEvent(event);
@@ -1982,7 +2018,7 @@
     // thus it won't destroy the widget.
 
     if (!editCommands_.empty()) {
-      widgetHost->Send(new ViewMsg_SetEditCommandsForNextKeyEvent(
+      widgetHost->Send(new InputMsg_SetEditCommandsForNextKeyEvent(
           widgetHost->GetRoutingID(), editCommands_));
     }
     widgetHost->ForwardKeyboardEvent(event);
@@ -2156,7 +2192,7 @@
     return;
 
   handlingGlobalFrameDidChange_ = YES;
-  if (renderWidgetHostView_->compositing_iosurface_.get())
+  if (renderWidgetHostView_->compositing_iosurface_)
     renderWidgetHostView_->compositing_iosurface_->GlobalFrameDidChange();
   handlingGlobalFrameDidChange_ = NO;
 }
@@ -2270,7 +2306,10 @@
     }
 
     renderWidgetHostView_->compositing_iosurface_->DrawIOSurface(
-        self, ScaleFactor(self), renderWidgetHostView_->frame_subscriber());
+        self,
+        ScaleFactor(self),
+        renderWidgetHostView_->window_number(),
+        renderWidgetHostView_->frame_subscriber());
     return;
   }
 
@@ -3041,7 +3080,8 @@
       editCommands_.push_back(EditCommand(command, ""));
   } else {
     RenderWidgetHostImpl* rwh = renderWidgetHostView_->render_widget_host_;
-    rwh->Send(new ViewMsg_ExecuteEditCommand(rwh->GetRoutingID(), command, ""));
+    rwh->Send(new InputMsg_ExecuteEditCommand(rwh->GetRoutingID(),
+                                              command, ""));
   }
 }
 
diff --git a/content/browser/renderer_host/render_widget_host_view_mac_editcommand_helper_unittest.mm b/content/browser/renderer_host/render_widget_host_view_mac_editcommand_helper_unittest.mm
index c81681a..460ec72 100644
--- a/content/browser/renderer_host/render_widget_host_view_mac_editcommand_helper_unittest.mm
+++ b/content/browser/renderer_host/render_widget_host_view_mac_editcommand_helper_unittest.mm
@@ -9,7 +9,7 @@
 #include "base/message_loop.h"
 #include "content/browser/renderer_host/render_widget_host_delegate.h"
 #include "content/browser/renderer_host/render_widget_host_impl.h"
-#include "content/common/view_messages.h"
+#include "content/common/input_messages.h"
 #include "content/public/test/mock_render_process_host.h"
 #include "content/public/test/test_browser_context.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -83,7 +83,7 @@
   }
 
   virtual bool Send(IPC::Message* message) OVERRIDE {
-    if (message->type() == ViewMsg_ExecuteEditCommand::ID)
+    if (message->type() == InputMsg_ExecuteEditCommand::ID)
       edit_command_message_count_++;
     return RenderWidgetHostImpl::Send(message);
   }
@@ -105,7 +105,7 @@
   NSArray* edit_command_strings = helper.GetEditSelectorNames();
 
   // Set up a mock render widget and set expectations.
-  MessageLoopForUI message_loop;
+  base::MessageLoopForUI message_loop;
   TestBrowserContext browser_context;
   MockRenderProcessHost mock_process(&browser_context);
   MockRenderWidgetHostDelegate delegate;
diff --git a/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm b/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm
index 6061ff5..9fa0d0e 100644
--- a/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm
+++ b/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm
@@ -11,6 +11,7 @@
 #include "content/browser/renderer_host/render_widget_host_delegate.h"
 #include "content/browser/renderer_host/test_render_view_host.h"
 #include "content/common/gpu/gpu_messages.h"
+#include "content/common/input_messages.h"
 #include "content/common/view_messages.h"
 #include "content/public/browser/notification_types.h"
 #include "content/public/test/mock_render_process_host.h"
@@ -160,7 +161,7 @@
     // Make sure the rwhv_mac_ is gone once the superclass's |TearDown()| runs.
     rwhv_cocoa_.reset();
     pool_.Recycle();
-    MessageLoop::current()->RunUntilIdle();
+    base::MessageLoop::current()->RunUntilIdle();
     pool_.Recycle();
 
     // See comment in SetUp().
@@ -685,16 +686,15 @@
   ASSERT_EQ(1U, process_host->sink().message_count());
 
   // Send an ACK for the first wheel event, so that the queue will be flushed.
-  scoped_ptr<IPC::Message> response(
-      new ViewHostMsg_HandleInputEvent_ACK(0, WebKit::WebInputEvent::MouseWheel,
-                                           INPUT_EVENT_ACK_STATE_CONSUMED));
+  scoped_ptr<IPC::Message> response(new InputHostMsg_HandleInputEvent_ACK(
+      0, WebKit::WebInputEvent::MouseWheel, INPUT_EVENT_ACK_STATE_CONSUMED));
   host->OnMessageReceived(*response);
 
   // Post the NSEventPhaseEnded wheel event to NSApp and check whether the
   // render view receives it.
   NSEvent* event2 = MockScrollWheelEventWithPhase(@selector(phaseEnded));
   [NSApp postEvent:event2 atStart:NO];
-  MessageLoop::current()->RunUntilIdle();
+  base::MessageLoop::current()->RunUntilIdle();
   ASSERT_EQ(2U, process_host->sink().message_count());
 
   // Clean up.
diff --git a/content/browser/renderer_host/render_widget_host_view_win.cc b/content/browser/renderer_host/render_widget_host_view_win.cc
index ec15a1a..000e532 100644
--- a/content/browser/renderer_host/render_widget_host_view_win.cc
+++ b/content/browser/renderer_host/render_widget_host_view_win.cc
@@ -4,6 +4,7 @@
 
 #include "content/browser/renderer_host/render_widget_host_view_win.h"
 
+#include <dwmapi.h>
 #include <InputScope.h>
 
 #include <algorithm>
@@ -262,7 +263,6 @@
 
   POINT client_point = gesture.location().ToPOINT();
   POINT screen_point = gesture.location().ToPOINT();
-  MapWindowPoints(::GetParent(hwnd), hwnd, &client_point, 1);
   MapWindowPoints(hwnd, HWND_DESKTOP, &screen_point, 1);
 
   gesture_event.x = client_point.x;
@@ -314,6 +314,22 @@
   results->deviceScaleFactor = ui::win::GetDeviceScaleFactor();
 }
 
+void SetDwmPresentParameters(HWND window) {
+  if (base::win::GetVersion() >= base::win::VERSION_VISTA) {
+    BOOL is_composited;
+    HRESULT result = DwmIsCompositionEnabled(&is_composited);
+    if (SUCCEEDED(result) && is_composited) {
+      DWM_PRESENT_PARAMETERS present_parameters = {0};
+      present_parameters.cbSize = sizeof(present_parameters);
+      present_parameters.cBuffer = 2;
+
+      result = DwmSetPresentParameters(window, &present_parameters);
+      if (FAILED(result))
+        DLOG(ERROR) << "Unable to set present parameters: 0x%08X", result;
+    }
+  }
+}
+
 }  // namespace
 
 const wchar_t kRenderWidgetHostHWNDClass[] = L"Chrome_RenderWidgetHostHWND";
@@ -390,13 +406,11 @@
       is_fullscreen_(false),
       ignore_mouse_movement_(true),
       composition_range_(ui::Range::InvalidRange()),
-      ALLOW_THIS_IN_INITIALIZER_LIST(
-          touch_state_(new WebTouchState(this))),
+      touch_state_(new WebTouchState(this)),
       pointer_down_context_(false),
       last_touch_location_(-1, -1),
       touch_events_enabled_(false),
-      ALLOW_THIS_IN_INITIALIZER_LIST(
-          gesture_recognizer_(ui::GestureRecognizer::Create(this))) {
+      gesture_recognizer_(ui::GestureRecognizer::Create(this)) {
   render_widget_host_->SetView(this);
   registrar_.Add(this,
                  NOTIFICATION_RENDERER_PROCESS_TERMINATED,
@@ -470,7 +484,7 @@
   if (render_widget_host_)
     render_widget_host_->WasHidden();
 
-  if (accelerated_surface_.get())
+  if (accelerated_surface_)
     accelerated_surface_->WasHidden();
 
   if (GetBrowserAccessibilityManager())
@@ -555,6 +569,8 @@
   if (!compositor_host_window_)
     return;
 
+  ui::SetWindowUserData(compositor_host_window_, NULL);
+
   // Hide the compositor and parent it to the desktop rather than destroying
   // it immediately. The GPU process has a grace period to stop accessing the
   // window. TODO(apatrick): the GPU process should acknowledge that it has
@@ -845,7 +861,7 @@
     const base::Callback<void(bool, const SkBitmap&)>& callback) {
   base::ScopedClosureRunner scoped_callback_runner(
       base::Bind(callback, false, SkBitmap()));
-  if (!accelerated_surface_.get())
+  if (!accelerated_surface_)
     return;
 
   if (dst_size.IsEmpty() || src_subrect.IsEmpty())
@@ -860,7 +876,7 @@
     const scoped_refptr<media::VideoFrame>& target,
     const base::Callback<void(bool)>& callback) {
   base::ScopedClosureRunner scoped_callback_runner(base::Bind(callback, false));
-  if (!accelerated_surface_.get())
+  if (!accelerated_surface_)
     return;
 
   if (!target || target->format() != media::VideoFrame::YV12)
@@ -1177,6 +1193,11 @@
   render_widget_host_->ExtendSelectionAndDelete(before, after);
 }
 
+void RenderWidgetHostViewWin::EnsureCaretInRect(const gfx::Rect& rect) {
+  // TODO(nona): Implement this function.
+  NOTIMPLEMENTED();
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 // RenderWidgetHostViewWin, private:
 
@@ -1190,6 +1211,7 @@
   props_.push_back(ui::SetWindowSupportsRerouteMouseWheel(m_hWnd));
 
   WTSRegisterSessionNotification(m_hWnd, NOTIFY_FOR_THIS_SESSION);
+  SetDwmPresentParameters(m_hWnd);
 
   UpdateDesiredTouchMode();
   UpdateIMEState();
@@ -1293,7 +1315,7 @@
 
     // Blit only the damaged regions from the backing store.
     DWORD data_size = GetRegionData(damage_region, 0, NULL);
-    scoped_array<char> region_data_buf;
+    scoped_ptr<char[]> region_data_buf;
     RGNDATA* region_data = NULL;
     RECT* region_rects = NULL;
 
@@ -1479,7 +1501,8 @@
     SetWindowPos(NULL, 0, 0, 0, 0,
                  SWP_HIDEWINDOW | SWP_NOACTIVATE | SWP_NOMOVE |
                  SWP_NOREPOSITION | SWP_NOSIZE | SWP_NOZORDER);
-    MessageLoop::current()->PostTask(FROM_HERE,
+    base::MessageLoop::current()->PostTask(
+        FROM_HERE,
         base::Bind(&RenderWidgetHostViewWin::ShutdownHost,
                    weak_factory_.GetWeakPtr()));
   }
@@ -2113,7 +2136,7 @@
 
   touch_point->screenPosition.x = coordinates.x;
   touch_point->screenPosition.y = coordinates.y;
-  window_->GetParent().ScreenToClient(&coordinates);
+  window_->ScreenToClient(&coordinates);
   touch_point->position.x = coordinates.x;
   touch_point->position.y = coordinates.y;
   touch_point->radiusX = radius_x;
@@ -2393,9 +2416,6 @@
   switch (message) {
   case WM_ERASEBKGND:
     return 0;
-  case WM_DESTROY:
-    ui::SetWindowUserData(hWnd, NULL);
-    return 0;
   case WM_PAINT:
     PaintCompositorHostWindow(hWnd);
     return 0;
@@ -2407,7 +2427,7 @@
 void RenderWidgetHostViewWin::AcceleratedPaint(HDC dc) {
   if (render_widget_host_)
     render_widget_host_->ScheduleComposite();
-  if (accelerated_surface_.get())
+  if (accelerated_surface_)
     accelerated_surface_->Present(dc);
 }
 
@@ -2444,7 +2464,7 @@
   // On Vista and later we present directly to the view window rather than a
   // child window.
   if (GpuDataManagerImpl::GetInstance()->IsUsingAcceleratedSurface()) {
-    if (!accelerated_surface_.get())
+    if (!accelerated_surface_)
       accelerated_surface_.reset(new AcceleratedSurface(m_hWnd));
     return gfx::GLSurfaceHandle(m_hWnd, gfx::NATIVE_TRANSPORT);
   }
@@ -2484,6 +2504,8 @@
 
   ui::SetWindowUserData(compositor_host_window_, this);
 
+  SetDwmPresentParameters(compositor_host_window_);
+
   gfx::GLSurfaceHandle surface_handle(compositor_host_window_,
                                       gfx::NATIVE_TRANSPORT);
 
@@ -2532,7 +2554,7 @@
     // Drop the backing store for the accelerated surface when the accelerated
     // compositor is disabled. Otherwise, a flash of the last presented frame
     // could appear when it is next enabled.
-    if (accelerated_surface_.get())
+    if (accelerated_surface_)
       accelerated_surface_->Suspend();
     hide_compositor_window_at_next_paint_ = true;
   }
@@ -2551,7 +2573,7 @@
 }
 
 void RenderWidgetHostViewWin::AcceleratedSurfaceSuspend() {
-    if (!accelerated_surface_.get())
+    if (!accelerated_surface_)
       return;
 
     accelerated_surface_->Suspend();
@@ -2624,7 +2646,7 @@
     // active windows screen reader.
     BrowserAccessibilityState::GetInstance()->OnScreenReaderDetected();
     render_widget_host_->SetAccessibilityMode(
-        BrowserAccessibilityStateImpl::GetInstance()->GetAccessibilityMode());
+        BrowserAccessibilityStateImpl::GetInstance()->accessibility_mode());
 
     // Return with failure.
     return static_cast<LRESULT>(0L);
@@ -2689,7 +2711,7 @@
   handled = FALSE;
   TRACE_EVENT0("browser", "RenderWidgetHostViewWin::OnSessionChange");
 
-  if (!accelerated_surface_.get())
+  if (!accelerated_surface_)
     return 0;
 
   switch (wparam) {
diff --git a/content/browser/renderer_host/render_widget_host_view_win.h b/content/browser/renderer_host/render_widget_host_view_win.h
index 17f6a47..2990541 100644
--- a/content/browser/renderer_host/render_widget_host_view_win.h
+++ b/content/browser/renderer_host/render_widget_host_view_win.h
@@ -283,6 +283,7 @@
   virtual bool ChangeTextDirectionAndLayoutAlignment(
       base::i18n::TextDirection direction) OVERRIDE;
   virtual void ExtendSelectionAndDelete(size_t before, size_t after) OVERRIDE;
+  virtual void EnsureCaretInRect(const gfx::Rect& rect) OVERRIDE;
 
  protected:
   friend class RenderWidgetHostView;
diff --git a/content/browser/renderer_host/smooth_scroll_gesture_controller.cc b/content/browser/renderer_host/smooth_scroll_gesture_controller.cc
new file mode 100644
index 0000000..3e8fcc1
--- /dev/null
+++ b/content/browser/renderer_host/smooth_scroll_gesture_controller.cc
@@ -0,0 +1,61 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/smooth_scroll_gesture_controller.h"
+
+#include "base/debug/trace_event.h"
+#include "base/message_loop.h"
+#include "content/common/view_messages.h"
+#include "content/port/browser/render_widget_host_view_port.h"
+#include "content/port/browser/smooth_scroll_gesture.h"
+#include "content/public/browser/render_widget_host.h"
+
+namespace content {
+
+namespace {
+
+// How many milliseconds apart synthetic scroll messages should be sent.
+const int kSyntheticScrollMessageIntervalMs = 8;
+
+}  // namespace
+
+SmoothScrollGestureController::SmoothScrollGestureController()
+    : rwh_(NULL) {
+}
+
+SmoothScrollGestureController::~SmoothScrollGestureController() {
+}
+
+void SmoothScrollGestureController::BeginSmoothScroll(
+    RenderWidgetHostViewPort* view,
+    const ViewHostMsg_BeginSmoothScroll_Params& params) {
+  if (pending_smooth_scroll_gesture_)
+    return;
+
+  rwh_ = view->GetRenderWidgetHost();
+  pending_smooth_scroll_gesture_ = view->CreateSmoothScrollGesture(
+      params.scroll_down,
+      params.pixels_to_scroll,
+      params.mouse_event_x,
+      params.mouse_event_y);
+
+  timer_.Start(FROM_HERE, GetSyntheticScrollMessageInterval(), this,
+               &SmoothScrollGestureController::OnTimer);
+}
+
+base::TimeDelta
+    SmoothScrollGestureController::GetSyntheticScrollMessageInterval() const {
+  return base::TimeDelta::FromMilliseconds(kSyntheticScrollMessageIntervalMs);
+}
+
+void SmoothScrollGestureController::OnTimer() {
+  base::TimeTicks now = base::TimeTicks::Now();
+  if (!pending_smooth_scroll_gesture_->ForwardInputEvents(now, rwh_)) {
+    timer_.Stop();
+    pending_smooth_scroll_gesture_ = NULL;
+    rwh_->Send(new ViewMsg_SmoothScrollCompleted(rwh_->GetRoutingID()));
+  }
+}
+
+}  // namespace content
diff --git a/content/browser/renderer_host/smooth_scroll_gesture_controller.h b/content/browser/renderer_host/smooth_scroll_gesture_controller.h
new file mode 100644
index 0000000..6e25cd7
--- /dev/null
+++ b/content/browser/renderer_host/smooth_scroll_gesture_controller.h
@@ -0,0 +1,52 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_RENDERER_HOST_SMOOTH_SCROLL_GESTURE_CONTROLLER_H_
+#define CONTENT_BROWSER_RENDERER_HOST_SMOOTH_SCROLL_GESTURE_CONTROLLER_H_
+
+#include <map>
+
+#include "base/memory/weak_ptr.h"
+#include "base/time.h"
+#include "base/timer.h"
+#include "content/common/content_export.h"
+
+struct ViewHostMsg_BeginSmoothScroll_Params;
+
+namespace content {
+
+class RenderWidgetHost;
+class RenderWidgetHostViewPort;
+class SmoothScrollGesture;
+
+// Controls SmoothScrollGestures, used to inject synthetic events
+// for performance test harness.
+class CONTENT_EXPORT SmoothScrollGestureController {
+ public:
+  SmoothScrollGestureController();
+  ~SmoothScrollGestureController();
+
+  // Initiates a synthetic event stream.
+  void BeginSmoothScroll(RenderWidgetHostViewPort* view,
+                         const ViewHostMsg_BeginSmoothScroll_Params& params);
+
+  base::TimeDelta GetSyntheticScrollMessageInterval() const;
+
+ private:
+  // Called periodically to advance the active scroll gesture after being
+  // initiated by OnBeginSmoothScroll.
+  void OnTimer();
+
+  base::RepeatingTimer<SmoothScrollGestureController> timer_;
+
+  RenderWidgetHost* rwh_;
+
+  scoped_refptr<SmoothScrollGesture> pending_smooth_scroll_gesture_;
+
+  DISALLOW_COPY_AND_ASSIGN(SmoothScrollGestureController);
+};
+
+}  // namespace content
+
+#endif  // CONTENT_BROWSER_RENDERER_HOST_SMOOTH_SCROLL_GESTURE_CONTROLLER_H_
diff --git a/content/browser/renderer_host/smooth_scroll_gesture_controller_unittest.cc b/content/browser/renderer_host/smooth_scroll_gesture_controller_unittest.cc
new file mode 100644
index 0000000..96b70a2
--- /dev/null
+++ b/content/browser/renderer_host/smooth_scroll_gesture_controller_unittest.cc
@@ -0,0 +1,183 @@
+// Copyright (c) 2013 The Chromium Authors. 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/memory/scoped_ptr.h"
+#include "base/time.h"
+#include "content/browser/renderer_host/render_widget_host_delegate.h"
+#include "content/browser/renderer_host/smooth_scroll_gesture_controller.h"
+#include "content/browser/renderer_host/test_render_view_host.h"
+#include "content/common/view_messages.h"
+#include "content/port/browser/render_widget_host_view_port.h"
+#include "content/port/browser/smooth_scroll_gesture.h"
+#include "content/public/test/mock_render_process_host.h"
+#include "content/public/test/test_browser_context.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+#if defined(USE_AURA)
+#include "ui/aura/env.h"
+#include "ui/aura/test/test_screen.h"
+#endif
+
+using base::TimeDelta;
+
+namespace content {
+
+namespace {
+
+class MockSmoothScrollGesture : public SmoothScrollGesture {
+ public:
+  MockSmoothScrollGesture() :
+      called_(0) {
+  }
+
+  // SmoothScrollGesture implementation:
+  virtual bool ForwardInputEvents(base::TimeTicks now,
+                                  RenderWidgetHost* host) OVERRIDE {
+    ++called_;
+    return true;
+  }
+
+  int called_;
+
+ protected:
+  virtual ~MockSmoothScrollGesture() {
+  }
+};
+
+class MockRenderWidgetHostDelegate : public RenderWidgetHostDelegate {
+ public:
+  MockRenderWidgetHostDelegate() {
+  }
+  virtual ~MockRenderWidgetHostDelegate() {}
+};
+
+class MockRenderWidgetHost : public RenderWidgetHostImpl {
+ public:
+  MockRenderWidgetHost(
+      RenderWidgetHostDelegate* delegate,
+      RenderProcessHost* process,
+      int routing_id)
+      : RenderWidgetHostImpl(delegate, process, routing_id) {
+  }
+  virtual ~MockRenderWidgetHost() {}
+};
+
+class TestView : public TestRenderWidgetHostView {
+ public:
+  explicit TestView(RenderWidgetHostImpl* rwh)
+      : TestRenderWidgetHostView(rwh),
+        mock_gesture_(NULL) {
+  }
+  virtual ~TestView() {}
+
+  // TestRenderWidgetHostView implementation:
+  virtual SmoothScrollGesture* CreateSmoothScrollGesture(
+      bool scroll_down, int pixels_to_scroll, int mouse_event_x,
+      int mouse_event_y) OVERRIDE {
+    mock_gesture_ = new MockSmoothScrollGesture();
+    return mock_gesture_;
+  }
+
+  virtual RenderWidgetHost* GetRenderWidgetHost() const OVERRIDE {
+    return rwh_;
+  }
+
+  MockSmoothScrollGesture* mock_gesture_;
+};
+
+class SmoothScrollGestureControllerTest : public testing::Test {
+ public:
+  SmoothScrollGestureControllerTest() : process_(NULL) {
+  }
+  virtual ~SmoothScrollGestureControllerTest() {}
+
+ protected:
+  // testing::Test implementation:
+  virtual void SetUp() OVERRIDE {
+    browser_context_.reset(new TestBrowserContext());
+    delegate_.reset(new MockRenderWidgetHostDelegate());
+    process_ = new MockRenderProcessHost(browser_context_.get());
+#if defined(USE_AURA)
+    screen_.reset(aura::TestScreen::Create());
+    gfx::Screen::SetScreenInstance(gfx::SCREEN_TYPE_NATIVE, screen_.get());
+#endif
+    host_.reset(
+        new MockRenderWidgetHost(delegate_.get(), process_, MSG_ROUTING_NONE));
+    view_.reset(new TestView(host_.get()));
+    host_->SetView(view_.get());
+    host_->Init();
+  }
+
+  virtual void TearDown() OVERRIDE {
+    view_.reset();
+    host_.reset();
+    delegate_.reset();
+    process_ = NULL;
+    browser_context_.reset();
+
+#if defined(USE_AURA)
+    aura::Env::DeleteInstance();
+    screen_.reset();
+#endif
+
+    // Process all pending tasks to avoid leaks.
+    MessageLoop::current()->RunUntilIdle();
+  }
+
+  void PostQuitMessageAndRun() {
+    // Allow the message loop to process pending synthetic scrolls, then quit.
+    MessageLoop::current()->PostDelayedTask(
+        FROM_HERE, MessageLoop::QuitClosure(),
+        TimeDelta::FromMilliseconds(
+            controller_.GetSyntheticScrollMessageInterval().InMilliseconds() *
+            3));
+    MessageLoop::current()->Run();
+  }
+
+  MessageLoopForUI message_loop_;
+
+  scoped_ptr<TestBrowserContext> browser_context_;
+  MockRenderProcessHost* process_;  // Deleted automatically by the widget.
+  scoped_ptr<MockRenderWidgetHostDelegate> delegate_;
+  scoped_ptr<MockRenderWidgetHost> host_;
+  scoped_ptr<TestView> view_;
+#if defined(USE_AURA)
+  scoped_ptr<gfx::Screen> screen_;
+#endif
+
+  SmoothScrollGestureController controller_;
+};
+
+TEST_F(SmoothScrollGestureControllerTest, Tick) {
+  ViewHostMsg_BeginSmoothScroll_Params params;
+  params.scroll_down = true;
+  params.pixels_to_scroll = 10;
+  params.mouse_event_x = 20;
+  params.mouse_event_y = 30;
+
+  // Begin a smooth scroll, |mock_gesture_| won't be |called| until we post
+  // message.
+  controller_.BeginSmoothScroll(view_.get(), params);
+  EXPECT_TRUE(view_->mock_gesture_ != NULL);
+  EXPECT_EQ(0, view_->mock_gesture_->called_);
+
+  PostQuitMessageAndRun();
+  const int current_ticks = view_->mock_gesture_->called_;
+  EXPECT_LT(0, current_ticks);
+
+  // Ensure it won't start another smooth scroll.
+  MockSmoothScrollGesture* original_gesture = view_->mock_gesture_;
+  controller_.BeginSmoothScroll(view_.get(), params);
+  PostQuitMessageAndRun();
+  EXPECT_EQ(original_gesture, view_->mock_gesture_);
+
+  // Ensure the smooth scroll is ticked.
+  PostQuitMessageAndRun();
+  EXPECT_LT(current_ticks, view_->mock_gesture_->called_);
+}
+
+}  // namespace
+
+}  // namespace content
diff --git a/content/browser/renderer_host/socket_stream_dispatcher_host.cc b/content/browser/renderer_host/socket_stream_dispatcher_host.cc
index 2eea8a8..3d0157b 100644
--- a/content/browser/renderer_host/socket_stream_dispatcher_host.cc
+++ b/content/browser/renderer_host/socket_stream_dispatcher_host.cc
@@ -101,6 +101,23 @@
   DeleteSocketStreamHost(socket_id);
 }
 
+void SocketStreamDispatcherHost::OnError(const net::SocketStream* socket,
+                                         int error) {
+  int socket_id = SocketStreamHost::SocketIdFromSocketStream(socket);
+  DVLOG(1) << "SocketStreamDispatcherHost::OnError socket_id=" << socket_id;
+  if (socket_id == content::kNoSocketId) {
+    LOG(ERROR) << "NoSocketId in OnError";
+    return;
+  }
+  // SocketStream::Delegate::OnError() events are handled as WebSocket error
+  // event when user agent was required to fail WebSocket connection or the
+  // WebSocket connection is closed with prejudice.
+  if (!Send(new SocketStreamMsg_Failed(socket_id, error))) {
+    LOG(ERROR) << "SocketStreamMsg_Failed failed.";
+    DeleteSocketStreamHost(socket_id);
+  }
+}
+
 void SocketStreamDispatcherHost::OnSSLCertificateError(
     net::SocketStream* socket, const net::SSLInfo& ssl_info, bool fatal) {
   int socket_id = SocketStreamHost::SocketIdFromSocketStream(socket);
diff --git a/content/browser/renderer_host/socket_stream_dispatcher_host.h b/content/browser/renderer_host/socket_stream_dispatcher_host.h
index 7426acc..c9e1c86 100644
--- a/content/browser/renderer_host/socket_stream_dispatcher_host.h
+++ b/content/browser/renderer_host/socket_stream_dispatcher_host.h
@@ -51,6 +51,7 @@
   virtual void OnReceivedData(net::SocketStream* socket,
                               const char* data, int len) OVERRIDE;
   virtual void OnClose(net::SocketStream* socket) OVERRIDE;
+  virtual void OnError(const net::SocketStream* socket, int error) OVERRIDE;
   virtual void OnSSLCertificateError(net::SocketStream* socket,
                                      const net::SSLInfo& ssl_info,
                                      bool fatal) OVERRIDE;
diff --git a/content/browser/renderer_host/socket_stream_host.cc b/content/browser/renderer_host/socket_stream_host.cc
index b3c9d4c..405a2b7 100644
--- a/content/browser/renderer_host/socket_stream_host.cc
+++ b/content/browser/renderer_host/socket_stream_host.cc
@@ -39,7 +39,8 @@
 }
 
 /* static */
-int SocketStreamHost::SocketIdFromSocketStream(net::SocketStream* socket) {
+int SocketStreamHost::SocketIdFromSocketStream(
+    const net::SocketStream* socket) {
   net::SocketStream::UserData* d = socket->GetUserData(kSocketIdKey);
   if (d) {
     SocketStreamId* socket_stream_id = static_cast<SocketStreamId*>(d);
diff --git a/content/browser/renderer_host/socket_stream_host.h b/content/browser/renderer_host/socket_stream_host.h
index d0c65ab..b71e14f 100644
--- a/content/browser/renderer_host/socket_stream_host.h
+++ b/content/browser/renderer_host/socket_stream_host.h
@@ -34,7 +34,7 @@
   ~SocketStreamHost();
 
   // Gets socket_id associated with |socket|.
-  static int SocketIdFromSocketStream(net::SocketStream* socket);
+  static int SocketIdFromSocketStream(const net::SocketStream* socket);
 
   int render_view_id() const { return render_view_id_; }
   int socket_id() const { return socket_id_; }
diff --git a/content/browser/renderer_host/software_output_device_win.cc b/content/browser/renderer_host/software_output_device_win.cc
index 90bc032..29c4542 100644
--- a/content/browser/renderer_host/software_output_device_win.cc
+++ b/content/browser/renderer_host/software_output_device_win.cc
@@ -17,13 +17,11 @@
   // TODO(skaslev) Remove this when crbug.com/180702 is fixed.
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
-  hdc_ = ::GetWindowDC(compositor->widget());
+  hwnd_ = compositor->widget();
 }
 
 SoftwareOutputDeviceWin::~SoftwareOutputDeviceWin() {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
-  ::ReleaseDC(compositor_->widget(), hdc_);
 }
 
 void SoftwareOutputDeviceWin::Resize(gfx::Size viewport_size) {
@@ -49,13 +47,15 @@
     return;
 
   const SkBitmap& bitmap = device_->accessBitmap(false);
-  gfx::StretchDIBits(hdc_,
+  HDC hdc = ::GetDC(hwnd_);
+  gfx::StretchDIBits(hdc,
                      rect.x(), rect.y(),
                      rect.width(), rect.height(),
                      rect.x(), rect.y(),
                      rect.width(), rect.height(),
                      bitmap.getPixels(),
                      &bitmap_info_);
+  ::ReleaseDC(hwnd_, hdc);
 }
 
 }  // namespace content
diff --git a/content/browser/renderer_host/software_output_device_win.h b/content/browser/renderer_host/software_output_device_win.h
index 930f523..057e48f 100644
--- a/content/browser/renderer_host/software_output_device_win.h
+++ b/content/browser/renderer_host/software_output_device_win.h
@@ -27,7 +27,7 @@
 
  private:
   ui::Compositor* compositor_;
-  HDC hdc_;
+  HWND hwnd_;
   BITMAPINFO bitmap_info_;
 };
 
diff --git a/content/browser/renderer_host/surface_texture_transport_client_android.cc b/content/browser/renderer_host/surface_texture_transport_client_android.cc
index ca2a5be..23888af 100644
--- a/content/browser/renderer_host/surface_texture_transport_client_android.cc
+++ b/content/browser/renderer_host/surface_texture_transport_client_android.cc
@@ -11,42 +11,59 @@
 #include "content/browser/gpu/gpu_surface_tracker.h"
 #include "content/browser/renderer_host/compositor_impl_android.h"
 #include "content/browser/renderer_host/image_transport_factory_android.h"
-#include "content/common/android/surface_texture_bridge.h"
+#include "content/public/browser/browser_thread.h"
 #include "third_party/WebKit/Source/Platform/chromium/public/WebGraphicsContext3D.h"
+#include "ui/gl/android/surface_texture_bridge.h"
 #include "webkit/compositor_bindings/web_compositor_support_impl.h"
 
+namespace content {
+
 namespace {
 
 static const uint32 kGLTextureExternalOES = 0x8D65;
 
-} // anonymous namespace
+class SurfaceRefAndroid : public GpuSurfaceTracker::SurfaceRef {
+ public:
+  SurfaceRefAndroid(
+      const scoped_refptr<gfx::SurfaceTextureBridge>& surface,
+      ANativeWindow* window)
+      : surface_(surface),
+        window_(window) {
+    ANativeWindow_acquire(window_);
+  }
 
-namespace content {
+ private:
+  virtual ~SurfaceRefAndroid() {
+    DCHECK(window_);
+    ANativeWindow_release(window_);
+  }
+
+  scoped_refptr<gfx::SurfaceTextureBridge> surface_;
+  ANativeWindow* window_;
+};
+
+} // anonymous namespace
 
 SurfaceTextureTransportClient::SurfaceTextureTransportClient()
     : window_(NULL),
       texture_id_(0),
-      surface_id_(0) {
+      surface_id_(0),
+      weak_factory_(this) {
 }
 
 SurfaceTextureTransportClient::~SurfaceTextureTransportClient() {
-  if (surface_id_) {
-    GpuSurfaceTracker::Get()->SetNativeWidget(
-        surface_id_, gfx::kNullAcceleratedWidget);
-  }
-  if (window_)
-    ANativeWindow_release(window_);
 }
 
 scoped_refptr<cc::Layer> SurfaceTextureTransportClient::Initialize() {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   // Use a SurfaceTexture to stream frames to the UI thread.
   video_layer_ = cc::VideoLayer::Create(this);
 
-  surface_texture_ = new SurfaceTextureBridge(0);
+  surface_texture_ = new gfx::SurfaceTextureBridge(0);
   surface_texture_->SetFrameAvailableCallback(
-      base::Bind(
-          &SurfaceTextureTransportClient::OnSurfaceTextureFrameAvailable,
-          base::Unretained(this)));
+    base::Bind(
+        &SurfaceTextureTransportClient::OnSurfaceTextureFrameAvailable,
+        weak_factory_.GetWeakPtr()));
   surface_texture_->DetachFromGLContext();
   return video_layer_.get();
 }
@@ -56,15 +73,22 @@
   DCHECK(surface_id);
   surface_id_ = surface_id;
 
-  if (!window_)
+  if (!window_) {
     window_ = surface_texture_->CreateSurface();
 
-  GpuSurfaceTracker::Get()->SetNativeWidget(surface_id, window_);
+    GpuSurfaceTracker::Get()->SetNativeWidget(
+        surface_id, window_, new SurfaceRefAndroid(surface_texture_, window_));
+    // SurfaceRefAndroid took ownership (and an extra ref to) window_.
+    ANativeWindow_release(window_);
+  }
+
   return gfx::GLSurfaceHandle(gfx::kNullPluginWindow, gfx::NATIVE_DIRECT);
 }
 
 void SurfaceTextureTransportClient::SetSize(const gfx::Size& size) {
-  surface_texture_->SetDefaultBufferSize(size.width(), size.height());
+  if (size.width() > 0 && size.height() > 0) {
+    surface_texture_->SetDefaultBufferSize(size.width(), size.height());
+  }
   video_layer_->SetBounds(size);
   video_frame_ = NULL;
 }
@@ -99,6 +123,7 @@
 }
 
 void SurfaceTextureTransportClient::OnSurfaceTextureFrameAvailable() {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   video_layer_->SetNeedsDisplay();
 }
 
diff --git a/content/browser/renderer_host/surface_texture_transport_client_android.h b/content/browser/renderer_host/surface_texture_transport_client_android.h
index d2540e1..8c5e63b 100644
--- a/content/browser/renderer_host/surface_texture_transport_client_android.h
+++ b/content/browser/renderer_host/surface_texture_transport_client_android.h
@@ -7,6 +7,7 @@
 
 #include "base/memory/ref_counted.h"
 #include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
 #include "cc/layers/video_frame_provider.h"
 #include "ui/gfx/native_widget_types.h"
 #include "ui/gfx/size.h"
@@ -18,8 +19,11 @@
 class VideoLayer;
 }
 
-namespace content {
+namespace gfx {
 class SurfaceTextureBridge;
+}
+
+namespace content {
 
 class SurfaceTextureTransportClient : public cc::VideoFrameProvider {
  public:
@@ -40,11 +44,12 @@
   void OnSurfaceTextureFrameAvailable();
 
   scoped_refptr<cc::VideoLayer> video_layer_;
-  scoped_refptr<SurfaceTextureBridge> surface_texture_;
+  scoped_refptr<gfx::SurfaceTextureBridge> surface_texture_;
   ANativeWindow* window_;
   scoped_refptr<media::VideoFrame> video_frame_;
   uint32 texture_id_;
   int surface_id_;
+  base::WeakPtrFactory<SurfaceTextureTransportClient> weak_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(SurfaceTextureTransportClient);
 };
diff --git a/content/browser/renderer_host/test_render_view_host.cc b/content/browser/renderer_host/test_render_view_host.cc
index 5bf77f1..0e1792a 100644
--- a/content/browser/renderer_host/test_render_view_host.cc
+++ b/content/browser/renderer_host/test_render_view_host.cc
@@ -212,9 +212,10 @@
 #endif
 
 #if defined(OS_WIN) && defined(USE_AURA)
-void TestRenderWidgetHostView::SetParentNativeViewAccessible(
-    gfx::NativeViewAccessible accessible_parent) {
+gfx::NativeViewAccessible
+TestRenderWidgetHostView::AccessibleObjectFromChildId(long child_id) {
   NOTIMPLEMENTED();
+  return NULL;
 }
 #endif
 
@@ -240,6 +241,7 @@
       render_view_created_(false),
       delete_counter_(NULL),
       simulate_fetch_via_proxy_(false),
+      simulate_history_list_was_cleared_(false),
       contents_mime_type_("text/html") {
   // For normal RenderViewHosts, this is freed when |Shutdown()| is
   // called.  For TestRenderViewHost, the view is explicitly
@@ -273,22 +275,33 @@
   SendNavigateWithTransition(page_id, url, PAGE_TRANSITION_LINK);
 }
 
+void TestRenderViewHost::SendFailedNavigate(int page_id, const GURL& url) {
+  SendNavigateWithTransitionAndResponseCode(
+      page_id, url, PAGE_TRANSITION_LINK, 500);
+}
+
 void TestRenderViewHost::SendNavigateWithTransition(
     int page_id, const GURL& url, PageTransition transition) {
-  OnDidStartProvisionalLoadForFrame(0, -1, true, url);
-  SendNavigateWithParameters(page_id, url, transition, url);
+  SendNavigateWithTransitionAndResponseCode(page_id, url, transition, 200);
 }
 
 void TestRenderViewHost::SendNavigateWithOriginalRequestURL(
     int page_id, const GURL& url, const GURL& original_request_url) {
   OnDidStartProvisionalLoadForFrame(0, -1, true, url);
   SendNavigateWithParameters(page_id, url, PAGE_TRANSITION_LINK,
-      original_request_url);
+                             original_request_url, 200);
+}
+
+void TestRenderViewHost::SendNavigateWithTransitionAndResponseCode(
+    int page_id, const GURL& url, PageTransition transition,
+    int response_code) {
+  OnDidStartProvisionalLoadForFrame(0, -1, true, url);
+  SendNavigateWithParameters(page_id, url, transition, url, response_code);
 }
 
 void TestRenderViewHost::SendNavigateWithParameters(
     int page_id, const GURL& url, PageTransition transition,
-    const GURL& original_request_url) {
+    const GURL& original_request_url, int response_code) {
   ViewHostMsg_FrameNavigate_Params params;
 
   params.page_id = page_id;
@@ -306,10 +319,11 @@
   params.contents_mime_type = contents_mime_type_;
   params.is_post = false;
   params.was_within_same_page = false;
-  params.http_status_code = 0;
+  params.http_status_code = response_code;
   params.socket_address.set_host("2001:db8::1");
   params.socket_address.set_port(80);
   params.was_fetched_via_proxy = simulate_fetch_via_proxy_;
+  params.history_list_was_cleared = simulate_history_list_was_cleared_;
   params.content_state = webkit_glue::CreateHistoryStateForURL(GURL(url));
   params.original_request_url = original_request_url;
 
@@ -318,7 +332,8 @@
 }
 
 void TestRenderViewHost::SendShouldCloseACK(bool proceed) {
-  OnShouldCloseACK(proceed, base::TimeTicks(), base::TimeTicks());
+  base::TimeTicks now = base::TimeTicks::Now();
+  OnShouldCloseACK(proceed, now, now);
 }
 
 void TestRenderViewHost::SetContentsMimeType(const std::string& mime_type) {
@@ -349,6 +364,10 @@
   simulate_fetch_via_proxy_ = proxy;
 }
 
+void TestRenderViewHost::set_simulate_history_list_was_cleared(bool cleared) {
+  simulate_history_list_was_cleared_ = cleared;
+}
+
 RenderViewHostImplTestHarness::RenderViewHostImplTestHarness() {
 }
 
diff --git a/content/browser/renderer_host/test_render_view_host.h b/content/browser/renderer_host/test_render_view_host.h
index 14ea4d8..a6ec555 100644
--- a/content/browser/renderer_host/test_render_view_host.h
+++ b/content/browser/renderer_host/test_render_view_host.h
@@ -141,13 +141,6 @@
   virtual void ShowDisambiguationPopup(
       const gfx::Rect& target_rect,
       const SkBitmap& zoomed_bitmap) OVERRIDE {}
-  virtual void UpdateFrameInfo(const gfx::Vector2dF& scroll_offset,
-                               float page_scale_factor,
-                               const gfx::Vector2dF& page_scale_factor_limits,
-                               const gfx::SizeF& content_size,
-                               const gfx::SizeF& viewport_size,
-                               const gfx::Vector2dF& controls_offset,
-                               const gfx::Vector2dF& content_offset) OVERRIDE {}
   virtual void HasTouchEventHandlers(bool need_touch_events) OVERRIDE {}
 #elif defined(OS_WIN) && !defined(USE_AURA)
   virtual void WillWmDestroy() OVERRIDE;
@@ -166,8 +159,8 @@
   virtual void SetClickthroughRegion(SkRegion* region) OVERRIDE;
 #endif
 #if defined(OS_WIN) && defined(USE_AURA)
-  virtual void SetParentNativeViewAccessible(
-      gfx::NativeViewAccessible accessible_parent) OVERRIDE;
+  virtual gfx::NativeViewAccessible AccessibleObjectFromChildId(long child_id)
+      OVERRIDE;
 #endif
   virtual bool LockMouse() OVERRIDE;
   virtual void UnlockMouse() OVERRIDE;
@@ -237,6 +230,7 @@
   // is not specified since it is synonymous with the one from
   // RenderViewHostImpl, see below.
   virtual void SendNavigate(int page_id, const GURL& url) OVERRIDE;
+  virtual void SendFailedNavigate(int page_id, const GURL& url) OVERRIDE;
   virtual void SendNavigateWithTransition(int page_id, const GURL& url,
                                           PageTransition transition) OVERRIDE;
   virtual void SendShouldCloseACK(bool proceed) OVERRIDE;
@@ -252,12 +246,6 @@
   void SendNavigateWithOriginalRequestURL(
       int page_id, const GURL& url, const GURL& original_request_url);
 
-  // Calls OnNavigate on the RenderViewHost with the given information.
-  // Sets the rest of the parameters in the message to the "typical" values.
-  // This is a helper function for simulating the most common types of loads.
-  void SendNavigateWithParameters(
-      int page_id, const GURL& url, PageTransition transition,
-      const GURL& original_request_url);
 
   void TestOnStartDragging(const WebDropData& drop_data);
 
@@ -296,6 +284,11 @@
   // False by default.
   void set_simulate_fetch_via_proxy(bool proxy);
 
+  // If set, navigations will appear to have cleared the history list in the
+  // RenderView (ViewHostMsg_FrameNavigate_Params::history_list_was_cleared).
+  // False by default.
+  void set_simulate_history_list_was_cleared(bool cleared);
+
   // RenderViewHost overrides --------------------------------------------------
 
   virtual bool CreateRenderView(const string16& frame_name,
@@ -306,6 +299,21 @@
  private:
   FRIEND_TEST_ALL_PREFIXES(RenderViewHostTest, FilterNavigate);
 
+  void SendNavigateWithTransitionAndResponseCode(int page_id,
+                                                 const GURL& url,
+                                                 PageTransition transition,
+                                                 int response_code);
+
+  // Calls OnNavigate on the RenderViewHost with the given information.
+  // Sets the rest of the parameters in the message to the "typical" values.
+  // This is a helper function for simulating the most common types of loads.
+  void SendNavigateWithParameters(int page_id,
+                                  const GURL& url,
+                                  PageTransition transition,
+                                  const GURL& original_request_url,
+                                  int response_code);
+
+
   // Tracks if the caller thinks if it created the RenderView. This is so we can
   // respond to IsRenderViewLive appropriately.
   bool render_view_created_;
@@ -316,6 +324,9 @@
   // See set_simulate_fetch_via_proxy() above.
   bool simulate_fetch_via_proxy_;
 
+  // See set_simulate_history_list_was_cleared() above.
+  bool simulate_history_list_was_cleared_;
+
   // See SetContentsMimeType() above.
   std::string contents_mime_type_;
 
diff --git a/content/browser/renderer_host/text_input_client_mac_unittest.mm b/content/browser/renderer_host/text_input_client_mac_unittest.mm
index 9930b3e..20976ef 100644
--- a/content/browser/renderer_host/text_input_client_mac_unittest.mm
+++ b/content/browser/renderer_host/text_input_client_mac_unittest.mm
@@ -35,7 +35,7 @@
 class TextInputClientMacTest : public testing::Test {
  public:
   TextInputClientMacTest()
-      : message_loop_(MessageLoop::TYPE_UI),
+      : message_loop_(base::MessageLoop::TYPE_UI),
         browser_context_(),
         process_factory_(),
         delegate_(),
@@ -73,7 +73,7 @@
  private:
   friend class ScopedTestingThread;
 
-  MessageLoop message_loop_;
+  base::MessageLoop message_loop_;
   TestBrowserContext browser_context_;
 
   // Gets deleted when the last RWH in the "process" gets destroyed.
diff --git a/content/browser/renderer_host/web_input_event_aura.cc b/content/browser/renderer_host/web_input_event_aura.cc
index 81e1ebf..e293377 100644
--- a/content/browser/renderer_host/web_input_event_aura.cc
+++ b/content/browser/renderer_host/web_input_event_aura.cc
@@ -20,13 +20,32 @@
     base::NativeEvent native_event);
 WebKit::WebGestureEvent MakeWebGestureEventFromNativeEvent(
     base::NativeEvent native_event);
-#else
+#elif defined(USE_X11)
 WebKit::WebMouseWheelEvent MakeWebMouseWheelEventFromAuraEvent(
     ui::ScrollEvent* event);
 WebKit::WebKeyboardEvent MakeWebKeyboardEventFromAuraEvent(
     ui::KeyEvent* event);
 WebKit::WebGestureEvent MakeWebGestureEventFromAuraEvent(
     ui::ScrollEvent* event);
+#else
+WebKit::WebMouseWheelEvent MakeWebMouseWheelEventFromAuraEvent(
+    ui::ScrollEvent* event) {
+  WebKit::WebMouseWheelEvent webkit_event;
+  return webkit_event;
+}
+
+WebKit::WebKeyboardEvent MakeWebKeyboardEventFromAuraEvent(
+    ui::KeyEvent* event) {
+  WebKit::WebKeyboardEvent webkit_event;
+  return webkit_event;
+}
+
+WebKit::WebGestureEvent MakeWebGestureEventFromAuraEvent(
+    ui::ScrollEvent* event) {
+  WebKit::WebGestureEvent webkit_event;
+  return webkit_event;
+}
+
 #endif
 
 WebKit::WebMouseEvent MakeWebMouseEventFromAuraEvent(
@@ -234,7 +253,8 @@
   webkit_event.button = WebKit::WebMouseEvent::ButtonNone;
   webkit_event.modifiers = EventFlagsToWebEventModifiers(event->flags());
   webkit_event.timeStampSeconds = event->time_stamp().InSecondsF();
-  webkit_event.deltaY = event->offset();
+  webkit_event.deltaX = event->x_offset();
+  webkit_event.deltaY = event->y_offset();
   webkit_event.wheelTicksY = webkit_event.deltaY / kPixelsPerTick;
 
   return webkit_event;
diff --git a/content/browser/resolve_proxy_msg_helper.cc b/content/browser/resolve_proxy_msg_helper.cc
index 52d0987..796b070 100644
--- a/content/browser/resolve_proxy_msg_helper.cc
+++ b/content/browser/resolve_proxy_msg_helper.cc
@@ -83,7 +83,7 @@
   // Verify the request wasn't started yet.
   DCHECK(NULL == req.pac_req);
 
-  if (context_getter_.get()) {
+  if (context_getter_) {
     proxy_service_ = context_getter_->GetURLRequestContext()->proxy_service();
     context_getter_ = NULL;
   }
diff --git a/content/browser/resolve_proxy_msg_helper_unittest.cc b/content/browser/resolve_proxy_msg_helper_unittest.cc
index f0d1c2d..628df86 100644
--- a/content/browser/resolve_proxy_msg_helper_unittest.cc
+++ b/content/browser/resolve_proxy_msg_helper_unittest.cc
@@ -41,10 +41,10 @@
 
   ResolveProxyMsgHelperTest()
       : resolver_(new net::MockAsyncProxyResolver),
-        service_(new net::ProxyService(
-            new MockProxyConfigService, resolver_, NULL)),
+        service_(
+            new net::ProxyService(new MockProxyConfigService, resolver_, NULL)),
         helper_(new ResolveProxyMsgHelper(service_.get())),
-        message_loop_(MessageLoop::TYPE_IO),
+        message_loop_(base::MessageLoop::TYPE_IO),
         io_thread_(BrowserThread::IO, &message_loop_) {
     test_sink_.AddFilter(this);
     helper_->OnFilterAdded(&test_sink_);
@@ -79,7 +79,7 @@
     return true;
   }
 
-  MessageLoop message_loop_;
+  base::MessageLoop message_loop_;
   BrowserThreadImpl io_thread_;
   IPC::TestSink test_sink_;
 };
diff --git a/content/browser/resources/indexed_db/OWNERS b/content/browser/resources/indexed_db/OWNERS
new file mode 100644
index 0000000..b106dad
--- /dev/null
+++ b/content/browser/resources/indexed_db/OWNERS
@@ -0,0 +1,4 @@
+dgrogan@chromium.org
+michaeln@chromium.org
+jsbell@chromium.org
+alecflett@chromium.org
diff --git a/content/browser/resources/indexed_db/indexeddb_internals.css b/content/browser/resources/indexed_db/indexeddb_internals.css
new file mode 100644
index 0000000..2bbea77
--- /dev/null
+++ b/content/browser/resources/indexed_db/indexeddb_internals.css
@@ -0,0 +1,35 @@
+/* Copyright (c) 2013 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file. */
+
+.indexeddb-summary {
+    background-color: rgb(235, 239, 249);
+    border-top: 1px solid rgb(156, 194, 239);
+    margin-bottom: 6px;
+    margin-top: 12px;
+    padding: 3px;
+    font-weight: bold;
+}
+
+.indexeddb-item {
+    margin-bottom: 15px;
+    margin-top: 6px;
+    position: relative;
+}
+
+.indexeddb-url {
+    color: rgb(85, 102, 221);
+    display: inline-block;
+    max-width: 500px;
+    overflow: hidden;
+    padding-bottom: 1px;
+    padding-top: 4px;
+    text-decoration: none;
+    text-overflow: ellipsis;
+    white-space: nowrap;
+}
+
+.controls a {
+    -webkit-margin-end: 16px;
+    color: #777;
+}
diff --git a/content/browser/resources/indexed_db/indexeddb_internals.html b/content/browser/resources/indexed_db/indexeddb_internals.html
new file mode 100644
index 0000000..87337ec
--- /dev/null
+++ b/content/browser/resources/indexed_db/indexeddb_internals.html
@@ -0,0 +1,56 @@
+<!DOCTYPE html>
+<html i18n-values="dir:textdirection;">
+<head>
+  <meta charset="utf-8">
+  <title>IndexedDB</title>
+  <link rel="stylesheet" href="chrome://resources/css/tabs.css">
+  <link rel="stylesheet" href="chrome://resources/css/widgets.css">
+  <link rel="stylesheet" href="indexeddb_internals.css">
+</head>
+<body i18n-values=".style.fontFamily:fontfamily;.style.fontSize:fontsize">
+    <!-- templates -->
+    <div style="display:none">
+        <div id="indexeddb-list-template"
+             jsvalues="$partition_path:$this.partition_path">
+            <div class="indexeddb-summary">
+                <span>Instances in: </span>
+                <span jscontent="$this.partition_path"></span>
+                <span jscontent="'(' + $this.idbs.length + ')'"></span>
+            </div>
+            <div class="indexeddb-item" jsselect="$this.idbs">
+                <a class="indexeddb-url" jscontent="url" jsvalues="href:url"
+                   target="_blank"></a>
+                <div class="indexeddb-size">
+                    <span>Size:</span>
+                    <span jscontent="size + ' bytes'"></span>
+                </div>
+                <div class="indexeddb-last-modified">
+                    <span>Last modified:</span>
+                    <span jscontent="new Date(last_modified)"></span>
+                </div>
+                <div class="indexeddb-last-modified">
+                    <span>Path:</span>
+                    <span jscontent="path"></span>
+                </div>
+                <div class="controls">
+                    <a href="#" class="download"
+                       jsvalues=".idb_origin_url:url;.idb_partition_path:$partition_path">Download</a>
+                    <span class="download-status" style="display: none">Loading...</span>
+                </div>
+            </div>
+        </div>
+    </div>
+    <h1>IndexedDB</h1>
+    <div class="content">
+        <div id="indexeddb-list">
+    </div>
+    <script src="chrome://resources/js/util.js"></script>
+    <script src="chrome://resources/js/cr.js"></script>
+    <script src="indexeddb_internals.js"></script>
+    <script src="chrome://resources/js/load_time_data.js"></script>
+    <script src="chrome://resources/js/jstemplate_compiled.js"></script>
+    <script src="strings.js"></script>
+    <script src="chrome://resources/js/i18n_template2.js"></script>
+</body>
+</html>
+
diff --git a/content/browser/resources/indexed_db/indexeddb_internals.js b/content/browser/resources/indexed_db/indexeddb_internals.js
new file mode 100644
index 0000000..378b9ad
--- /dev/null
+++ b/content/browser/resources/indexed_db/indexeddb_internals.js
@@ -0,0 +1,59 @@
+// Copyright (c) 2013 The Chromium 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('indexeddb', function() {
+  'use strict';
+
+  function initialize() {
+    chrome.send('getAllOrigins');
+  }
+
+  function progressNodeFor(link) {
+    return link.parentNode.querySelector('.download-status');
+  }
+
+  function downloadOriginData(event) {
+    var link = event.target;
+    progressNodeFor(link).style.display = 'inline';
+    chrome.send('downloadOriginData', [link.idb_partition_path,
+                                       link.idb_origin_url]);
+    return false;
+  }
+
+  // Fired from the backend after the data has been zipped up, and the
+  // download manager has begun downloading the file.
+  function onOriginDownloadReady(partition_path, origin_url) {
+    var downloadLinks = document.querySelectorAll('a.download');
+    for (var i = 0; i < downloadLinks.length; ++i) {
+      var link = downloadLinks[i];
+      if (partition_path == link.idb_partition_path &&
+          origin_url == link.idb_origin_url) {
+        progressNodeFor(link).style.display = 'none';
+      }
+    }
+  }
+
+  // Fired from the backend with a single partition's worth of
+  // IndexedDB metadata.
+  function onOriginsReady(origins, partition_path) {
+    var template = jstGetTemplate('indexeddb-list-template');
+    var container = $('indexeddb-list');
+    container.appendChild(template);
+    jstProcess(new JsEvalContext({ idbs: origins,
+                                   partition_path: partition_path}), template);
+
+    var downloadLinks = container.querySelectorAll('a.download');
+    for (var i = 0; i < downloadLinks.length; ++i) {
+      downloadLinks[i].addEventListener('click', downloadOriginData, false);
+    }
+  }
+
+  return {
+    initialize: initialize,
+    onOriginDownloadReady: onOriginDownloadReady,
+    onOriginsReady: onOriginsReady,
+  };
+});
+
+document.addEventListener('DOMContentLoaded', indexeddb.initialize);
diff --git a/content/browser/resources/media/dump_creator.js b/content/browser/resources/media/dump_creator.js
new file mode 100644
index 0000000..3770e48
--- /dev/null
+++ b/content/browser/resources/media/dump_creator.js
@@ -0,0 +1,112 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+
+/**
+ * Provides the UI to start and stop RTP recording, forwards the start/stop
+ * commands to Chrome, and updates the UI based on dump updates.
+ *
+ * @param {Element} containerElement The parent element of the dump creation UI.
+ */
+var DumpCreator = (function() {
+  /**
+   * @param {Element} containerElement The parent element of the dump creation
+   *     UI.
+   * @constructor
+   */
+  function DumpCreator(containerElement) {
+    /**
+     * True if the RTP packets are being recorded.
+     * @type {bool}
+     * @private
+     */
+    this.recording_ = false;
+
+    /**
+     * @type {!Object.<string>}
+     * @private
+     * @const
+     */
+    this.StatusStrings_ = {
+      NOT_STARTED: 'not started.',
+      RECORDING: 'recording...',
+    },
+
+    /**
+     * The status of dump creation.
+     * @type {string}
+     * @private
+     */
+    this.status_ = this.StatusStrings_.NOT_STARTED;
+
+    /**
+     * The root element of the dump creation UI.
+     * @type {Element}
+     * @private
+     */
+    this.root_ = document.createElement('details');
+
+    this.root_.className = 'peer-connection-dump-root';
+    containerElement.appendChild(this.root_);
+    var summary = document.createElement('summary');
+    this.root_.appendChild(summary);
+    summary.textContent = 'Create Dump';
+    var content = document.createElement('pre');
+    this.root_.appendChild(content);
+    content.innerHTML = '<button></button> Status: <span></span>';
+    content.getElementsByTagName('button')[0].addEventListener(
+        'click', this.onToggled_.bind(this));
+
+    this.updateDisplay_();
+  }
+
+  DumpCreator.prototype = {
+    /**
+     * Handles the event of toggling the dump recording state.
+     *
+     * @private
+     */
+    onToggled_: function() {
+      if (this.recording_) {
+        this.recording_ = false;
+        this.status_ = this.StatusStrings_.NOT_STARTED;
+        chrome.send('stopRtpRecording');
+      } else {
+        this.recording_ = true;
+        this.status_ = this.StatusStrings_.RECORDING;
+        chrome.send('startRtpRecording');
+      }
+      this.updateDisplay_();
+    },
+
+    /**
+     * Updates the UI based on the recording status.
+     *
+     * @private
+     */
+    updateDisplay_: function() {
+      if (this.recording_) {
+        this.root_.getElementsByTagName('button')[0].textContent =
+            'Stop Recording RTP Packets';
+      } else {
+        this.root_.getElementsByTagName('button')[0].textContent =
+            'Start Recording RTP Packets';
+      }
+
+      this.root_.getElementsByTagName('span')[0].textContent = this.status_;
+    },
+
+    /**
+     * Set the status to the content of the update.
+     * @param {!Object} update
+     */
+    onUpdate: function(update) {
+      if (this.recording_) {
+        this.status_ = JSON.stringify(update);
+        this.updateDisplay_();
+      }
+    },
+  };
+  return DumpCreator;
+})();
diff --git a/content/browser/resources/media/peer_connection_update_table.js b/content/browser/resources/media/peer_connection_update_table.js
new file mode 100644
index 0000000..facbefa
--- /dev/null
+++ b/content/browser/resources/media/peer_connection_update_table.js
@@ -0,0 +1,128 @@
+// Copyright (c) 2013 The Chromium 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 data of a peer connection update.
+ * @param {number} pid The id of the renderer.
+ * @param {number} lid The id of the peer conneciton inside a renderer.
+ * @param {string} type The type of the update.
+ * @param {string} value The details of the update.
+ * @constructor
+ */
+var PeerConnectionUpdateEntry = function(pid, lid, type, value) {
+  /**
+   * @type {number}
+   */
+  this.pid = pid;
+
+  /**
+   * @type {number}
+   */
+  this.lid = lid;
+
+  /**
+   * @type {string}
+   */
+  this.type = type;
+
+  /**
+   * @type {string}
+   */
+  this.value = value;
+};
+
+
+/**
+ * Maintains the peer connection update log table.
+ */
+var PeerConnectionUpdateTable = (function() {
+  'use strict';
+
+  /**
+   * @constructor
+   */
+  function PeerConnectionUpdateTable() {
+    /**
+     * @type {string}
+     * @const
+     * @private
+     */
+    this.UPDATE_LOG_ID_SUFFIX_ = '-update-log';
+
+    /**
+     * @type {string}
+     * @const
+     * @private
+     */
+    this.UPDATE_LOG_CONTAINER_CLASS_ = 'update-log-container';
+
+    /**
+     * @type {string}
+     * @const
+     * @private
+     */
+    this.UPDATE_LOG_TABLE_CLASS_ = 'update-log-table';
+  }
+
+  PeerConnectionUpdateTable.prototype = {
+    /**
+     * Adds the update to the update table as a new row. The type of the update
+     * is set to the summary of the cell; clicking the cell will reveal or hide
+     * the details as the content of a TextArea element.
+     *
+     * @param {!Element} peerConnectionElement The root element.
+     * @param {!PeerConnectionUpdateEntry} update The update to add.
+     */
+    addPeerConnectionUpdate: function(peerConnectionElement, update) {
+      var tableElement = this.ensureUpdateContainer_(peerConnectionElement);
+
+      var row = document.createElement('tr');
+      tableElement.firstChild.appendChild(row);
+
+      row.innerHTML = '<td>' + (new Date()).toLocaleString() + '</td>';
+
+      if (update.value.length == 0) {
+        row.innerHTML += '<td>' + update.type + '</td>';
+        return;
+      }
+
+      row.innerHTML += '<td><details><summary>' + update.type +
+          '</summary></details></td>';
+
+      var valueContainer = document.createElement('pre');
+      var details = row.cells[1].childNodes[0];
+      details.appendChild(valueContainer);
+      valueContainer.textContent = update.value;
+    },
+
+    /**
+     * Makes sure the update log table of the peer connection is created.
+     *
+     * @param {!Element} peerConnectionElement The root element.
+     * @return {!Element} The log table element.
+     * @private
+     */
+    ensureUpdateContainer_: function(peerConnectionElement) {
+      var tableId = peerConnectionElement.id + this.UPDATE_LOG_ID_SUFFIX_;
+      var tableElement = $(tableId);
+      if (!tableElement) {
+        var tableContainer = document.createElement('div');
+        tableContainer.className = this.UPDATE_LOG_CONTAINER_CLASS_;
+        peerConnectionElement.appendChild(tableContainer);
+
+        tableElement = document.createElement('table');
+        tableElement.className = this.UPDATE_LOG_TABLE_CLASS_;
+        tableElement.id = tableId;
+        tableElement.border = 1;
+        tableContainer.appendChild(tableElement);
+        tableElement.innerHTML = '<tr><th>Time</th>' +
+            '<th class="update-log-header-event">Event</th></tr>';
+      }
+      return tableElement;
+    }
+  };
+
+  return PeerConnectionUpdateTable;
+})();
diff --git a/content/browser/resources/media/ssrc_info_manager.js b/content/browser/resources/media/ssrc_info_manager.js
new file mode 100644
index 0000000..8236e87
--- /dev/null
+++ b/content/browser/resources/media/ssrc_info_manager.js
@@ -0,0 +1,134 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+
+/**
+ * SsrcInfoManager stores the ssrc stream info extracted from SDP.
+ */
+var SsrcInfoManager = (function() {
+  'use strict';
+
+  /**
+   * @constructor
+   */
+  function SsrcInfoManager() {
+    /**
+     * Map from ssrc id to an object containing all the stream properties.
+     * @type {!Object.<string, !Object.<string>>}
+     * @private
+     */
+    this.streamInfoContainer_ = {};
+
+    /**
+     * The string separating attibutes in an SDP.
+     * @type {string}
+     * @const
+     * @private
+     */
+    this.ATTRIBUTE_SEPARATOR_ = /[\r,\n]/;
+
+    /**
+     * The regex separating fields within an ssrc description.
+     * @type {RegExp}
+     * @const
+     * @private
+     */
+    this.FIELD_SEPARATOR_REGEX_ = / .*:/;
+
+    /**
+     * The prefix string of an ssrc description.
+     * @type {string}
+     * @const
+     * @private
+     */
+    this.SSRC_ATTRIBUTE_PREFIX_ = 'a=ssrc:';
+
+    /**
+     * The className of the ssrc info parent element.
+     * @type {string}
+     * @const
+     * @private
+     */
+    this.SSRC_INFO_BLOCK_CLASS_ = 'ssrc-info-block';
+  }
+
+  SsrcInfoManager.prototype = {
+    /**
+     * Extracts the stream information from |sdp| and saves it.
+     * For example:
+     *     a=ssrc:1234 msid:abcd
+     *     a=ssrc:1234 label:hello
+     *
+     * @param {string} sdp The SDP string.
+     */
+    addSsrcStreamInfo: function(sdp) {
+      var attributes = sdp.split(this.ATTRIBUTE_SEPARATOR_);
+      for (var i = 0; i < attributes.length; ++i) {
+        // Check if this is a ssrc attribute.
+        if (attributes[i].indexOf(this.SSRC_ATTRIBUTE_PREFIX_) != 0)
+          continue;
+
+        var nextFieldIndex = attributes[i].search(this.FIELD_SEPARATOR_REGEX_);
+
+        if (nextFieldIndex == -1)
+          continue;
+
+        var ssrc = attributes[i].substring(this.SSRC_ATTRIBUTE_PREFIX_.length,
+                                           nextFieldIndex);
+        if (!this.streamInfoContainer_[ssrc])
+          this.streamInfoContainer_[ssrc] = {};
+
+        // Make |rest| starting at the next field.
+        var rest = attributes[i].substring(nextFieldIndex + 1);
+        var name, value;
+        while (rest.length > 0) {
+          nextFieldIndex = rest.search(this.FIELD_SEPARATOR_REGEX_);
+          if (nextFieldIndex == -1)
+            nextFieldIndex = rest.length;
+
+          // The field name is the string before the colon.
+          name = rest.substring(0, rest.indexOf(':'));
+          // The field value is from after the colon to the next field.
+          value = rest.substring(rest.indexOf(':') + 1, nextFieldIndex);
+          this.streamInfoContainer_[ssrc][name] = value;
+
+          // Move |rest| to the start of the next field.
+          rest = rest.substring(nextFieldIndex + 1);
+        }
+      }
+    },
+
+    /**
+     * @param {string} sdp The ssrc id.
+     * @return {!Object.<string>} The object containing the ssrc infomation.
+     */
+    getStreamInfo: function(ssrc) {
+      return this.streamInfoContainer_[ssrc];
+    },
+
+    /**
+     * Populate the ssrc information into |parentElement|, each field as a
+     * DIV element.
+     *
+     * @param {!Element} parentElement The parent element for the ssrc info.
+     * @param {string} ssrc The ssrc id.
+     */
+    populateSsrcInfo: function(parentElement, ssrc) {
+      if (!this.streamInfoContainer_[ssrc])
+        return;
+
+      parentElement.className = this.SSRC_INFO_BLOCK_CLASS_;
+
+      var fieldElement;
+      for (var property in this.streamInfoContainer_[ssrc]) {
+        fieldElement = document.createElement('div');
+        parentElement.appendChild(fieldElement);
+        fieldElement.textContent =
+            property + ':' + this.streamInfoContainer_[ssrc][property];
+      }
+    }
+  };
+
+  return SsrcInfoManager;
+})();
diff --git a/content/browser/resources/media/stats_graph_helper.js b/content/browser/resources/media/stats_graph_helper.js
index c56ab72..c252f0a 100644
--- a/content/browser/resources/media/stats_graph_helper.js
+++ b/content/browser/resources/media/stats_graph_helper.js
@@ -14,6 +14,8 @@
 <include src="data_series.js"/>
 <include src="timeline_graph_view.js"/>
 
+var STATS_GRAPH_CONTAINER_HEADING_CLASS = 'stats-graph-container-heading';
+
 // Specifies which stats should be drawn on the 'bweCompound' graph and how.
 var bweCompoundGraphConfig = {
   googAvailableSendBandwidth: {color: 'red'},
@@ -82,12 +84,18 @@
 
 // Adds the stats report |singleReport| to the timeline graph for the given
 // |peerConnectionElement| and |reportName|.
-function drawSingleReport(peerConnectionElement, reportName, singleReport) {
+function drawSingleReport(
+    peerConnectionElement, reportType, reportId, singleReport) {
   if (!singleReport || !singleReport.values)
     return;
+
+  var reportName = reportType + '-' + reportId;
   for (var i = 0; i < singleReport.values.length - 1; i = i + 2) {
     var rawLabel = singleReport.values[i];
     var rawValue = parseInt(singleReport.values[i + 1]);
+    if (isNaN(rawValue))
+      return;
+
     var rawDataSeriesId =
         peerConnectionElement.id + '-' + reportName + '-' + rawLabel;
 
@@ -121,7 +129,7 @@
 
     if (!graphViews[graphViewId]) {
       graphViews[graphViewId] = createStatsGraphView(peerConnectionElement,
-                                                     reportName,
+                                                     reportType, reportId,
                                                      graphType);
       var date = new Date(singleReport.timestamp);
       graphViews[graphViewId].setDateRange(date, date);
@@ -147,41 +155,43 @@
   dataSeries[dataSeriesId].addPoint(time, value);
 }
 
-// Ensures a div container to hold all stats graphs for a report type
-// is created as a child of |peerConnectionElement|.
-function ensureStatsGraphTopContainer(peerConnectionElement, reportName) {
+// Ensures a div container to hold all stats graphs for one track is created as
+// a child of |peerConnectionElement|.
+function ensureStatsGraphTopContainer(
+    peerConnectionElement, reportType, reportId) {
   var containerId = peerConnectionElement.id + '-' +
-                    reportName + '-graph-container';
+      reportType + '-' + reportId + '-graph-container';
   var container = $(containerId);
   if (!container) {
-    container = document.createElement('div');
+    container = document.createElement('details');
     container.id = containerId;
-    container.className = 'stats-graph-container-collapsed';
+    container.className = 'stats-graph-container';
 
     peerConnectionElement.appendChild(container);
-    container.innerHTML =
-        '<button>Expand/Collapse Graphs for ' + reportName + '</button>';
+    container.innerHTML ='<summary><span></span></summary>';
+    container.firstChild.firstChild.className =
+        STATS_GRAPH_CONTAINER_HEADING_CLASS;
+    container.firstChild.firstChild.textContent =
+        'Stats graphs for ' + reportType + '-' + reportId;
 
-    // Expands or collapses the graphs on click.
-    container.childNodes[0].addEventListener('click', function(event) {
-      var element = event.target.parentNode;
-      if (element.className == 'stats-graph-container-collapsed')
-        element.className = 'stats-graph-container';
-      else
-        element.className = 'stats-graph-container-collapsed';
-    });
+    if (reportType == 'ssrc') {
+      var ssrcInfoElement = document.createElement('div');
+      container.firstChild.appendChild(ssrcInfoElement);
+      ssrcInfoManager.populateSsrcInfo(ssrcInfoElement, reportId);
+    }
   }
   return container;
 }
 
 // Creates the container elements holding a timeline graph
 // and the TimelineGraphView object.
-function createStatsGraphView(peerConnectionElement, reportName, statsName) {
+function createStatsGraphView(
+    peerConnectionElement, reportType, reportId, statsName) {
   var topContainer = ensureStatsGraphTopContainer(peerConnectionElement,
-                                                  reportName);
+                                                  reportType, reportId);
 
-  var graphViewId =
-      peerConnectionElement.id + '-' + reportName + '-' + statsName;
+  var graphViewId = peerConnectionElement.id + '-' +
+      reportType + '-' + reportId + '-' + statsName;
   var divId = graphViewId + '-div';
   var canvasId = graphViewId + '-canvas';
   var container = document.createElement("div");
@@ -191,9 +201,10 @@
   container.innerHTML = '<div>' + statsName + '</div>' +
       '<div id=' + divId + '><canvas id=' + canvasId + '></canvas></div>';
   if (statsName == 'bweCompound') {
-      container.insertBefore(createBweCompoundLegend(peerConnectionElement,
-                                                     reportName),
-                             $(divId));
+      container.insertBefore(
+          createBweCompoundLegend(
+              peerConnectionElement, reportType + '-' + reportId),
+          $(divId));
   }
   return new TimelineGraphView(divId, canvasId);
 }
diff --git a/content/browser/resources/media/stats_table.js b/content/browser/resources/media/stats_table.js
new file mode 100644
index 0000000..d31c73a
--- /dev/null
+++ b/content/browser/resources/media/stats_table.js
@@ -0,0 +1,139 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+
+/**
+ * Maintains the stats table.
+ * @param {SsrcInfoManager} ssrcInfoManager The source of the ssrc info.
+ */
+var StatsTable = (function(ssrcInfoManager) {
+  'use strict';
+
+  /**
+   * @param {SsrcInfoManager} ssrcInfoManager The source of the ssrc info.
+   * @constructor
+   */
+  function StatsTable(ssrcInfoManager) {
+    /**
+     * @type {SsrcInfoManager}
+     * @private
+     */
+    this.ssrcInfoManager_ = ssrcInfoManager;
+  }
+
+  StatsTable.prototype = {
+    /**
+     * Adds |report| to the stats table of |peerConnectionElement|.
+     *
+     * @param {!Element} peerConnectionElement The root element.
+     * @param {!Object} report The object containing stats, which is the object
+     *     containing timestamp and values, which is an array of strings, whose
+     *     even index entry is the name of the stat, and the odd index entry is
+     *     the value.
+     */
+    addStatsReport: function(peerConnectionElement, report) {
+      var statsTable = this.ensureStatsTable_(peerConnectionElement, report);
+
+      if (report.stats) {
+        this.addStatsToTable_(statsTable,
+                              report.stats.timestamp, report.stats.values);
+      }
+    },
+
+    /**
+     * Ensure the DIV container for the stats tables is created as a child of
+     * |peerConnectionElement|.
+     *
+     * @param {!Element} peerConnectionElement The root element.
+     * @return {!Element} The stats table container.
+     * @private
+     */
+    ensureStatsTableContainer_: function(peerConnectionElement) {
+      var containerId = peerConnectionElement.id + '-table-container';
+      var container = $(containerId);
+      if (!container) {
+        container = document.createElement('div');
+        container.id = containerId;
+        container.className = 'stats-table-container';
+        peerConnectionElement.appendChild(container);
+      }
+      return container;
+    },
+
+    /**
+     * Ensure the stats table for track specified by |report| of PeerConnection
+     * |peerConnectionElement| is created.
+     *
+     * @param {!Element} peerConnectionElement The root element.
+     * @param {!Object} report The object containing stats, which is the object
+     *     containing timestamp and values, which is an array of strings, whose
+     *     even index entry is the name of the stat, and the odd index entry is
+     *     the value.
+     * @return {!Element} The stats table element.
+     * @private
+     */
+     ensureStatsTable_: function(peerConnectionElement, report) {
+      var tableId = peerConnectionElement.id + '-table-' +
+          report.type + '-' + report.id;
+      var table = $(tableId);
+      if (!table) {
+        var container = this.ensureStatsTableContainer_(peerConnectionElement);
+        table = document.createElement('table');
+        container.appendChild(table);
+        table.id = tableId;
+        table.border = 1;
+
+        table.innerHTML = '<tr><th colspan=2></th></tr>';
+        table.rows[0].cells[0].textContent =
+            'Statistics ' + report.type + '-' + report.id;
+        if (report.type == 'ssrc') {
+            table.insertRow(1);
+            table.rows[1].innerHTML = '<td colspan=2></td>';
+            this.ssrcInfoManager_.populateSsrcInfo(
+                table.rows[1].cells[0], report.id);
+        }
+      }
+      return table;
+    },
+
+    /**
+     * Update |statsTable| with |time| and |statsData|.
+     *
+     * @param {!Element} statsTable Which table to update.
+     * @param {number} time The number of miliseconds since epoch.
+     * @param {Array.<string>} statsData An array of stats name and value pairs.
+     * @private
+     */
+    addStatsToTable_: function(statsTable, time, statsData) {
+      var date = Date(time);
+      this.updateStatsTableRow_(statsTable, 'timestamp', date.toLocaleString());
+      for (var i = 0; i < statsData.length - 1; i = i + 2) {
+        this.updateStatsTableRow_(statsTable, statsData[i], statsData[i + 1]);
+      }
+    },
+
+    /**
+     * Update the value column of the stats row of |rowName| to |value|.
+     * A new row is created is this is the first report of this stats.
+     *
+     * @param {!Element} statsTable Which table to update.
+     * @param {string} rowName The name of the row to update.
+     * @param {string} value The new value to set.
+     * @private
+     */
+    updateStatsTableRow_: function(statsTable, rowName, value) {
+      var trId = statsTable.id + '-' + rowName;
+      var trElement = $(trId);
+      if (!trElement) {
+        trElement = document.createElement('tr');
+        trElement.id = trId;
+        statsTable.firstChild.appendChild(trElement);
+        trElement.innerHTML = '<td>' + rowName + '</td><td></td>';
+      }
+      trElement.cells[1].textContent = value;
+    }
+  };
+
+  return StatsTable;
+})();
diff --git a/content/browser/resources/media/webrtc_internals.css b/content/browser/resources/media/webrtc_internals.css
index 83d1f39..c0ac402 100644
--- a/content/browser/resources/media/webrtc_internals.css
+++ b/content/browser/resources/media/webrtc_internals.css
@@ -2,25 +2,33 @@
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file. */
 
-.log-container {
+
+.peer-connection-dump-root {
+  font-size: 0.8em;
+  padding-bottom: 3px;
+}
+
+.peer-connection-hidden > *:not(h3) {
+  display:none;
+}
+
+.update-log-container {
   float: left;
 }
 
-.stats-graph-container,
-.stats-graph-container-collapsed {
+.ssrc-info-block {
+  color: #999;
+  font-size: 0.8em;
+}
+
+.stats-graph-container {
   clear: both;
   margin: 0.5em 0 0.5em 0;
 }
 
-.stats-graph-container button,
-.stats-graph-container-collapsed button {
-  display: block;
-  margin: 0;
-  padding: 0;
-}
-
-.stats-graph-container-collapsed .stats-graph-sub-container {
-  display: none;
+.stats-graph-container-heading {
+  font-size: 0.8em;
+  font-weight: bold;
 }
 
 .stats-graph-sub-container {
@@ -47,7 +55,7 @@
 }
 
 details {
-  width: 30em;
+  min-width: 30em;
 }
 
 h3 + div {
@@ -64,9 +72,11 @@
 }
 
 h3 {
-  color: #666;
+  color: #555;
+  cursor: pointer;
   font-size: 0.9em;
-  margin: 1em 0 0.5em 0;
+  margin: 2em 0 0.5em 0;
+  text-decoration: underline;
 }
 
 li {
@@ -91,12 +101,6 @@
   padding-top: 0.3em;
 }
 
-textarea {
-  border: none;
-  outline: none;
-  width: 100%;
-}
-
 table > tr {
   vertical-align: top;
 }
diff --git a/content/browser/resources/media/webrtc_internals.js b/content/browser/resources/media/webrtc_internals.js
index 77faaf8..1fa0faf 100644
--- a/content/browser/resources/media/webrtc_internals.js
+++ b/content/browser/resources/media/webrtc_internals.js
@@ -2,212 +2,172 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-<include src="stats_graph_helper.js"/>
 
 var peerConnectionsListElem = null;
+var ssrcInfoManager = null;
+var peerConnectionUpdateTable = null;
+var statsTable = null;
+var dumpCreator = null;
+
+<include src="ssrc_info_manager.js"/>
+<include src="stats_graph_helper.js"/>
+<include src="stats_table.js"/>
+<include src="peer_connection_update_table.js"/>
+<include src="dump_creator.js"/>
 
 function initialize() {
   peerConnectionsListElem = $('peer-connections-list');
+  dumpCreator = new DumpCreator(peerConnectionsListElem);
+  ssrcInfoManager = new SsrcInfoManager();
+  peerConnectionUpdateTable = new PeerConnectionUpdateTable();
+  statsTable = new StatsTable(ssrcInfoManager);
+
   chrome.send('getAllUpdates');
-  startGetStats();
-}
 
-// Polls stats from all PeerConnections every second.
-function startGetStats() {
-  if (document.getElementsByTagName('li').length)
-    chrome.send('getAllStats');
-  window.setTimeout(startGetStats, 1000);
+  // Requests stats from all peer connections every second.
+  window.setInterval(function() {
+    if (peerConnectionsListElem.getElementsByTagName('li').length > 0)
+      chrome.send('getAllStats');
+  }, 1000);
 }
+document.addEventListener('DOMContentLoaded', initialize);
 
+
+/**
+ * A helper function for getting a peer connection element id.
+ *
+ * @param {!Object.<string, number>} data The object containing the pid and lid
+ *     of the peer connection.
+ * @return {string} The peer connection element id.
+ */
 function getPeerConnectionId(data) {
   return data.pid + '-' + data.lid;
 }
 
-// Makes sure a LI element representing a PeerConnection is created
-// and appended to peerConnectionListElem.
-function ensurePeerConnectionElement(id) {
-  var element = $(id);
-  if (!element) {
-    element = document.createElement('li');
-    peerConnectionsListElem.appendChild(element);
-    element.id = id;
-  }
-  return element;
-}
 
-// Makes sure the table representing the PeerConnection event log is created
-// and appended to peerConnectionElement.
-function ensurePeerConnectionLog(peerConnectionElement) {
-  var logId = peerConnectionElement.id + '-log';
-  var logElement = $(logId);
-  if (!logElement) {
-    var container = document.createElement('div');
-    container.className = 'log-container';
-    peerConnectionElement.appendChild(container);
-
-    logElement = document.createElement('table');
-    logElement.id = logId;
-    logElement.className = 'log-table';
-    logElement.border = 1;
-    container.appendChild(logElement);
-    logElement.innerHTML = '<tr><th>Time</th>' +
-                           '<th class="log-header-event">Event</th></tr>';
-  }
-  return logElement;
-}
-
-// Add the update to the log table as a new row. The type of the update is set
-// as the text of the cell; clicking the cell will reveal or hide the details
-// as the content of a TextArea element.
-function addToPeerConnectionLog(logElement, update) {
-  var row = document.createElement('tr');
-  logElement.appendChild(row);
-
-  var expandable = (update.value.length > 0);
-  // details.open is true initially so that we can get the real scrollHeight
-  // of the textareas.
-  row.innerHTML =
-      '<td>' + (new Date()).toLocaleString() + '</td>' +
-      (expandable ?
-          '<td><details open><summary>' + update.type + '</summary>' +
-              '</details></td>' :
-          '<td>' + update.type + '</td>');
-  if (!expandable)
-    return;
-
-  var valueContainer = document.createElement('textarea');
-  var details = row.cells[1].childNodes[0];
-  details.appendChild(valueContainer);
-  valueContainer.value = update.value;
-  valueContainer.style.height = valueContainer.scrollHeight + 'px';
-  details.open = false;
-}
-
-// Ensure the DIV container for the stats tables is created as a child of
-// |peerConnectionElement|.
-function ensureStatsTableContainer(peerConnectionElement) {
-  var containerId = peerConnectionElement.id + '-table-container';
-  var container = $(containerId);
-  if (!container) {
-    container = document.createElement('div');
-    container.id = containerId;
-    container.className = 'stats-table-container';
-    peerConnectionElement.appendChild(container);
-  }
-  return container;
-}
-
-// Ensure the stats table for track |statsId| of PeerConnection
-// |peerConnectionElement| is created as a child of the stats table container.
-function ensureStatsTable(peerConnectionElement, statsId) {
-  var tableId = peerConnectionElement.id + '-table-' + statsId;
-  var table = $(tableId);
-  if (!table) {
-    var container = ensureStatsTableContainer(peerConnectionElement);
-    table = document.createElement('table');
-    container.appendChild(table);
-    table.id = tableId;
-    table.border = 1;
-    table.innerHTML = '<th>Statistics ' + statsId + '</th>';
-  }
-  return table;
-}
-
-// Update the value column of the stats row of |rowName| to |value|.
-// A new row is created is this is the first report of this stats.
-function updateStatsTableRow(statsTable, rowName, value) {
-  var trId = statsTable.id + '-' + rowName;
-  var trElement = $(trId);
-  if (!trElement) {
-    trElement = document.createElement('tr');
-    trElement.id = trId;
-    statsTable.appendChild(trElement);
-    trElement.innerHTML = '<td>' + rowName + '</td><td></td>';
-  }
-  trElement.cells[1].textContent = value;
-}
-
-// Add |singleReport| to the stats table.
-function addSingleReportToTable(statsTable, singleReport) {
-  if (!singleReport || !singleReport.values || singleReport.values.length == 0)
-    return;
-
-  var date = Date(singleReport.timestamp);
-  updateStatsTableRow(statsTable, 'timestamp', date.toLocaleString());
-  for (var i = 0; i < singleReport.values.length - 1; i = i + 2) {
-    updateStatsTableRow(statsTable, singleReport.values[i],
-                        singleReport.values[i + 1]);
+/**
+ * Extracts ssrc info from a setLocal/setRemoteDescription update.
+ *
+ * @param {!PeerConnectionUpdateEntry} data The peer connection update data.
+ */
+function extractSsrcInfo(data) {
+  if (data.type == 'setLocalDescription' ||
+      data.type == 'setRemoteDescription') {
+    ssrcInfoManager.addSsrcStreamInfo(data.value);
   }
 }
 
-//
-// Browser message handlers.
-//
 
-// data = {pid:|integer|, lid:|integer|}.
+/**
+ * Browser message handlers.
+ */
+
+
+/**
+ * Removes all information about a peer connection.
+ *
+ * @param {!Object.<string, number>} data The object containing the pid and lid
+ *     of a peer connection.
+ */
 function removePeerConnection(data) {
   var element = $(getPeerConnectionId(data));
   if (element)
     peerConnectionsListElem.removeChild(element);
 }
 
-// data = {pid:|integer|, lid:|integer|,
-//         url:|string|, servers:|string|, constraints:|string|}.
+
+/**
+ * Adds a peer connection.
+ *
+ * @param {!Object} data The object containing the pid, lid, url, servers, and
+ *     constraints of a peer connection.
+ */
 function addPeerConnection(data) {
-  var peerConnectionElement = ensurePeerConnectionElement(
-      getPeerConnectionId(data));
+  var peerConnectionElement = $(getPeerConnectionId(data));
+  if (!peerConnectionElement) {
+    peerConnectionElement = document.createElement('li');
+    peerConnectionsListElem.appendChild(peerConnectionElement);
+    peerConnectionElement.id = getPeerConnectionId(data);
+  }
   peerConnectionElement.innerHTML =
       '<h3>PeerConnection ' + peerConnectionElement.id + '</h3>' +
       '<div>' + data.url + ' ' + data.servers + ' ' + data.constraints +
       '</div>';
+
+  // Clicking the heading can expand or collapse the peer connection item.
+  peerConnectionElement.firstChild.title = 'Click to collapse or expand';
+  peerConnectionElement.firstChild.addEventListener('click', function(e) {
+    if (e.target.parentElement.className == '')
+      e.target.parentElement.className = 'peer-connection-hidden';
+    else
+      e.target.parentElement.className = '';
+  });
   return peerConnectionElement;
 }
 
-// data = {pid:|integer|, lid:|integer|, type:|string|, value:|string|}.
+
+/**
+ * Adds a peer connection update.
+ *
+ * @param {!PeerConnectionUpdateEntry} data The peer connection update data.
+ */
 function updatePeerConnection(data) {
-  var peerConnectionElement = ensurePeerConnectionElement(
-      getPeerConnectionId(data));
-  var logElement = ensurePeerConnectionLog(peerConnectionElement);
-  addToPeerConnectionLog(logElement, data);
+  var peerConnectionElement = $(getPeerConnectionId(data));
+  peerConnectionUpdateTable.addPeerConnectionUpdate(
+      peerConnectionElement, data);
+  extractSsrcInfo(data);
 }
 
-// data is an array and each entry is
-// {pid:|integer|, lid:|integer|,
-//  url:|string|, servers:|string|, constraints:|string|, log:|array|},
-// each entry of log is {type:|string|, value:|string|}.
+
+/**
+ * Adds the information of all peer connections created so far.
+ *
+ * @param {Array.<!Object>} data An array of the information of all peer
+ *     connections. Each array item contains pid, lid, url, servers,
+ *     constraints, and an array of updates as the log.
+ */
 function updateAllPeerConnections(data) {
   for (var i = 0; i < data.length; ++i) {
     var peerConnection = addPeerConnection(data[i]);
-    var logElement = ensurePeerConnectionLog(peerConnection);
 
     var log = data[i].log;
     for (var j = 0; j < log.length; ++j) {
-      addToPeerConnectionLog(logElement, log[j]);
+      peerConnectionUpdateTable.addPeerConnectionUpdate(
+          peerConnection, log[j]);
+      extractSsrcInfo(log[j]);
     }
   }
 }
 
-// data = {pid:|integer|, lid:|integer|, reports:|array|}.
-// Each entry of reports =
-// {id:|string|, type:|string|, local:|object|, remote:|object|}.
-// reports.local or reports.remote =
-// {timestamp: |double|, values: |array|},
-// where values is an array of strings, whose even index entry represents
-// the name of the stat, and the odd index entry represents the value of
-// the stat.
+
+/**
+ * Handles the report of stats.
+ *
+ * @param {!Object} data The object containing pid, lid, and reports, where
+ *     reports is an array of stats reports. Each report contains id, type,
+ *     and stats, where stats is the object containing timestamp and values,
+ *     which is an array of strings, whose even index entry is the name of the
+ *     stat, and the odd index entry is the value.
+ */
 function addStats(data) {
-  var peerConnectionElement = ensurePeerConnectionElement(
-      getPeerConnectionId(data));
+  var peerConnectionElement = $(getPeerConnectionId(data));
+  if (!peerConnectionElement)
+    return;
+
   for (var i = 0; i < data.reports.length; ++i) {
     var report = data.reports[i];
-    var reportName = report.type + '-' + report.id;
-    var statsTable = ensureStatsTable(peerConnectionElement, reportName);
-
-    addSingleReportToTable(statsTable, report.local);
-    drawSingleReport(peerConnectionElement, reportName, report.local);
-    addSingleReportToTable(statsTable, report.remote);
-    drawSingleReport(peerConnectionElement, reportName, report.remote);
+    statsTable.addStatsReport(peerConnectionElement, report);
+    drawSingleReport(peerConnectionElement,
+                     report.type, report.id, report.stats);
   }
 }
 
-document.addEventListener('DOMContentLoaded', initialize);
+
+/**
+ * Delegates to dumpCreator to update the recording status.
+ * @param {!Object.<string>} update Key-value pairs describing the status of the
+ *     RTP recording.
+ */
+function updateDumpStatus(update) {
+  dumpCreator.onUpdate(update);
+}
diff --git a/content/browser/session_history_browsertest.cc b/content/browser/session_history_browsertest.cc
index cd70207..cb5d100 100644
--- a/content/browser/session_history_browsertest.cc
+++ b/content/browser/session_history_browsertest.cc
@@ -14,7 +14,7 @@
 #include "content/shell/shell.h"
 #include "content/test/content_browser_test.h"
 #include "content/test/content_browser_test_utils.h"
-#include "net/test/test_server.h"
+#include "net/test/spawned_test_server.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace content {
diff --git a/content/browser/site_instance_impl_unittest.cc b/content/browser/site_instance_impl_unittest.cc
index a66e5c8..fb322b1 100644
--- a/content/browser/site_instance_impl_unittest.cc
+++ b/content/browser/site_instance_impl_unittest.cc
@@ -92,8 +92,7 @@
   }
 
   virtual void SetUp() {
-    old_browser_client_ = GetContentClient()->browser();
-    GetContentClient()->set_browser_for_testing(&browser_client_);
+    old_browser_client_ = SetBrowserClientForTesting(&browser_client_);
     url_util::AddStandardScheme(kPrivilegedScheme);
     url_util::AddStandardScheme(chrome::kChromeUIScheme);
   }
@@ -102,7 +101,7 @@
     // Ensure that no RenderProcessHosts are left over after the tests.
     EXPECT_TRUE(RenderProcessHost::AllHostsIterator().IsAtEnd());
 
-    GetContentClient()->set_browser_for_testing(old_browser_client_);
+    SetBrowserClientForTesting(old_browser_client_);
 
     // http://crbug.com/143565 found SiteInstanceTest leaking an
     // AppCacheDatabase. This happens because some part of the test indirectly
@@ -124,12 +123,12 @@
     // We don't just do this in TearDown() because we create TestBrowserContext
     // objects in each test, which will be destructed before
     // TearDown() is called.
-    MessageLoop::current()->RunUntilIdle();
+    base::MessageLoop::current()->RunUntilIdle();
     message_loop_.RunUntilIdle();
   }
 
  private:
-  MessageLoopForUI message_loop_;
+  base::MessageLoopForUI message_loop_;
   TestBrowserThread ui_thread_;
   TestBrowserThread file_user_blocking_thread_;
   TestBrowserThread io_thread_;
diff --git a/content/browser/site_per_process_browsertest.cc b/content/browser/site_per_process_browsertest.cc
index d4af058..0989c7a 100644
--- a/content/browser/site_per_process_browsertest.cc
+++ b/content/browser/site_per_process_browsertest.cc
@@ -166,9 +166,9 @@
 // security checks are back in place.
 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, DISABLED_CrossSiteIframe) {
   ASSERT_TRUE(test_server()->Start());
-  net::TestServer https_server(
-      net::TestServer::TYPE_HTTPS,
-      net::TestServer::kLocalhost,
+  net::SpawnedTestServer https_server(
+      net::SpawnedTestServer::TYPE_HTTPS,
+      net::SpawnedTestServer::kLocalhost,
       base::FilePath(FILE_PATH_LITERAL("content/test/data")));
   ASSERT_TRUE(https_server.Start());
   GURL main_url(test_server()->GetURL("files/site_per_process_main.html"));
@@ -198,9 +198,9 @@
 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
                        DISABLED_CrossSiteIframeRedirectOnce) {
   ASSERT_TRUE(test_server()->Start());
-  net::TestServer https_server(
-      net::TestServer::TYPE_HTTPS,
-      net::TestServer::kLocalhost,
+  net::SpawnedTestServer https_server(
+      net::SpawnedTestServer::TYPE_HTTPS,
+      net::SpawnedTestServer::kLocalhost,
       base::FilePath(FILE_PATH_LITERAL("content/test/data")));
   ASSERT_TRUE(https_server.Start());
 
@@ -322,9 +322,9 @@
 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
                        DISABLED_CrossSiteIframeRedirectTwice) {
   ASSERT_TRUE(test_server()->Start());
-  net::TestServer https_server(
-      net::TestServer::TYPE_HTTPS,
-      net::TestServer::kLocalhost,
+  net::SpawnedTestServer https_server(
+      net::SpawnedTestServer::TYPE_HTTPS,
+      net::SpawnedTestServer::kLocalhost,
       base::FilePath(FILE_PATH_LITERAL("content/test/data")));
   ASSERT_TRUE(https_server.Start());
 
diff --git a/content/browser/speech/audio_encoder.cc b/content/browser/speech/audio_encoder.cc
index 73bbd41..e1a407b 100644
--- a/content/browser/speech/audio_encoder.cc
+++ b/content/browser/speech/audio_encoder.cc
@@ -88,7 +88,7 @@
 
   // FLAC encoder wants samples as int32s.
   const int num_samples = raw_audio.NumSamples();
-  scoped_array<FLAC__int32> flac_samples(new FLAC__int32[num_samples]);
+  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] = static_cast<FLAC__int32>(raw_audio.GetSample16(i));
diff --git a/content/browser/speech/google_one_shot_remote_engine_unittest.cc b/content/browser/speech/google_one_shot_remote_engine_unittest.cc
index efcf84f..7f06f86 100644
--- a/content/browser/speech/google_one_shot_remote_engine_unittest.cc
+++ b/content/browser/speech/google_one_shot_remote_engine_unittest.cc
@@ -43,7 +43,7 @@
   }
 
  protected:
-  MessageLoop message_loop_;
+  base::MessageLoop message_loop_;
   net::TestURLFetcherFactory url_fetcher_factory_;
   SpeechRecognitionErrorCode error_;
   SpeechRecognitionResults results_;
@@ -104,7 +104,7 @@
   EXPECT_EQ(0U, result().hypotheses.size());
 
   // Http failure case.
-  CreateAndTestRequest(false, "");
+  CreateAndTestRequest(false, std::string());
   EXPECT_EQ(error_, SPEECH_RECOGNITION_ERROR_NETWORK);
   EXPECT_EQ(0U, result().hypotheses.size());
 
diff --git a/content/browser/speech/google_streaming_remote_engine_unittest.cc b/content/browser/speech/google_streaming_remote_engine_unittest.cc
index 8223fec..cd23d4b 100644
--- a/content/browser/speech/google_streaming_remote_engine_unittest.cc
+++ b/content/browser/speech/google_streaming_remote_engine_unittest.cc
@@ -79,7 +79,7 @@
   scoped_ptr<GoogleStreamingRemoteEngine> engine_under_test_;
   TestURLFetcherFactory url_fetcher_factory_;
   size_t last_number_of_upstream_chunks_seen_;
-  MessageLoop message_loop_;
+  base::MessageLoop message_loop_;
   std::string response_buffer_;
   SpeechRecognitionErrorCode error_;
   std::queue<SpeechRecognitionResults> results_;
diff --git a/content/browser/speech/proto/speech_proto.target.darwin-arm.mk b/content/browser/speech/proto/speech_proto.target.darwin-arm.mk
new file mode 100644
index 0000000..9e7cf38
--- /dev/null
+++ b/content/browser/speech/proto/speech_proto.target.darwin-arm.mk
@@ -0,0 +1,180 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := content_browser_speech_proto_speech_proto_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(gyp_shared_intermediate_dir)/protoc
+
+
+### Generated for rule "content_browser_speech_proto_speech_proto_gyp_speech_proto_target_genproto":
+# "{'inputs': ['../../../../tools/protoc_wrapper/protoc_wrapper.py', '$(gyp_shared_intermediate_dir)/protoc'], 'msvs_cygwin_shell': '0', 'extension': 'proto', 'outputs': ['$(gyp_shared_intermediate_dir)/pyproto/content/browser/speech/proto/%(INPUT_ROOT)s_pb2.py', '$(gyp_shared_intermediate_dir)/protoc_out/content/browser/speech/proto/%(INPUT_ROOT)s.pb.cc', '$(gyp_shared_intermediate_dir)/protoc_out/content/browser/speech/proto/%(INPUT_ROOT)s.pb.h'], 'rule_name': 'genproto', 'rule_sources': ['google_streaming_api.proto'], 'action': ['python', '../../../../tools/protoc_wrapper/protoc_wrapper.py', '--include', '', '--protobuf', '$(gyp_shared_intermediate_dir)/protoc_out/content/browser/speech/proto/%(INPUT_ROOT)s.pb.h', '--proto-in-dir', '.', '--proto-in-file', '%(INPUT_ROOT)s$(suffix $<)', '--use-system-protobuf=0', '--', '$(gyp_shared_intermediate_dir)/protoc', '--cpp_out', '$(gyp_shared_intermediate_dir)/protoc_out/content/browser/speech/proto', '--python_out', '$(gyp_shared_intermediate_dir)/pyproto/content/browser/speech/proto'], 'message': 'Generating C++ and Python code from $(RULE_SOURCES)', 'process_outputs_as_sources': '1'}":
+$(gyp_shared_intermediate_dir)/pyproto/content/browser/speech/proto/google_streaming_api_pb2.py: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/pyproto/content/browser/speech/proto/google_streaming_api_pb2.py: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
+$(gyp_shared_intermediate_dir)/pyproto/content/browser/speech/proto/google_streaming_api_pb2.py: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
+$(gyp_shared_intermediate_dir)/pyproto/content/browser/speech/proto/google_streaming_api_pb2.py: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/pyproto/content/browser/speech/proto/google_streaming_api_pb2.py: $(LOCAL_PATH)/content/browser/speech/proto/google_streaming_api.proto $(LOCAL_PATH)/tools/protoc_wrapper/protoc_wrapper.py $(gyp_shared_intermediate_dir)/protoc $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/pyproto/content/browser/speech/proto $(gyp_shared_intermediate_dir)/protoc_out/content/browser/speech/proto; cd $(gyp_local_path)/content/browser/speech/proto; python ../../../../tools/protoc_wrapper/protoc_wrapper.py --include "" --protobuf "$(gyp_shared_intermediate_dir)/protoc_out/content/browser/speech/proto/google_streaming_api.pb.h" --proto-in-dir . --proto-in-file "google_streaming_api$(suffix $<)" "--use-system-protobuf=0" -- "$(gyp_shared_intermediate_dir)/protoc" --cpp_out "$(gyp_shared_intermediate_dir)/protoc_out/content/browser/speech/proto" --python_out "$(gyp_shared_intermediate_dir)/pyproto/content/browser/speech/proto"
+
+$(gyp_shared_intermediate_dir)/protoc_out/content/browser/speech/proto/google_streaming_api.pb.cc: $(gyp_shared_intermediate_dir)/pyproto/content/browser/speech/proto/google_streaming_api_pb2.py
+$(gyp_shared_intermediate_dir)/protoc_out/content/browser/speech/proto/google_streaming_api.pb.h: $(gyp_shared_intermediate_dir)/pyproto/content/browser/speech/proto/google_streaming_api_pb2.py
+.PHONY: content_browser_speech_proto_speech_proto_gyp_rule_trigger
+content_browser_speech_proto_speech_proto_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/pyproto/content/browser/speech/proto/google_streaming_api_pb2.py
+
+### Finished generating for all rules
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/pyproto/content/browser/speech/proto/google_streaming_api_pb2.py \
+	$(gyp_shared_intermediate_dir)/protoc_out/content/browser/speech/proto/google_streaming_api.pb.cc \
+	$(gyp_shared_intermediate_dir)/protoc_out/content/browser/speech/proto/google_streaming_api.pb.h
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+$(gyp_intermediate_dir)/google_streaming_api.pb.cc: $(gyp_shared_intermediate_dir)/protoc_out/content/browser/speech/proto/google_streaming_api.pb.cc
+	mkdir -p $(@D); cp $< $@
+LOCAL_GENERATED_SOURCES := \
+	$(gyp_intermediate_dir)/google_streaming_api.pb.cc \
+	$(gyp_shared_intermediate_dir)/pyproto/content/browser/speech/proto/google_streaming_api_pb2.py \
+	$(gyp_shared_intermediate_dir)/protoc_out/content/browser/speech/proto/google_streaming_api.pb.h \
+	content_browser_speech_proto_speech_proto_gyp_rule_trigger
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS := \
+	$(gyp_shared_intermediate_dir)/protoc_out/content/browser/speech/proto
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-format \
+	-fno-tree-sra \
+	-fuse-ld=gold \
+	-Wno-psabi \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections
+
+MY_CFLAGS_C :=
+
+MY_DEFS := \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DUSE_LINUX_BREAKPAD' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_GPU=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DENABLE_LANGUAGE_DETECTION=1' \
+	'-DPROTOBUF_USE_DLLS' \
+	'-DGOOGLE_PROTOBUF_NO_RTTI' \
+	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+LOCAL_CFLAGS := $(MY_CFLAGS_C) $(MY_CFLAGS) $(MY_DEFS)
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES := \
+	$(gyp_shared_intermediate_dir)/protoc_out \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/protobuf \
+	$(LOCAL_PATH)/third_party/protobuf/src \
+	$(GYP_ABS_ANDROID_TOP_DIR)/frameworks/wilhelm/include \
+	$(GYP_ABS_ANDROID_TOP_DIR)/bionic \
+	$(GYP_ABS_ANDROID_TOP_DIR)/external/stlport/stlport
+
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES)
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-abi \
+	-Wno-error=c++0x-compat \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+### Rules for final target.
+
+LOCAL_LDFLAGS := \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-Wl,-z,relro \
+	-Wl,-z,now \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--icf=safe \
+	-Wl,--gc-sections \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_browser_speech_proto_speech_proto_gyp
+
+# Alias gyp target name.
+.PHONY: speech_proto
+speech_proto: content_browser_speech_proto_speech_proto_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/content/browser/speech/proto/speech_proto.target.darwin-x86.mk b/content/browser/speech/proto/speech_proto.target.darwin-x86.mk
new file mode 100644
index 0000000..991fe36
--- /dev/null
+++ b/content/browser/speech/proto/speech_proto.target.darwin-x86.mk
@@ -0,0 +1,179 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := content_browser_speech_proto_speech_proto_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(gyp_shared_intermediate_dir)/protoc
+
+
+### Generated for rule "content_browser_speech_proto_speech_proto_gyp_speech_proto_target_genproto":
+# "{'inputs': ['../../../../tools/protoc_wrapper/protoc_wrapper.py', '$(gyp_shared_intermediate_dir)/protoc'], 'msvs_cygwin_shell': '0', 'extension': 'proto', 'outputs': ['$(gyp_shared_intermediate_dir)/pyproto/content/browser/speech/proto/%(INPUT_ROOT)s_pb2.py', '$(gyp_shared_intermediate_dir)/protoc_out/content/browser/speech/proto/%(INPUT_ROOT)s.pb.cc', '$(gyp_shared_intermediate_dir)/protoc_out/content/browser/speech/proto/%(INPUT_ROOT)s.pb.h'], 'rule_name': 'genproto', 'rule_sources': ['google_streaming_api.proto'], 'action': ['python', '../../../../tools/protoc_wrapper/protoc_wrapper.py', '--include', '', '--protobuf', '$(gyp_shared_intermediate_dir)/protoc_out/content/browser/speech/proto/%(INPUT_ROOT)s.pb.h', '--proto-in-dir', '.', '--proto-in-file', '%(INPUT_ROOT)s$(suffix $<)', '--use-system-protobuf=0', '--', '$(gyp_shared_intermediate_dir)/protoc', '--cpp_out', '$(gyp_shared_intermediate_dir)/protoc_out/content/browser/speech/proto', '--python_out', '$(gyp_shared_intermediate_dir)/pyproto/content/browser/speech/proto'], 'message': 'Generating C++ and Python code from $(RULE_SOURCES)', 'process_outputs_as_sources': '1'}":
+$(gyp_shared_intermediate_dir)/pyproto/content/browser/speech/proto/google_streaming_api_pb2.py: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/pyproto/content/browser/speech/proto/google_streaming_api_pb2.py: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
+$(gyp_shared_intermediate_dir)/pyproto/content/browser/speech/proto/google_streaming_api_pb2.py: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
+$(gyp_shared_intermediate_dir)/pyproto/content/browser/speech/proto/google_streaming_api_pb2.py: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/pyproto/content/browser/speech/proto/google_streaming_api_pb2.py: $(LOCAL_PATH)/content/browser/speech/proto/google_streaming_api.proto $(LOCAL_PATH)/tools/protoc_wrapper/protoc_wrapper.py $(gyp_shared_intermediate_dir)/protoc $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/pyproto/content/browser/speech/proto $(gyp_shared_intermediate_dir)/protoc_out/content/browser/speech/proto; cd $(gyp_local_path)/content/browser/speech/proto; python ../../../../tools/protoc_wrapper/protoc_wrapper.py --include "" --protobuf "$(gyp_shared_intermediate_dir)/protoc_out/content/browser/speech/proto/google_streaming_api.pb.h" --proto-in-dir . --proto-in-file "google_streaming_api$(suffix $<)" "--use-system-protobuf=0" -- "$(gyp_shared_intermediate_dir)/protoc" --cpp_out "$(gyp_shared_intermediate_dir)/protoc_out/content/browser/speech/proto" --python_out "$(gyp_shared_intermediate_dir)/pyproto/content/browser/speech/proto"
+
+$(gyp_shared_intermediate_dir)/protoc_out/content/browser/speech/proto/google_streaming_api.pb.cc: $(gyp_shared_intermediate_dir)/pyproto/content/browser/speech/proto/google_streaming_api_pb2.py
+$(gyp_shared_intermediate_dir)/protoc_out/content/browser/speech/proto/google_streaming_api.pb.h: $(gyp_shared_intermediate_dir)/pyproto/content/browser/speech/proto/google_streaming_api_pb2.py
+.PHONY: content_browser_speech_proto_speech_proto_gyp_rule_trigger
+content_browser_speech_proto_speech_proto_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/pyproto/content/browser/speech/proto/google_streaming_api_pb2.py
+
+### Finished generating for all rules
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/pyproto/content/browser/speech/proto/google_streaming_api_pb2.py \
+	$(gyp_shared_intermediate_dir)/protoc_out/content/browser/speech/proto/google_streaming_api.pb.cc \
+	$(gyp_shared_intermediate_dir)/protoc_out/content/browser/speech/proto/google_streaming_api.pb.h
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+$(gyp_intermediate_dir)/google_streaming_api.pb.cc: $(gyp_shared_intermediate_dir)/protoc_out/content/browser/speech/proto/google_streaming_api.pb.cc
+	mkdir -p $(@D); cp $< $@
+LOCAL_GENERATED_SOURCES := \
+	$(gyp_intermediate_dir)/google_streaming_api.pb.cc \
+	$(gyp_shared_intermediate_dir)/pyproto/content/browser/speech/proto/google_streaming_api_pb2.py \
+	$(gyp_shared_intermediate_dir)/protoc_out/content/browser/speech/proto/google_streaming_api.pb.h \
+	content_browser_speech_proto_speech_proto_gyp_rule_trigger
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS := \
+	$(gyp_shared_intermediate_dir)/protoc_out/content/browser/speech/proto
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS := \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-format \
+	-m32 \
+	-mmmx \
+	-march=pentium4 \
+	-msse2 \
+	-mfpmath=sse \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-fno-stack-protector \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections
+
+MY_CFLAGS_C :=
+
+MY_DEFS := \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DUSE_LINUX_BREAKPAD' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_GPU=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DENABLE_LANGUAGE_DETECTION=1' \
+	'-DPROTOBUF_USE_DLLS' \
+	'-DGOOGLE_PROTOBUF_NO_RTTI' \
+	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+LOCAL_CFLAGS := $(MY_CFLAGS_C) $(MY_CFLAGS) $(MY_DEFS)
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES := \
+	$(gyp_shared_intermediate_dir)/protoc_out \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/protobuf \
+	$(LOCAL_PATH)/third_party/protobuf/src \
+	$(GYP_ABS_ANDROID_TOP_DIR)/frameworks/wilhelm/include \
+	$(GYP_ABS_ANDROID_TOP_DIR)/bionic \
+	$(GYP_ABS_ANDROID_TOP_DIR)/external/stlport/stlport
+
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES)
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-error=c++0x-compat \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+### Rules for final target.
+
+LOCAL_LDFLAGS := \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m32 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_browser_speech_proto_speech_proto_gyp
+
+# Alias gyp target name.
+.PHONY: speech_proto
+speech_proto: content_browser_speech_proto_speech_proto_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/content/browser/speech/proto/speech_proto.target.linux-arm.mk b/content/browser/speech/proto/speech_proto.target.linux-arm.mk
index 951ff80..9e7cf38 100644
--- a/content/browser/speech/proto/speech_proto.target.linux-arm.mk
+++ b/content/browser/speech/proto/speech_proto.target.linux-arm.mk
@@ -92,7 +92,6 @@
 MY_CFLAGS_C :=
 
 MY_DEFS := \
-	'-DUSE_SKIA' \
 	'-D_FILE_OFFSET_BITS=64' \
 	'-DUSE_LINUX_BREAKPAD' \
 	'-DNO_TCMALLOC' \
@@ -100,7 +99,6 @@
 	'-DCHROMIUM_BUILD' \
 	'-DUSE_LIBJPEG_TURBO=1' \
 	'-DUSE_PROPRIETARY_CODECS' \
-	'-DENABLE_PEPPER_THREADING' \
 	'-DENABLE_GPU=1' \
 	'-DUSE_OPENSSL=1' \
 	'-DENABLE_EGLIMAGE=1' \
@@ -157,9 +155,9 @@
 	-Wl,--no-undefined \
 	-Wl,--exclude-libs=ALL \
 	-Wl,--icf=safe \
+	-Wl,--gc-sections \
 	-Wl,-O1 \
-	-Wl,--as-needed \
-	-Wl,--gc-sections
+	-Wl,--as-needed
 
 
 LOCAL_STATIC_LIBRARIES :=
diff --git a/content/browser/speech/proto/speech_proto.target.linux-x86.mk b/content/browser/speech/proto/speech_proto.target.linux-x86.mk
index f3b9bd3..991fe36 100644
--- a/content/browser/speech/proto/speech_proto.target.linux-x86.mk
+++ b/content/browser/speech/proto/speech_proto.target.linux-x86.mk
@@ -69,6 +69,7 @@
 	-march=pentium4 \
 	-msse2 \
 	-mfpmath=sse \
+	-fuse-ld=gold \
 	-ffunction-sections \
 	-funwind-tables \
 	-g \
@@ -93,7 +94,6 @@
 MY_CFLAGS_C :=
 
 MY_DEFS := \
-	'-DUSE_SKIA' \
 	'-D_FILE_OFFSET_BITS=64' \
 	'-DUSE_LINUX_BREAKPAD' \
 	'-DNO_TCMALLOC' \
@@ -101,7 +101,6 @@
 	'-DCHROMIUM_BUILD' \
 	'-DUSE_LIBJPEG_TURBO=1' \
 	'-DUSE_PROPRIETARY_CODECS' \
-	'-DENABLE_PEPPER_THREADING' \
 	'-DENABLE_GPU=1' \
 	'-DUSE_OPENSSL=1' \
 	'-DENABLE_EGLIMAGE=1' \
@@ -151,12 +150,13 @@
 	-Wl,-z,noexecstack \
 	-fPIC \
 	-m32 \
+	-fuse-ld=gold \
 	-nostdlib \
 	-Wl,--no-undefined \
 	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
 	-Wl,-O1 \
-	-Wl,--as-needed \
-	-Wl,--gc-sections
+	-Wl,--as-needed
 
 
 LOCAL_STATIC_LIBRARIES :=
diff --git a/content/browser/speech/speech_recognition_manager_impl.cc b/content/browser/speech/speech_recognition_manager_impl.cc
index 8f9c3e1..ea49579 100644
--- a/content/browser/speech/speech_recognition_manager_impl.cc
+++ b/content/browser/speech/speech_recognition_manager_impl.cc
@@ -60,7 +60,7 @@
       is_dispatching_event_(false),
       delegate_(GetContentClient()->browser()->
                     GetSpeechRecognitionManagerDelegate()),
-      ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) {
+      weak_factory_(this) {
   DCHECK(!g_speech_recognition_manager_impl);
   g_speech_recognition_manager_impl = this;
 }
@@ -86,7 +86,7 @@
 
   std::string hardware_info;
   bool can_report_metrics = false;
-  if (delegate_.get())
+  if (delegate_)
     delegate_->GetDiagnosticInformation(&can_report_metrics, &hardware_info);
 
   SpeechRecognitionEngineConfig remote_engine_config;
@@ -100,7 +100,8 @@
   remote_engine_config.interim_results = config.interim_results;
   remote_engine_config.max_hypotheses = config.max_hypotheses;
   remote_engine_config.hardware_info = hardware_info;
-  remote_engine_config.origin_url = can_report_metrics ? config.origin_url : "";
+  remote_engine_config.origin_url =
+      can_report_metrics ? config.origin_url : std::string();
 
   SpeechRecognitionEngine* google_remote_engine;
   if (config.is_legacy_api) {
@@ -137,7 +138,7 @@
 
   primary_session_id_ = session_id;
 
-  if (delegate_.get()) {
+  if (delegate_) {
     delegate_->CheckRecognitionIsAllowed(
         session_id,
         base::Bind(&SpeechRecognitionManagerImpl::RecognitionAllowedCallback,
@@ -177,15 +178,21 @@
 #endif  // defined(OS_IOS)
 
   if (is_allowed) {
-    MessageLoop::current()->PostTask(FROM_HERE,
+    base::MessageLoop::current()->PostTask(
+        FROM_HERE,
         base::Bind(&SpeechRecognitionManagerImpl::DispatchEvent,
-                   weak_factory_.GetWeakPtr(), session_id, EVENT_START));
+                   weak_factory_.GetWeakPtr(),
+                   session_id,
+                   EVENT_START));
   } else {
     OnRecognitionError(session_id, SpeechRecognitionError(
         SPEECH_RECOGNITION_ERROR_NOT_ALLOWED));
-    MessageLoop::current()->PostTask(FROM_HERE,
+    base::MessageLoop::current()->PostTask(
+        FROM_HERE,
         base::Bind(&SpeechRecognitionManagerImpl::DispatchEvent,
-                   weak_factory_.GetWeakPtr(), session_id, EVENT_ABORT));
+                   weak_factory_.GetWeakPtr(),
+                   session_id,
+                   EVENT_ABORT));
   }
 }
 
@@ -224,9 +231,12 @@
     BrowserMainLoop::GetMediaStreamManager()->CancelRequest(context.label);
 #endif  // !defined(OS_IOS)
 
-  MessageLoop::current()->PostTask(FROM_HERE,
+  base::MessageLoop::current()->PostTask(
+      FROM_HERE,
       base::Bind(&SpeechRecognitionManagerImpl::DispatchEvent,
-                 weak_factory_.GetWeakPtr(), session_id, EVENT_ABORT));
+                 weak_factory_.GetWeakPtr(),
+                 session_id,
+                 EVENT_ABORT));
 }
 
 void SpeechRecognitionManagerImpl::StopAudioCaptureForSession(int session_id) {
@@ -241,9 +251,12 @@
     BrowserMainLoop::GetMediaStreamManager()->CancelRequest(context.label);
 #endif  // !defined(OS_IOS)
 
-  MessageLoop::current()->PostTask(FROM_HERE,
+  base::MessageLoop::current()->PostTask(
+      FROM_HERE,
       base::Bind(&SpeechRecognitionManagerImpl::DispatchEvent,
-                 weak_factory_.GetWeakPtr(), session_id, EVENT_STOP_CAPTURE));
+                 weak_factory_.GetWeakPtr(),
+                 session_id,
+                 EVENT_STOP_CAPTURE));
 }
 
 // Here begins the SpeechRecognitionEventListener interface implementation,
@@ -262,8 +275,7 @@
   if (!context.devices.empty()) {
     // Notify the UI the devices are being used.
     BrowserMainLoop::GetMediaStreamManager()->NotifyUIDevicesOpened(
-        context.label, context.render_process_id, context.render_view_id,
-        context.devices);
+        context.label);
   }
 #endif  // !defined(OS_IOS)
 
@@ -331,9 +343,12 @@
     delegate_listener->OnAudioEnd(session_id);
   if (SpeechRecognitionEventListener* listener = GetListener(session_id))
     listener->OnAudioEnd(session_id);
-  MessageLoop::current()->PostTask(FROM_HERE,
+  base::MessageLoop::current()->PostTask(
+      FROM_HERE,
       base::Bind(&SpeechRecognitionManagerImpl::DispatchEvent,
-                 weak_factory_.GetWeakPtr(), session_id, EVENT_AUDIO_ENDED));
+                 weak_factory_.GetWeakPtr(),
+                 session_id,
+                 EVENT_AUDIO_ENDED));
 }
 
 void SpeechRecognitionManagerImpl::OnRecognitionResults(
@@ -382,7 +397,7 @@
   if (!context.devices.empty()) {
     // Notify the UI the devices has been closed.
      BrowserMainLoop::GetMediaStreamManager()->NotifyUIDevicesClosed(
-         context.render_process_id, context.render_view_id, context.devices);
+         context.label);
   }
 #endif  // !defined(OS_IOS)
 
@@ -390,7 +405,8 @@
     delegate_listener->OnRecognitionEnd(session_id);
   if (SpeechRecognitionEventListener* listener = GetListener(session_id))
     listener->OnRecognitionEnd(session_id);
-  MessageLoop::current()->PostTask(FROM_HERE,
+  base::MessageLoop::current()->PostTask(
+      FROM_HERE,
       base::Bind(&SpeechRecognitionManagerImpl::DispatchEvent,
                  weak_factory_.GetWeakPtr(),
                  session_id,
diff --git a/content/browser/speech/speech_recognizer.cc b/content/browser/speech/speech_recognizer.cc
index cc66178..62c1b35 100644
--- a/content/browser/speech/speech_recognizer.cc
+++ b/content/browser/speech/speech_recognizer.cc
@@ -155,7 +155,7 @@
 
 SpeechRecognizer::~SpeechRecognizer() {
   endpointer_.EndSession();
-  if (audio_controller_.get()) {
+  if (audio_controller_) {
     audio_controller_->Close(base::Bind(&KeepAudioControllerRefcountedForDtor,
                                         audio_controller_));
   }
diff --git a/content/browser/speech/speech_recognizer_unittest.cc b/content/browser/speech/speech_recognizer_unittest.cc
index 2cc4db3..9b55ec5 100644
--- a/content/browser/speech/speech_recognizer_unittest.cc
+++ b/content/browser/speech/speech_recognizer_unittest.cc
@@ -56,7 +56,7 @@
     recognizer_ = new SpeechRecognizer(
         this, kTestingSessionId, kOneShotMode, sr_engine);
     audio_manager_.reset(new media::MockAudioManager(
-        MessageLoop::current()->message_loop_proxy()));
+        base::MessageLoop::current()->message_loop_proxy()));
     recognizer_->SetAudioManagerForTests(audio_manager_.get());
 
     int audio_packet_length_bytes =
@@ -162,7 +162,7 @@
   }
 
  protected:
-  MessageLoopForIO message_loop_;
+  base::MessageLoopForIO message_loop_;
   BrowserThreadImpl io_thread_;
   scoped_refptr<SpeechRecognizer> recognizer_;
   scoped_ptr<AudioManager> audio_manager_;
@@ -185,7 +185,7 @@
   // Check for callbacks when stopping record before any audio gets recorded.
   recognizer_->StartRecognition();
   recognizer_->StopAudioCapture();
-  MessageLoop::current()->RunUntilIdle();
+  base::MessageLoop::current()->RunUntilIdle();
   EXPECT_TRUE(recognition_started_);
   EXPECT_FALSE(audio_started_);
   EXPECT_FALSE(result_received_);
@@ -198,7 +198,7 @@
   // recorded.
   recognizer_->StartRecognition();
   recognizer_->AbortRecognition();
-  MessageLoop::current()->RunUntilIdle();
+  base::MessageLoop::current()->RunUntilIdle();
   EXPECT_TRUE(recognition_started_);
   EXPECT_FALSE(audio_started_);
   EXPECT_FALSE(result_received_);
@@ -210,7 +210,7 @@
   // Start recording, give some data and then stop. This should wait for the
   // network callback to arrive before completion.
   recognizer_->StartRecognition();
-  MessageLoop::current()->RunUntilIdle();
+  base::MessageLoop::current()->RunUntilIdle();
   TestAudioInputController* controller =
       audio_input_controller_factory_.controller();
   ASSERT_TRUE(controller);
@@ -223,14 +223,14 @@
   for (size_t i = 0; i < kNumChunks; ++i) {
     controller->event_handler()->OnData(controller, &audio_packet_[0],
                                         audio_packet_.size());
-    MessageLoop::current()->RunUntilIdle();
+    base::MessageLoop::current()->RunUntilIdle();
     net::TestURLFetcher* fetcher = url_fetcher_factory_.GetFetcherByID(0);
     ASSERT_TRUE(fetcher);
     EXPECT_EQ(i + 1, fetcher->upload_chunks().size());
   }
 
   recognizer_->StopAudioCapture();
-  MessageLoop::current()->RunUntilIdle();
+  base::MessageLoop::current()->RunUntilIdle();
   EXPECT_TRUE(audio_started_);
   EXPECT_TRUE(audio_ended_);
   EXPECT_FALSE(recognition_ended_);
@@ -249,7 +249,7 @@
   fetcher->SetResponseString(
       "{\"status\":0,\"hypotheses\":[{\"utterance\":\"123\"}]}");
   fetcher->delegate()->OnURLFetchComplete(fetcher);
-  MessageLoop::current()->RunUntilIdle();
+  base::MessageLoop::current()->RunUntilIdle();
   EXPECT_TRUE(recognition_ended_);
   EXPECT_TRUE(result_received_);
   EXPECT_EQ(SPEECH_RECOGNITION_ERROR_NONE, error_);
@@ -259,15 +259,15 @@
 TEST_F(SpeechRecognizerTest, CancelWithData) {
   // Start recording, give some data and then cancel.
   recognizer_->StartRecognition();
-  MessageLoop::current()->RunUntilIdle();
+  base::MessageLoop::current()->RunUntilIdle();
   TestAudioInputController* controller =
       audio_input_controller_factory_.controller();
   ASSERT_TRUE(controller);
   controller->event_handler()->OnData(controller, &audio_packet_[0],
                                       audio_packet_.size());
-  MessageLoop::current()->RunUntilIdle();
+  base::MessageLoop::current()->RunUntilIdle();
   recognizer_->AbortRecognition();
-  MessageLoop::current()->RunUntilIdle();
+  base::MessageLoop::current()->RunUntilIdle();
   ASSERT_TRUE(url_fetcher_factory_.GetFetcherByID(0));
   EXPECT_TRUE(recognition_started_);
   EXPECT_TRUE(audio_started_);
@@ -280,18 +280,18 @@
   // Start recording, give some data and then stop. Issue the network callback
   // with a connection error and verify that the recognizer bubbles the error up
   recognizer_->StartRecognition();
-  MessageLoop::current()->RunUntilIdle();
+  base::MessageLoop::current()->RunUntilIdle();
   TestAudioInputController* controller =
       audio_input_controller_factory_.controller();
   ASSERT_TRUE(controller);
   controller->event_handler()->OnData(controller, &audio_packet_[0],
                                       audio_packet_.size());
-  MessageLoop::current()->RunUntilIdle();
+  base::MessageLoop::current()->RunUntilIdle();
   net::TestURLFetcher* fetcher = url_fetcher_factory_.GetFetcherByID(0);
   ASSERT_TRUE(fetcher);
 
   recognizer_->StopAudioCapture();
-  MessageLoop::current()->RunUntilIdle();
+  base::MessageLoop::current()->RunUntilIdle();
   EXPECT_TRUE(audio_started_);
   EXPECT_TRUE(audio_ended_);
   EXPECT_FALSE(recognition_ended_);
@@ -305,9 +305,9 @@
   status.set_error(net::ERR_CONNECTION_REFUSED);
   fetcher->set_status(status);
   fetcher->set_response_code(0);
-  fetcher->SetResponseString("");
+  fetcher->SetResponseString(std::string());
   fetcher->delegate()->OnURLFetchComplete(fetcher);
-  MessageLoop::current()->RunUntilIdle();
+  base::MessageLoop::current()->RunUntilIdle();
   EXPECT_TRUE(recognition_ended_);
   EXPECT_FALSE(result_received_);
   EXPECT_EQ(SPEECH_RECOGNITION_ERROR_NETWORK, error_);
@@ -318,18 +318,18 @@
   // Start recording, give some data and then stop. Issue the network callback
   // with a 500 error and verify that the recognizer bubbles the error up
   recognizer_->StartRecognition();
-  MessageLoop::current()->RunUntilIdle();
+  base::MessageLoop::current()->RunUntilIdle();
   TestAudioInputController* controller =
       audio_input_controller_factory_.controller();
   ASSERT_TRUE(controller);
   controller->event_handler()->OnData(controller, &audio_packet_[0],
                                       audio_packet_.size());
-  MessageLoop::current()->RunUntilIdle();
+  base::MessageLoop::current()->RunUntilIdle();
   net::TestURLFetcher* fetcher = url_fetcher_factory_.GetFetcherByID(0);
   ASSERT_TRUE(fetcher);
 
   recognizer_->StopAudioCapture();
-  MessageLoop::current()->RunUntilIdle();
+  base::MessageLoop::current()->RunUntilIdle();
   EXPECT_TRUE(audio_started_);
   EXPECT_TRUE(audio_ended_);
   EXPECT_FALSE(recognition_ended_);
@@ -344,7 +344,7 @@
   fetcher->set_response_code(500);
   fetcher->SetResponseString("Internal Server Error");
   fetcher->delegate()->OnURLFetchComplete(fetcher);
-  MessageLoop::current()->RunUntilIdle();
+  base::MessageLoop::current()->RunUntilIdle();
   EXPECT_TRUE(recognition_ended_);
   EXPECT_FALSE(result_received_);
   EXPECT_EQ(SPEECH_RECOGNITION_ERROR_NETWORK, error_);
@@ -354,12 +354,12 @@
 TEST_F(SpeechRecognizerTest, AudioControllerErrorNoData) {
   // Check if things tear down properly if AudioInputController threw an error.
   recognizer_->StartRecognition();
-  MessageLoop::current()->RunUntilIdle();
+  base::MessageLoop::current()->RunUntilIdle();
   TestAudioInputController* controller =
       audio_input_controller_factory_.controller();
   ASSERT_TRUE(controller);
   controller->event_handler()->OnError(controller);
-  MessageLoop::current()->RunUntilIdle();
+  base::MessageLoop::current()->RunUntilIdle();
   EXPECT_TRUE(recognition_started_);
   EXPECT_FALSE(audio_started_);
   EXPECT_FALSE(result_received_);
@@ -371,14 +371,14 @@
   // Check if things tear down properly if AudioInputController threw an error
   // after giving some audio data.
   recognizer_->StartRecognition();
-  MessageLoop::current()->RunUntilIdle();
+  base::MessageLoop::current()->RunUntilIdle();
   TestAudioInputController* controller =
       audio_input_controller_factory_.controller();
   ASSERT_TRUE(controller);
   controller->event_handler()->OnData(controller, &audio_packet_[0],
                                       audio_packet_.size());
   controller->event_handler()->OnError(controller);
-  MessageLoop::current()->RunUntilIdle();
+  base::MessageLoop::current()->RunUntilIdle();
   ASSERT_TRUE(url_fetcher_factory_.GetFetcherByID(0));
   EXPECT_TRUE(recognition_started_);
   EXPECT_TRUE(audio_started_);
@@ -391,7 +391,7 @@
   // Start recording and give a lot of packets with audio samples set to zero.
   // This should trigger the no-speech detector and issue a callback.
   recognizer_->StartRecognition();
-  MessageLoop::current()->RunUntilIdle();
+  base::MessageLoop::current()->RunUntilIdle();
   TestAudioInputController* controller =
       audio_input_controller_factory_.controller();
   ASSERT_TRUE(controller);
@@ -403,7 +403,7 @@
     controller->event_handler()->OnData(controller, &audio_packet_[0],
                                         audio_packet_.size());
   }
-  MessageLoop::current()->RunUntilIdle();
+  base::MessageLoop::current()->RunUntilIdle();
   EXPECT_TRUE(recognition_started_);
   EXPECT_TRUE(audio_started_);
   EXPECT_FALSE(result_received_);
@@ -417,7 +417,7 @@
   // treated as normal speech input and the no-speech detector should not get
   // triggered.
   recognizer_->StartRecognition();
-  MessageLoop::current()->RunUntilIdle();
+  base::MessageLoop::current()->RunUntilIdle();
   TestAudioInputController* controller =
       audio_input_controller_factory_.controller();
   ASSERT_TRUE(controller);
@@ -439,13 +439,13 @@
                                         audio_packet_.size());
   }
 
-  MessageLoop::current()->RunUntilIdle();
+  base::MessageLoop::current()->RunUntilIdle();
   EXPECT_EQ(SPEECH_RECOGNITION_ERROR_NONE, error_);
   EXPECT_TRUE(audio_started_);
   EXPECT_FALSE(audio_ended_);
   EXPECT_FALSE(recognition_ended_);
   recognizer_->AbortRecognition();
-  MessageLoop::current()->RunUntilIdle();
+  base::MessageLoop::current()->RunUntilIdle();
   CheckFinalEventsConsistency();
 }
 
@@ -455,7 +455,7 @@
   // get the callback during estimation phase, then get zero for the silence
   // samples and proper volume for the loud audio.
   recognizer_->StartRecognition();
-  MessageLoop::current()->RunUntilIdle();
+  base::MessageLoop::current()->RunUntilIdle();
   TestAudioInputController* controller =
       audio_input_controller_factory_.controller();
   ASSERT_TRUE(controller);
@@ -470,19 +470,19 @@
     controller->event_handler()->OnData(controller, &audio_packet_[0],
                                         audio_packet_.size());
   }
-  MessageLoop::current()->RunUntilIdle();
+  base::MessageLoop::current()->RunUntilIdle();
   EXPECT_EQ(-1.0f, volume_);  // No audio volume set yet.
 
   // The vector is already filled with zero value samples on create.
   controller->event_handler()->OnData(controller, &audio_packet_[0],
                                       audio_packet_.size());
-  MessageLoop::current()->RunUntilIdle();
+  base::MessageLoop::current()->RunUntilIdle();
   EXPECT_FLOAT_EQ(0.74939233f, volume_);
 
   FillPacketWithTestWaveform();
   controller->event_handler()->OnData(controller, &audio_packet_[0],
                                       audio_packet_.size());
-  MessageLoop::current()->RunUntilIdle();
+  base::MessageLoop::current()->RunUntilIdle();
   EXPECT_FLOAT_EQ(0.89926866f, volume_);
   EXPECT_FLOAT_EQ(0.75071919f, noise_volume_);
 
@@ -490,7 +490,7 @@
   EXPECT_FALSE(audio_ended_);
   EXPECT_FALSE(recognition_ended_);
   recognizer_->AbortRecognition();
-  MessageLoop::current()->RunUntilIdle();
+  base::MessageLoop::current()->RunUntilIdle();
   CheckFinalEventsConsistency();
 }
 
diff --git a/content/browser/ssl/ssl_cert_error_handler.cc b/content/browser/ssl/ssl_cert_error_handler.cc
index 268ccf7..b3bdb41 100644
--- a/content/browser/ssl/ssl_cert_error_handler.cc
+++ b/content/browser/ssl/ssl_cert_error_handler.cc
@@ -6,8 +6,8 @@
 
 #include "content/browser/ssl/ssl_manager.h"
 #include "content/browser/ssl/ssl_policy.h"
-#include "net/base/cert_status_flags.h"
-#include "net/base/x509_certificate.h"
+#include "net/cert/cert_status_flags.h"
+#include "net/cert/x509_certificate.h"
 
 namespace content {
 
diff --git a/content/browser/ssl/ssl_client_auth_handler.cc b/content/browser/ssl/ssl_client_auth_handler.cc
index 97db658..1180269 100644
--- a/content/browser/ssl/ssl_client_auth_handler.cc
+++ b/content/browser/ssl/ssl_client_auth_handler.cc
@@ -9,7 +9,7 @@
 #include "content/browser/loader/resource_request_info_impl.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/content_browser_client.h"
-#include "net/base/x509_certificate.h"
+#include "net/cert/x509_certificate.h"
 #include "net/http/http_transaction_factory.h"
 #include "net/url_request/url_request.h"
 #include "net/url_request/url_request_context.h"
diff --git a/content/browser/ssl/ssl_host_state.h b/content/browser/ssl/ssl_host_state.h
index da3fe9c..d3b69c2 100644
--- a/content/browser/ssl/ssl_host_state.h
+++ b/content/browser/ssl/ssl_host_state.h
@@ -5,17 +5,17 @@
 #ifndef CONTENT_BROWSER_SSL_SSL_HOST_STATE_H_
 #define CONTENT_BROWSER_SSL_SSL_HOST_STATE_H_
 
-#include <string>
 #include <map>
 #include <set>
+#include <string>
 
-#include "base/compiler_specific.h"
 #include "base/basictypes.h"
+#include "base/compiler_specific.h"
 #include "base/supports_user_data.h"
 #include "base/threading/non_thread_safe.h"
 #include "content/common/content_export.h"
 #include "googleurl/src/gurl.h"
-#include "net/base/x509_certificate.h"
+#include "net/cert/x509_certificate.h"
 
 namespace content {
 class BrowserContext;
diff --git a/content/browser/ssl/ssl_manager.h b/content/browser/ssl/ssl_manager.h
index 8cd1668..0ccedb2 100644
--- a/content/browser/ssl/ssl_manager.h
+++ b/content/browser/ssl/ssl_manager.h
@@ -17,7 +17,7 @@
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
 #include "googleurl/src/gurl.h"
-#include "net/base/cert_status_flags.h"
+#include "net/cert/cert_status_flags.h"
 #include "net/base/net_errors.h"
 
 namespace net {
diff --git a/content/browser/ssl/ssl_policy.cc b/content/browser/ssl/ssl_policy.cc
index 750bf47..1b0e424 100644
--- a/content/browser/ssl/ssl_policy.cc
+++ b/content/browser/ssl/ssl_policy.cc
@@ -8,8 +8,8 @@
 #include "base/bind.h"
 #include "base/command_line.h"
 #include "base/memory/singleton.h"
-#include "base/string_piece.h"
 #include "base/string_util.h"
+#include "base/strings/string_piece.h"
 #include "content/browser/renderer_host/render_process_host_impl.h"
 #include "content/browser/renderer_host/render_view_host_impl.h"
 #include "content/browser/site_instance_impl.h"
diff --git a/content/browser/ssl/ssl_policy_backend.h b/content/browser/ssl/ssl_policy_backend.h
index 3d8f390..bef0469 100644
--- a/content/browser/ssl/ssl_policy_backend.h
+++ b/content/browser/ssl/ssl_policy_backend.h
@@ -10,7 +10,7 @@
 
 #include "base/basictypes.h"
 #include "base/string16.h"
-#include "net/base/x509_certificate.h"
+#include "net/cert/x509_certificate.h"
 
 namespace content {
 class NavigationControllerImpl;
diff --git a/content/browser/ssl/ssl_request_info.h b/content/browser/ssl/ssl_request_info.h
index 5e9428c..d5971ed 100644
--- a/content/browser/ssl/ssl_request_info.h
+++ b/content/browser/ssl/ssl_request_info.h
@@ -9,7 +9,7 @@
 
 #include "base/memory/ref_counted.h"
 #include "googleurl/src/gurl.h"
-#include "net/base/cert_status_flags.h"
+#include "net/cert/cert_status_flags.h"
 #include "webkit/glue/resource_type.h"
 
 namespace content {
diff --git a/content/browser/storage_partition_impl.cc b/content/browser/storage_partition_impl.cc
index fbee33d..ab0e7a5 100644
--- a/content/browser/storage_partition_impl.cc
+++ b/content/browser/storage_partition_impl.cc
@@ -6,6 +6,7 @@
 
 #include "base/utf_string_conversions.h"
 #include "content/browser/fileapi/browser_file_system_helper.h"
+#include "content/browser/gpu/shader_disk_cache.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/dom_storage_context.h"
@@ -74,6 +75,11 @@
                                        origins,
                                        quota::kStorageTypePersistent);
   }
+  if (storage_mask & StoragePartition::kQuotaManagedSyncableStorage) {
+    ClearQuotaManagedOriginsOnIOThread(quota_manager,
+                                       origins,
+                                       quota::kStorageTypeSyncable);
+  }
 }
 
 void ClearAllDataOnIOThread(
@@ -102,6 +108,24 @@
         quota::kStorageTypePersistent, base::Time(),
         base::Bind(&ClearQuotaManagedOriginsOnIOThread, quota_manager));
   }
+  if (storage_mask & StoragePartition::kQuotaManagedSyncableStorage) {
+    quota_manager->GetOriginsModifiedSince(
+        quota::kStorageTypeSyncable, base::Time(),
+        base::Bind(&ClearQuotaManagedOriginsOnIOThread, quota_manager));
+  }
+}
+
+void ClearedShaderCacheOnIOThread(base::Closure callback) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, callback);
+}
+
+void ClearShaderCacheOnIOThread(base::FilePath path,
+    base::Time begin, base::Time end, base::Closure callback) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  ShaderCacheFactory::GetInstance()->ClearByPath(
+      path, begin, end,
+      base::Bind(&ClearedShaderCacheOnIOThread, callback));
 }
 
 void OnLocalStorageUsageInfo(
@@ -293,6 +317,20 @@
   }
 }
 
+void StoragePartitionImpl::AsyncClearDataBetween(uint32 storage_mask,
+      const base::Time& begin, const base::Time& end,
+      const base::Closure& callback) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK(storage_mask == kShaderStorage);
+
+  if (storage_mask & kShaderStorage) {
+    BrowserThread::PostTask(
+        BrowserThread::IO, FROM_HERE,
+        base::Bind(&ClearShaderCacheOnIOThread, GetPath(), begin, end,
+            callback));
+  }
+}
+
 void StoragePartitionImpl::SetURLRequestContext(
     net::URLRequestContextGetter* url_request_context) {
   url_request_context_ = url_request_context;
diff --git a/content/browser/storage_partition_impl.h b/content/browser/storage_partition_impl.h
index 07cea99..af206f5 100644
--- a/content/browser/storage_partition_impl.h
+++ b/content/browser/storage_partition_impl.h
@@ -10,14 +10,15 @@
 #include "base/memory/ref_counted.h"
 #include "content/browser/appcache/chrome_appcache_service.h"
 #include "content/browser/dom_storage/dom_storage_context_impl.h"
-#include "content/browser/in_process_webkit/indexed_db_context_impl.h"
+#include "content/browser/indexed_db/indexed_db_context_impl.h"
+#include "content/common/content_export.h"
 #include "content/public/browser/storage_partition.h"
 
 namespace content {
 
 class StoragePartitionImpl : public StoragePartition {
  public:
-  virtual ~StoragePartitionImpl();
+  CONTENT_EXPORT virtual ~StoragePartitionImpl();
 
   // StoragePartition interface.
   virtual base::FilePath GetPath() OVERRIDE;
@@ -34,9 +35,15 @@
       const GURL& storage_origin,
       net::URLRequestContextGetter* request_context_getter) OVERRIDE;
   virtual void AsyncClearData(uint32 storage_mask) OVERRIDE;
+  virtual void AsyncClearDataBetween(
+      uint32 storage_mask,
+      const base::Time& begin,
+      const base::Time& end,
+      const base::Closure& callback) OVERRIDE;
 
  private:
   friend class StoragePartitionImplMap;
+  FRIEND_TEST_ALL_PREFIXES(StoragePartitionShaderClearTest, ClearShaderCache);
 
   // The |partition_path| is the absolute path to the root of this
   // StoragePartition's on-disk storage.
@@ -48,7 +55,7 @@
                                       bool in_memory,
                                       const base::FilePath& profile_path);
 
-  StoragePartitionImpl(
+  CONTENT_EXPORT StoragePartitionImpl(
       const base::FilePath& partition_path,
       quota::QuotaManager* quota_manager,
       ChromeAppCacheService* appcache_service,
diff --git a/content/browser/storage_partition_impl_map.cc b/content/browser/storage_partition_impl_map.cc
index 16111cf..94141d6 100644
--- a/content/browser/storage_partition_impl_map.cc
+++ b/content/browser/storage_partition_impl_map.cc
@@ -90,7 +90,7 @@
 
     virtual net::URLRequestJob* MaybeCreateJob(
         net::URLRequest* request,
-        net::NetworkDelegate* network_delegate) const {
+        net::NetworkDelegate* network_delegate) const OVERRIDE {
       scoped_refptr<Stream> stream =
           stream_context_->registry()->GetStream(request->url());
       if (stream)
@@ -254,7 +254,7 @@
     const std::vector<base::FilePath>& paths_to_keep,
     const scoped_refptr<base::TaskRunner>& closure_runner,
     const base::Closure& on_gc_required) {
-  // Early exit required because file_util::AbsolutePath() will fail on POSIX
+  // Early exit required because MakeAbsoluteFilePath() will fail on POSIX
   // if |unnormalized_root| does not exist. This is safe because there is
   // nothing to do in this situation anwyays.
   if (!file_util::PathExists(unnormalized_root)) {
@@ -263,12 +263,12 @@
 
   // Never try to obliterate things outside of the browser context root or the
   // browser context root itself. Die hard.
-  base::FilePath root = unnormalized_root;
-  base::FilePath browser_context_root = unnormalized_browser_context_root;
-  CHECK(file_util::AbsolutePath(&root));
-  CHECK(file_util::AbsolutePath(&browser_context_root));
-  CHECK(file_util::ContainsPath(browser_context_root, root) &&
-        browser_context_root != root);
+  base::FilePath root = base::MakeAbsoluteFilePath(unnormalized_root);
+  base::FilePath browser_context_root =
+      base::MakeAbsoluteFilePath(unnormalized_browser_context_root);
+  CHECK(!root.empty());
+  CHECK(!browser_context_root.empty());
+  CHECK(browser_context_root.IsParent(root) && browser_context_root != root);
 
   // Reduce |paths_to_keep| set to those under the root and actually on disk.
   std::vector<base::FilePath> valid_paths_to_keep;
@@ -426,8 +426,9 @@
               browser_context_->IsOffTheRecord(),
               partition->GetAppCacheService(),
               blob_storage_context));
-  std::vector<std::string> additional_webui_schemes =
-      GetContentClient()->browser()->GetAdditionalWebUISchemes();
+  std::vector<std::string> additional_webui_schemes;
+  GetContentClient()->browser()->GetAdditionalWebUISchemes(
+      &additional_webui_schemes);
   for (std::vector<std::string>::const_iterator it =
            additional_webui_schemes.begin();
        it != additional_webui_schemes.end();
diff --git a/content/browser/storage_partition_impl_map_unittest.cc b/content/browser/storage_partition_impl_map_unittest.cc
index 1c44fcc..04127cc 100644
--- a/content/browser/storage_partition_impl_map_unittest.cc
+++ b/content/browser/storage_partition_impl_map_unittest.cc
@@ -13,13 +13,18 @@
 // Test that the Less comparison function is implemented properly to uniquely
 // identify storage partitions used as keys in a std::map.
 TEST_F(StoragePartitionConfigTest, OperatorLess) {
-  StoragePartitionImplMap::StoragePartitionConfig c1("", "", false);
-  StoragePartitionImplMap::StoragePartitionConfig c2("", "", false);
-  StoragePartitionImplMap::StoragePartitionConfig c3("", "", true);
-  StoragePartitionImplMap::StoragePartitionConfig c4("a", "", true);
-  StoragePartitionImplMap::StoragePartitionConfig c5("b", "", true);
-  StoragePartitionImplMap::StoragePartitionConfig c6("", "abc", false);
-  StoragePartitionImplMap::StoragePartitionConfig c7("", "abc", true);
+  StoragePartitionImplMap::StoragePartitionConfig c1(
+      std::string(), std::string(), false);
+  StoragePartitionImplMap::StoragePartitionConfig c2(
+      std::string(), std::string(), false);
+  StoragePartitionImplMap::StoragePartitionConfig c3(
+      std::string(), std::string(), true);
+  StoragePartitionImplMap::StoragePartitionConfig c4("a", std::string(), true);
+  StoragePartitionImplMap::StoragePartitionConfig c5("b", std::string(), true);
+  StoragePartitionImplMap::StoragePartitionConfig c6(
+      std::string(), "abc", false);
+  StoragePartitionImplMap::StoragePartitionConfig c7(
+      std::string(), "abc", true);
   StoragePartitionImplMap::StoragePartitionConfig c8("a", "abc", false);
   StoragePartitionImplMap::StoragePartitionConfig c9("a", "abc", true);
 
diff --git a/content/browser/storage_partition_impl_unittest.cc b/content/browser/storage_partition_impl_unittest.cc
new file mode 100644
index 0000000..631ac7b
--- /dev/null
+++ b/content/browser/storage_partition_impl_unittest.cc
@@ -0,0 +1,124 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/files/scoped_temp_dir.h"
+#include "base/message_loop/message_loop_proxy.h"
+#include "base/run_loop.h"
+#include "base/threading/thread.h"
+#include "content/browser/browser_thread_impl.h"
+#include "content/browser/gpu/shader_disk_cache.h"
+#include "content/browser/storage_partition_impl.h"
+#include "content/public/browser/storage_partition.h"
+#include "content/public/test/test_browser_thread.h"
+#include "net/base/test_completion_callback.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+namespace {
+
+class TestClosureCallback {
+ public:
+  TestClosureCallback()
+      : callback_(base::Bind(
+          &TestClosureCallback::StopWaiting, base::Unretained(this))) {
+  }
+
+  void WaitForResult() {
+    wait_run_loop_.reset(new base::RunLoop());
+    wait_run_loop_->Run();
+  }
+
+  const base::Closure& callback() { return callback_; }
+
+ private:
+  void StopWaiting() {
+    wait_run_loop_->Quit();
+  }
+
+  base::Closure callback_;
+  scoped_ptr<base::RunLoop> wait_run_loop_;
+
+  DISALLOW_COPY_AND_ASSIGN(TestClosureCallback);
+};
+
+const int kDefaultClientId = 42;
+const char kCacheKey[] = "key";
+const char kCacheValue[] = "cached value";
+
+}  // namespace
+
+class StoragePartitionShaderClearTest : public testing::Test {
+ public:
+  StoragePartitionShaderClearTest() :
+      ui_thread_(BrowserThread::UI, &message_loop_),
+      cache_thread_(BrowserThread::CACHE, &message_loop_),
+      io_thread_(BrowserThread::IO, &message_loop_) {
+  }
+
+  virtual ~StoragePartitionShaderClearTest() {}
+
+  const base::FilePath& cache_path() { return temp_dir_.path(); }
+
+  virtual void SetUp() OVERRIDE {
+    ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
+    ShaderCacheFactory::GetInstance()->SetCacheInfo(kDefaultClientId,
+                                                    cache_path());
+
+    cache_ = ShaderCacheFactory::GetInstance()->Get(kDefaultClientId);
+    ASSERT_TRUE(cache_.get() != NULL);
+  }
+
+  void InitCache() {
+    net::TestCompletionCallback available_cb;
+    int rv = cache_->SetAvailableCallback(available_cb.callback());
+    ASSERT_EQ(net::OK, available_cb.GetResult(rv));
+    EXPECT_EQ(0, cache_->Size());
+
+    cache_->Cache(kCacheKey, kCacheValue);
+
+    net::TestCompletionCallback complete_cb;
+
+    rv = cache_->SetCacheCompleteCallback(complete_cb.callback());
+    ASSERT_EQ(net::OK, complete_cb.GetResult(rv));
+  }
+
+  size_t Size() { return cache_->Size(); }
+
+  base::MessageLoop* message_loop() { return &message_loop_; }
+
+ private:
+  virtual void TearDown() OVERRIDE {
+    cache_ = NULL;
+    ShaderCacheFactory::GetInstance()->RemoveCacheInfo(kDefaultClientId);
+  }
+
+  base::ScopedTempDir temp_dir_;
+  base::MessageLoopForIO message_loop_;
+  TestBrowserThread ui_thread_;
+  TestBrowserThread cache_thread_;
+  TestBrowserThread io_thread_;
+
+  scoped_refptr<ShaderDiskCache> cache_;
+};
+
+void ClearData(content::StoragePartitionImpl* sp,
+               const base::Closure& cb) {
+  base::Time time;
+  sp->AsyncClearDataBetween(content::StoragePartition::kShaderStorage,
+                           time, time, cb);
+}
+
+TEST_F(StoragePartitionShaderClearTest, ClearShaderCache) {
+  InitCache();
+  EXPECT_EQ(1u, Size());
+
+  TestClosureCallback clear_cb;
+  StoragePartitionImpl sp(cache_path(), NULL, NULL, NULL, NULL, NULL, NULL);
+  message_loop()->PostTask(FROM_HERE,
+                           base::Bind(&ClearData, &sp, clear_cb.callback()));
+  clear_cb.WaitForResult();
+  EXPECT_EQ(0u, Size());
+}
+
+}  // namespace content
diff --git a/content/browser/streams/stream.cc b/content/browser/streams/stream.cc
index a0b8007..8a926a6 100644
--- a/content/browser/streams/stream.cc
+++ b/content/browser/streams/stream.cc
@@ -33,7 +33,7 @@
       read_observer_(NULL),
       write_observer_(write_observer),
       stream_handle_(NULL),
-      weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
+      weak_ptr_factory_(this) {
   CreateByteStream(base::MessageLoopProxy::current(),
                    base::MessageLoopProxy::current(),
                    kDeferSizeThreshold,
@@ -125,6 +125,9 @@
 }
 
 void Stream::CloseHandle() {
+  // Prevent deletion until this function ends.
+  scoped_refptr<Stream> ref(this);
+
   CHECK(stream_handle_);
   stream_handle_ = NULL;
   registry_->UnregisterStream(url());
diff --git a/content/browser/streams/stream_unittest.cc b/content/browser/streams/stream_unittest.cc
index 2c9f34c..3452553 100644
--- a/content/browser/streams/stream_unittest.cc
+++ b/content/browser/streams/stream_unittest.cc
@@ -32,7 +32,7 @@
   }
 
  protected:
-  MessageLoop message_loop_;
+  base::MessageLoop message_loop_;
   scoped_ptr<StreamRegistry> registry_;
 
  private:
@@ -138,7 +138,7 @@
   writer.Write(stream, buffer, kBufferSize);
   stream->Finalize();
   reader.Read(stream);
-  MessageLoop::current()->RunUntilIdle();
+  base::MessageLoop::current()->RunUntilIdle();
 
   ASSERT_EQ(reader.buffer()->capacity(), kBufferSize);
   for (int i = 0; i < kBufferSize; i++)
diff --git a/content/browser/streams/stream_url_request_job.cc b/content/browser/streams/stream_url_request_job.cc
index da2e9ce..4478d16 100644
--- a/content/browser/streams/stream_url_request_job.cc
+++ b/content/browser/streams/stream_url_request_job.cc
@@ -37,7 +37,7 @@
     net::NetworkDelegate* network_delegate,
     scoped_refptr<Stream> stream)
     : net::URLRequestJob(request, network_delegate),
-      ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)),
+      weak_factory_(this),
       stream_(stream),
       headers_set_(false),
       pending_buffer_size_(0),
@@ -72,7 +72,7 @@
 // net::URLRequestJob methods.
 void StreamURLRequestJob::Start() {
   // Continue asynchronously.
-  MessageLoop::current()->PostTask(
+  base::MessageLoop::current()->PostTask(
       FROM_HERE,
       base::Bind(&StreamURLRequestJob::DidStart, weak_factory_.GetWeakPtr()));
 }
@@ -117,7 +117,7 @@
 }
 
 bool StreamURLRequestJob::GetMimeType(std::string* mime_type) const {
-  if (!response_info_.get())
+  if (!response_info_)
     return false;
 
   // TODO(zork): Support registered MIME types if needed.
@@ -125,12 +125,12 @@
 }
 
 void StreamURLRequestJob::GetResponseInfo(net::HttpResponseInfo* info) {
-  if (response_info_.get())
+  if (response_info_)
     *info = *response_info_;
 }
 
 int StreamURLRequestJob::GetResponseCode() const {
-  if (!response_info_.get())
+  if (!response_info_)
     return -1;
 
   return response_info_->headers->response_code();
diff --git a/content/browser/streams/stream_url_request_job_unittest.cc b/content/browser/streams/stream_url_request_job_unittest.cc
index 10a02c9..37d9c4f 100644
--- a/content/browser/streams/stream_url_request_job_unittest.cc
+++ b/content/browser/streams/stream_url_request_job_unittest.cc
@@ -49,9 +49,7 @@
     StreamRegistry* registry_;
   };
 
-  StreamURLRequestJobTest()
-      : message_loop_(MessageLoop::TYPE_IO) {
-  }
+  StreamURLRequestJobTest() : message_loop_(base::MessageLoop::TYPE_IO) {}
 
   virtual void SetUp() {
     registry_.reset(new StreamRegistry());
@@ -81,7 +79,7 @@
       request_->SetExtraRequestHeaders(extra_headers);
     request_->Start();
 
-    MessageLoop::current()->RunUntilIdle();
+    base::MessageLoop::current()->RunUntilIdle();
 
     // Verify response.
     EXPECT_TRUE(request_->status().is_success());
@@ -91,7 +89,7 @@
   }
 
  protected:
-  MessageLoop message_loop_;
+  base::MessageLoop message_loop_;
   scoped_ptr<StreamRegistry> registry_;
 
   net::URLRequestContext url_request_context_;
@@ -135,7 +133,7 @@
   request_->set_method("GET");
   request_->Start();
 
-  MessageLoop::current()->RunUntilIdle();
+  base::MessageLoop::current()->RunUntilIdle();
 
   // Verify response.
   EXPECT_FALSE(request_->status().is_success());
@@ -169,7 +167,7 @@
 
   net::HttpRequestHeaders extra_headers;
   extra_headers.SetHeader(net::HttpRequestHeaders::kRange, "bytes=1-3");
-  TestRequest("GET", kStreamURL, extra_headers, 405, "");
+  TestRequest("GET", kStreamURL, extra_headers, 405, std::string());
 }
 
 }  // namespace content
diff --git a/content/browser/system_message_window_win_unittest.cc b/content/browser/system_message_window_win_unittest.cc
index 38566b5..25c77c9d 100644
--- a/content/browser/system_message_window_win_unittest.cc
+++ b/content/browser/system_message_window_win_unittest.cc
@@ -25,7 +25,7 @@
     system_monitor_.AddDevicesChangedObserver(&observer_);
   }
 
-  MessageLoop message_loop_;
+  base::MessageLoop message_loop_;
   base::SystemMonitor system_monitor_;
   base::MockDevicesChangedObserver observer_;
   SystemMessageWindowWin window_;
diff --git a/content/browser/tracing/trace_controller_impl.cc b/content/browser/tracing/trace_controller_impl.cc
index e416126..d944299 100644
--- a/content/browser/tracing/trace_controller_impl.cc
+++ b/content/browser/tracing/trace_controller_impl.cc
@@ -54,7 +54,9 @@
     pending_bpf_ack_count_(0),
     maximum_bpf_(0.0f),
     is_tracing_(false),
-    is_get_categories_(false) {
+    is_get_category_groups_(false),
+    category_filter_(
+        base::debug::CategoryFilter::kDefaultCategoryFilterString) {
   TraceLog::GetInstance()->SetNotificationCallback(
       base::Bind(&TraceControllerImpl::OnTraceNotification,
                  base::Unretained(this)));
@@ -106,40 +108,23 @@
       base::TimeDelta::FromSeconds(delay_secs));
 }
 
-bool TraceControllerImpl::GetKnownCategoriesAsync(TraceSubscriber* subscriber) {
+bool TraceControllerImpl::GetKnownCategoryGroupsAsync(
+    TraceSubscriber* subscriber) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
   // Known categories come back from child processes with the EndTracingAck
   // message. So to get known categories, just begin and end tracing immediately
   // afterwards. This will ping all the child processes for categories.
-  is_get_categories_ = true;
+  is_get_category_groups_ = true;
   bool success = BeginTracing(subscriber, "*",
                               TraceLog::GetInstance()->trace_options()) &&
                  EndTracingAsync(subscriber);
-  is_get_categories_ = success;
+  is_get_category_groups_ = success;
   return success;
 }
 
-bool TraceControllerImpl::BeginTracing(
-    TraceSubscriber* subscriber,
-    const std::vector<std::string>& included_categories,
-    const std::vector<std::string>& excluded_categories,
-    base::debug::TraceLog::Options options) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
-  if (!can_begin_tracing(subscriber))
-    return false;
-
-  // Enable tracing
-  TraceLog::GetInstance()->SetEnabled(included_categories, excluded_categories,
-                                      options);
-  OnTracingBegan(subscriber);
-
-  return true;
-}
-
 bool TraceControllerImpl::BeginTracing(TraceSubscriber* subscriber,
-                                       const std::string& categories,
+                                       const std::string& category_patterns,
                                        base::debug::TraceLog::Options options) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
@@ -147,7 +132,8 @@
     return false;
 
   // Enable tracing
-  TraceLog::GetInstance()->SetEnabled(categories, options);
+  TraceLog::GetInstance()->SetEnabled(
+      base::debug::CategoryFilter(category_patterns), options);
 
   OnTracingBegan(subscriber);
 
@@ -170,11 +156,11 @@
   // Handle special case of zero child processes.
   if (pending_end_ack_count_ == 1) {
     // Ack asynchronously now, because we don't have any children to wait for.
-    std::vector<std::string> categories;
-    TraceLog::GetInstance()->GetKnownCategories(&categories);
+    std::vector<std::string> category_groups;
+    TraceLog::GetInstance()->GetKnownCategoryGroups(&category_groups);
     BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
         base::Bind(&TraceControllerImpl::OnEndTracingAck,
-                   base::Unretained(this), categories));
+                   base::Unretained(this), category_groups));
   }
 
   // Notify all child processes.
@@ -265,8 +251,8 @@
 
   filters_.insert(filter);
   if (is_tracing_enabled()) {
-    filter->SendBeginTracing(included_categories_, excluded_categories_,
-                             trace_options_);
+    std::string cf_str = category_filter_.ToString();
+    filter->SendBeginTracing(cf_str, trace_options_);
     if (!watch_category_.empty())
       filter->SendSetWatchEvent(watch_category_, watch_name_);
   }
@@ -288,28 +274,27 @@
 
   subscriber_ = subscriber;
 
-  TraceLog::GetInstance()->GetEnabledTraceCategories(&included_categories_,
-                                                     &excluded_categories_);
+  category_filter_ = TraceLog::GetInstance()->GetCurrentCategoryFilter();
   trace_options_ = TraceLog::GetInstance()->trace_options();
 
   // Notify all child processes.
   for (FilterMap::iterator it = filters_.begin(); it != filters_.end(); ++it) {
-    it->get()->SendBeginTracing(included_categories_, excluded_categories_,
-                                trace_options_);
+    it->get()->SendBeginTracing(category_filter_.ToString(), trace_options_);
   }
 }
 
 void TraceControllerImpl::OnEndTracingAck(
-    const std::vector<std::string>& known_categories) {
+    const std::vector<std::string>& known_category_groups) {
   if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
     BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
         base::Bind(&TraceControllerImpl::OnEndTracingAck,
-                   base::Unretained(this), known_categories));
+                   base::Unretained(this), known_category_groups));
     return;
   }
 
-  // Merge known_categories with known_categories_
-  known_categories_.insert(known_categories.begin(), known_categories.end());
+  // Merge known_category_groups with known_category_groups_
+  known_category_groups_.insert(known_category_groups.begin(),
+                                known_category_groups.end());
 
   if (pending_end_ack_count_ == 0)
     return;
@@ -331,25 +316,25 @@
 
     // Trigger callback if one is set.
     if (subscriber_) {
-      if (is_get_categories_)
-        subscriber_->OnKnownCategoriesCollected(known_categories_);
+      if (is_get_category_groups_)
+        subscriber_->OnKnownCategoriesCollected(known_category_groups_);
       else
         subscriber_->OnEndTracingComplete();
       // Clear subscriber so that others can use TraceController.
       subscriber_ = NULL;
     }
 
-    is_get_categories_ = false;
+    is_get_category_groups_ = false;
   }
 
   if (pending_end_ack_count_ == 1) {
     // The last ack represents local trace, so we need to ack it now. Note that
     // this code only executes if there were child processes.
-    std::vector<std::string> categories;
-    TraceLog::GetInstance()->GetKnownCategories(&categories);
+    std::vector<std::string> category_groups;
+    TraceLog::GetInstance()->GetKnownCategoryGroups(&category_groups);
     BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
         base::Bind(&TraceControllerImpl::OnEndTracingAck,
-                   base::Unretained(this), categories));
+                   base::Unretained(this), category_groups));
   }
 }
 
@@ -365,7 +350,7 @@
   }
 
   // Drop trace events if we are just getting categories.
-  if (subscriber_ && !is_get_categories_)
+  if (subscriber_ && !is_get_category_groups_)
     subscriber_->OnTraceDataCollected(events_str_ptr);
 }
 
diff --git a/content/browser/tracing/trace_controller_impl.h b/content/browser/tracing/trace_controller_impl.h
index 248f131..f24d283 100644
--- a/content/browser/tracing/trace_controller_impl.h
+++ b/content/browser/tracing/trace_controller_impl.h
@@ -26,19 +26,9 @@
   // startup tracing.
   void InitStartupTracing(const CommandLine& command_line);
 
-  // Same as above, but specifies which categories to trace.
-  // If both included_categories and excluded_categories are empty,
-  //   all categories are traced.
-  // Else if included_categories is non-empty, only those are traced.
-  // Else if excluded_categories is non-empty, everything but those are traced.
-  bool BeginTracing(TraceSubscriber* subscriber,
-                    const std::vector<std::string>& included_categories,
-                    const std::vector<std::string>& excluded_categories,
-                    base::debug::TraceLog::Options options);
-
   // TraceController implementation:
   virtual bool BeginTracing(TraceSubscriber* subscriber,
-                            const std::string& categories,
+                            const std::string& category_patterns,
                             base::debug::TraceLog::Options options) OVERRIDE;
   virtual  bool EndTracingAsync(TraceSubscriber* subscriber) OVERRIDE;
   virtual bool GetTraceBufferPercentFullAsync(
@@ -48,7 +38,8 @@
                              const std::string& event_name) OVERRIDE;
   virtual bool CancelWatchEvent(TraceSubscriber* subscriber) OVERRIDE;
   virtual void CancelSubscriber(TraceSubscriber* subscriber) OVERRIDE;
-  virtual bool GetKnownCategoriesAsync(TraceSubscriber* subscriber) OVERRIDE;
+  virtual bool GetKnownCategoryGroupsAsync(TraceSubscriber* subscriber)
+      OVERRIDE;
 
  private:
   typedef std::set<scoped_refptr<TraceMessageFilter> > FilterMap;
@@ -84,7 +75,7 @@
   void AddFilter(TraceMessageFilter* filter);
   void RemoveFilter(TraceMessageFilter* filter);
   void OnTracingBegan(TraceSubscriber* subscriber);
-  void OnEndTracingAck(const std::vector<std::string>& known_categories);
+  void OnEndTracingAck(const std::vector<std::string>& known_category_groups);
   void OnTraceDataCollected(
       const scoped_refptr<base::RefCountedString>& events_str_ptr);
   void OnTraceNotification(int notification);
@@ -98,13 +89,12 @@
   int pending_bpf_ack_count_;
   float maximum_bpf_;
   bool is_tracing_;
-  bool is_get_categories_;
-  std::set<std::string> known_categories_;
-  std::vector<std::string> included_categories_;
-  std::vector<std::string> excluded_categories_;
+  bool is_get_category_groups_;
+  std::set<std::string> known_category_groups_;
   std::string watch_category_;
   std::string watch_name_;
   base::debug::TraceLog::Options trace_options_;
+  base::debug::CategoryFilter category_filter_;
 
   DISALLOW_COPY_AND_ASSIGN(TraceControllerImpl);
 };
diff --git a/content/browser/tracing/trace_message_filter.cc b/content/browser/tracing/trace_message_filter.cc
index 8894cff..e75d786 100644
--- a/content/browser/tracing/trace_message_filter.cc
+++ b/content/browser/tracing/trace_message_filter.cc
@@ -55,11 +55,10 @@
 }
 
 void TraceMessageFilter::SendBeginTracing(
-    const std::vector<std::string>& included_categories,
-    const std::vector<std::string>& excluded_categories,
+    const std::string& category_filter_str,
     base::debug::TraceLog::Options options) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  Send(new TracingMsg_BeginTracing(included_categories, excluded_categories,
+  Send(new TracingMsg_BeginTracing(category_filter_str,
                                    base::TimeTicks::NowFromSystemTraceTime(),
                                    options));
 }
diff --git a/content/browser/tracing/trace_message_filter.h b/content/browser/tracing/trace_message_filter.h
index aa5f336..8da3453 100644
--- a/content/browser/tracing/trace_message_filter.h
+++ b/content/browser/tracing/trace_message_filter.h
@@ -28,8 +28,7 @@
   virtual bool OnMessageReceived(const IPC::Message& message,
                                  bool* message_was_ok) OVERRIDE;
 
-  void SendBeginTracing(const std::vector<std::string>& included_categories,
-                        const std::vector<std::string>& excluded_categories,
+  void SendBeginTracing(const std::string& category_filter_str,
                         base::debug::TraceLog::Options options);
   void SendEndTracing();
   void SendGetTraceBufferPercentFull();
diff --git a/content/browser/tracing/tracing_ui.cc b/content/browser/tracing/tracing_ui.cc
index aa2e529..5b7e359 100644
--- a/content/browser/tracing/tracing_ui.cc
+++ b/content/browser/tracing/tracing_ui.cc
@@ -12,6 +12,7 @@
 #include "base/debug/trace_event.h"
 #include "base/file_util.h"
 #include "base/memory/scoped_ptr.h"
+#include "base/string_util.h"
 #include "base/stringprintf.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/utf_string_conversions.h"
@@ -40,8 +41,7 @@
 namespace {
 
 WebUIDataSource* CreateTracingHTMLSource() {
-  WebUIDataSource* source =
-      WebUIDataSource::Create(chrome::kChromeUITracingHost);
+  WebUIDataSource* source = WebUIDataSource::Create(kChromeUITracingHost);
 
   source->SetJsonPath("strings.js");
   source->SetDefaultResource(IDR_TRACING_HTML);
@@ -306,7 +306,7 @@
 
 void TracingMessageHandler::OnLoadTraceFile(const base::ListValue* list) {
   // Only allow a single dialog at a time.
-  if (select_trace_file_dialog_.get())
+  if (select_trace_file_dialog_)
     return;
   select_trace_file_dialog_type_ = ui::SelectFileDialog::SELECT_OPEN_FILE;
   select_trace_file_dialog_ = ui::SelectFileDialog::Create(
@@ -317,8 +317,11 @@
       ui::SelectFileDialog::SELECT_OPEN_FILE,
       string16(),
       base::FilePath(),
-      NULL, 0, FILE_PATH_LITERAL(""),
-      web_ui()->GetWebContents()->GetView()->GetTopLevelNativeWindow(), NULL);
+      NULL,
+      0,
+      base::FilePath::StringType(),
+      web_ui()->GetWebContents()->GetView()->GetTopLevelNativeWindow(),
+      NULL);
 }
 
 void TracingMessageHandler::LoadTraceFileComplete(string16* contents) {
@@ -342,13 +345,13 @@
     rvh->ExecuteJavascriptInWebFrame(string16(), javascript);
   }
   rvh->ExecuteJavascriptInWebFrame(string16(), UTF8ToUTF16(
-      "tracingController.onLoadTraceFileComplete(JSON.parse(window.traceData));"
+      "tracingController.onLoadTraceFileComplete(window.traceData);"
       "delete window.traceData;"));
 }
 
 void TracingMessageHandler::OnSaveTraceFile(const base::ListValue* list) {
   // Only allow a single dialog at a time.
-  if (select_trace_file_dialog_.get())
+  if (select_trace_file_dialog_)
     return;
 
   DCHECK(list->GetSize() == 1);
@@ -367,8 +370,11 @@
       ui::SelectFileDialog::SELECT_SAVEAS_FILE,
       string16(),
       base::FilePath(),
-      NULL, 0, FILE_PATH_LITERAL(""),
-      web_ui()->GetWebContents()->GetView()->GetTopLevelNativeWindow(), NULL);
+      NULL,
+      0,
+      base::FilePath::StringType(),
+      web_ui()->GetWebContents()->GetView()->GetTopLevelNativeWindow(),
+      NULL);
 }
 
 void TracingMessageHandler::SaveTraceFileComplete() {
@@ -420,6 +426,14 @@
 void TracingMessageHandler::OnEndTracingAsync(const base::ListValue* list) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
+  // This is really us beginning to end tracing, rather than tracing being truly
+  // over. When this function yields, we expect to get some number of
+  // OnTraceDataCollected callbacks, which will append data to window.traceData.
+  // To set up for this, set window.traceData to the empty string.
+  web_ui()->GetWebContents()->GetRenderViewHost()->
+    ExecuteJavascriptInWebFrame(string16(),
+                                UTF8ToUTF16("window.traceData = '';"));
+
   // TODO(nduca): fix javascript code to make sure trace_enabled_ is always true
   //              here. triggered a false condition by just clicking stop
   //              trace a few times when it was going slow, and maybe switching
@@ -450,7 +464,11 @@
     return;
 #endif
   }
-  web_ui()->CallJavascriptFunction("tracingController.onEndTracingComplete");
+
+  RenderViewHost* rvh = web_ui()->GetWebContents()->GetRenderViewHost();
+  rvh->ExecuteJavascriptInWebFrame(string16(), UTF8ToUTF16(
+      "tracingController.onEndTracingComplete(window.traceData);"
+      "delete window.traceData;"));
 }
 
 void TracingMessageHandler::OnEndSystemTracingAck(
@@ -469,17 +487,19 @@
     const scoped_refptr<base::RefCountedString>& trace_fragment) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
-  base::debug::TraceResultBuffer::SimpleOutput output;
-  base::debug::TraceResultBuffer trace_buffer;
-  trace_buffer.SetOutputCallback(output.GetCallback());
-  output.Append("tracingController.onTraceDataCollected(");
-  trace_buffer.Start();
-  trace_buffer.AddFragment(trace_fragment->data());
-  trace_buffer.Finish();
-  output.Append(");");
+  std::string javascript("window.traceData += '");
+
+  std::string escaped_data;
+  ReplaceChars(trace_fragment->data(), "\\", "\\\\", &escaped_data);
+  javascript += escaped_data;
+
+  // Intentionally append a , to the traceData. This technically causes all
+  // traceData that we pass back to JS to end with a comma, but that is actually
+  // something the JS side strips away anyway
+  javascript += ",';";
 
   web_ui()->GetWebContents()->GetRenderViewHost()->
-      ExecuteJavascriptInWebFrame(string16(), UTF8ToUTF16(output.json_output));
+    ExecuteJavascriptInWebFrame(string16(), UTF8ToUTF16(javascript));
 }
 
 void TracingMessageHandler::OnTraceBufferPercentFullReply(float percent_full) {
@@ -491,7 +511,7 @@
 
 void TracingMessageHandler::OnGetKnownCategories(const base::ListValue* list) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  if (!TraceController::GetInstance()->GetKnownCategoriesAsync(this)) {
+  if (!TraceController::GetInstance()->GetKnownCategoryGroupsAsync(this)) {
     std::set<std::string> ret;
     OnKnownCategoriesCollected(ret);
   }
diff --git a/content/browser/udev_linux.cc b/content/browser/udev_linux.cc
index d9f31db..13f5494 100644
--- a/content/browser/udev_linux.cc
+++ b/content/browser/udev_linux.cc
@@ -32,8 +32,12 @@
   monitor_fd_ = udev_monitor_get_fd(monitor_);
   CHECK_GE(monitor_fd_, 0);
 
-  bool success = MessageLoopForIO::current()->WatchFileDescriptor(monitor_fd_,
-      true, MessageLoopForIO::WATCH_READ, &monitor_watcher_, this);
+  bool success = base::MessageLoopForIO::current()->WatchFileDescriptor(
+      monitor_fd_,
+      true,
+      base::MessageLoopForIO::WATCH_READ,
+      &monitor_watcher_,
+      this);
   CHECK(success);
 }
 
diff --git a/content/browser/web_contents/OWNERS b/content/browser/web_contents/OWNERS
index e5c12b0..4966076 100644
--- a/content/browser/web_contents/OWNERS
+++ b/content/browser/web_contents/OWNERS
@@ -1,2 +1,2 @@
-# for *aura.*

-ben@chromium.org

+# for *aura*
+per-file *aura*=ben@chromium.org
diff --git a/content/browser/web_contents/aura/image_window_delegate.cc b/content/browser/web_contents/aura/image_window_delegate.cc
new file mode 100644
index 0000000..1829f46
--- /dev/null
+++ b/content/browser/web_contents/aura/image_window_delegate.cc
@@ -0,0 +1,100 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/web_contents/aura/image_window_delegate.h"
+
+#include "ui/base/hit_test.h"
+#include "ui/compositor/compositor.h"
+#include "ui/gfx/canvas.h"
+#include "ui/gfx/image/image.h"
+#include "ui/gfx/image/image_skia.h"
+#include "ui/gfx/rect.h"
+#include "ui/gfx/size.h"
+
+namespace content {
+
+ImageWindowDelegate::ImageWindowDelegate()
+    : size_mismatch_(false) {
+}
+
+ImageWindowDelegate::~ImageWindowDelegate() {
+}
+
+void ImageWindowDelegate::SetImage(const gfx::Image& image) {
+  image_ = image;
+  if (!window_size_.IsEmpty() && !image_.IsEmpty())
+    size_mismatch_ = window_size_ != image_.AsImageSkia().size();
+}
+
+gfx::Size ImageWindowDelegate::GetMinimumSize() const {
+  return gfx::Size();
+}
+
+gfx::Size ImageWindowDelegate::GetMaximumSize() const {
+  return gfx::Size();
+}
+
+void ImageWindowDelegate::OnBoundsChanged(const gfx::Rect& old_bounds,
+                                          const gfx::Rect& new_bounds) {
+  window_size_ = new_bounds.size();
+  if (!image_.IsEmpty())
+    size_mismatch_ = window_size_ != image_.AsImageSkia().size();
+}
+
+gfx::NativeCursor ImageWindowDelegate::GetCursor(const gfx::Point& point) {
+  return gfx::kNullCursor;
+}
+
+int ImageWindowDelegate::GetNonClientComponent(const gfx::Point& point) const {
+  return HTNOWHERE;
+}
+
+bool ImageWindowDelegate::ShouldDescendIntoChildForEventHandling(
+    aura::Window* child,
+    const gfx::Point& location) {
+  return false;
+}
+
+bool ImageWindowDelegate::CanFocus() {
+  return false;
+}
+
+void ImageWindowDelegate::OnCaptureLost() {
+}
+
+void ImageWindowDelegate::OnPaint(gfx::Canvas* canvas) {
+  if (image_.IsEmpty()) {
+    canvas->DrawColor(SK_ColorGRAY);
+  } else {
+    if (size_mismatch_)
+      canvas->DrawColor(SK_ColorWHITE);
+    canvas->DrawImageInt(image_.AsImageSkia(), 0, 0);
+  }
+}
+
+void ImageWindowDelegate::OnDeviceScaleFactorChanged(float scale_factor) {
+}
+
+void ImageWindowDelegate::OnWindowDestroying() {
+}
+
+void ImageWindowDelegate::OnWindowDestroyed() {
+  delete this;
+}
+
+void ImageWindowDelegate::OnWindowTargetVisibilityChanged(bool visible) {
+}
+
+bool ImageWindowDelegate::HasHitTestMask() const {
+  return false;
+}
+
+void ImageWindowDelegate::GetHitTestMask(gfx::Path* mask) const {
+}
+
+scoped_refptr<ui::Texture> ImageWindowDelegate::CopyTexture() {
+  return scoped_refptr<ui::Texture>();
+}
+
+}  // namespace content
diff --git a/content/browser/web_contents/aura/image_window_delegate.h b/content/browser/web_contents/aura/image_window_delegate.h
new file mode 100644
index 0000000..ad92ce2
--- /dev/null
+++ b/content/browser/web_contents/aura/image_window_delegate.h
@@ -0,0 +1,61 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_WEB_CONTENTS_AURA_IMAGE_WINDOW_DELEGATE_H_
+#define CONTENT_BROWSER_WEB_CONTENTS_AURA_IMAGE_WINDOW_DELEGATE_H_
+
+#include "ui/aura/window_delegate.h"
+#include "ui/gfx/image/image.h"
+#include "ui/gfx/size.h"
+
+namespace content {
+
+// An ImageWindowDelegate paints an image for a Window. The delegate destroys
+// itself when the Window is destroyed. The delegate does not consume any event.
+class ImageWindowDelegate : public aura::WindowDelegate {
+ public:
+  ImageWindowDelegate();
+
+  void SetImage(const gfx::Image& image);
+  bool has_image() const { return !image_.IsEmpty(); }
+
+ protected:
+  virtual ~ImageWindowDelegate();
+
+  // Overridden from aura::WindowDelegate:
+  virtual gfx::Size GetMinimumSize() const OVERRIDE;
+  virtual gfx::Size GetMaximumSize() const OVERRIDE;
+  virtual void OnBoundsChanged(const gfx::Rect& old_bounds,
+                               const gfx::Rect& new_bounds) OVERRIDE;
+  virtual gfx::NativeCursor GetCursor(const gfx::Point& point) OVERRIDE;
+  virtual int GetNonClientComponent(const gfx::Point& point) const OVERRIDE;
+  virtual bool ShouldDescendIntoChildForEventHandling(
+      aura::Window* child,
+      const gfx::Point& location) OVERRIDE;
+  virtual bool CanFocus() OVERRIDE;
+  virtual void OnCaptureLost() OVERRIDE;
+  virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
+  virtual void OnDeviceScaleFactorChanged(float device_scale_factor) OVERRIDE;
+  virtual void OnWindowDestroying() OVERRIDE;
+  virtual void OnWindowDestroyed() OVERRIDE;
+  virtual void OnWindowTargetVisibilityChanged(bool visible) OVERRIDE;
+  virtual bool HasHitTestMask() const OVERRIDE;
+  virtual void GetHitTestMask(gfx::Path* mask) const OVERRIDE;
+  virtual scoped_refptr<ui::Texture> CopyTexture() OVERRIDE;
+
+ protected:
+  gfx::Image image_;
+  gfx::Size window_size_;
+
+  // Keeps track of whether the window size matches the image size or not. If
+  // the image size is smaller than the window size, then the delegate paints a
+  // white background for the missing regions.
+  bool size_mismatch_;
+
+  DISALLOW_COPY_AND_ASSIGN(ImageWindowDelegate);
+};
+
+}  // namespace content
+
+#endif  // CONTENT_BROWSER_WEB_CONTENTS_AURA_IMAGE_WINDOW_DELEGATE_H_
diff --git a/content/browser/web_contents/aura/shadow_layer_delegate.cc b/content/browser/web_contents/aura/shadow_layer_delegate.cc
new file mode 100644
index 0000000..8ff270b
--- /dev/null
+++ b/content/browser/web_contents/aura/shadow_layer_delegate.cc
@@ -0,0 +1,61 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/web_contents/aura/shadow_layer_delegate.h"
+
+#include "base/bind.h"
+#include "third_party/skia/include/effects/SkGradientShader.h"
+#include "ui/aura/window.h"
+#include "ui/compositor/layer.h"
+#include "ui/gfx/canvas.h"
+#include "ui/gfx/skia_util.h"
+
+namespace {
+
+const SkColor kShadowLightColor = SkColorSetARGB(0x0, 0, 0, 0);
+const SkColor kShadowDarkColor = SkColorSetARGB(0x70, 0, 0, 0);
+const int kShadowThick = 7;
+
+}  // namespace
+
+namespace content {
+
+ShadowLayerDelegate::ShadowLayerDelegate(aura::Window* window)
+    : layer_(new ui::Layer(ui::LAYER_TEXTURED)) {
+  layer_->set_delegate(this);
+  layer_->SetBounds(gfx::Rect(-kShadowThick, 0, kShadowThick,
+                              window->bounds().height()));
+  layer_->SetFillsBoundsOpaquely(false);
+  window->layer()->Add(layer_.get());
+}
+
+ShadowLayerDelegate::~ShadowLayerDelegate() {
+}
+
+void ShadowLayerDelegate::OnPaintLayer(gfx::Canvas* canvas) {
+  SkPoint points[2];
+  const SkColor kShadowColors[2] = { kShadowLightColor, kShadowDarkColor };
+
+  points[0].iset(0, 0);
+  points[1].iset(kShadowThick, 0);
+
+  skia::RefPtr<SkShader> shader = skia::AdoptRef(
+      SkGradientShader::CreateLinear(points, kShadowColors, NULL,
+          arraysize(points), SkShader::kRepeat_TileMode, NULL));
+
+  gfx::Rect paint_rect = gfx::Rect(0, 0, kShadowThick,
+                                   layer_->bounds().height());
+  SkPaint paint;
+  paint.setShader(shader.get());
+  canvas->sk_canvas()->drawRect(gfx::RectToSkRect(paint_rect), paint);
+}
+
+void ShadowLayerDelegate::OnDeviceScaleFactorChanged(float scale_factor) {
+}
+
+base::Closure ShadowLayerDelegate::PrepareForLayerBoundsChange() {
+  return base::Bind(&base::DoNothing);
+}
+
+}  // namespace content
diff --git a/content/browser/web_contents/aura/shadow_layer_delegate.h b/content/browser/web_contents/aura/shadow_layer_delegate.h
new file mode 100644
index 0000000..25c2fb4
--- /dev/null
+++ b/content/browser/web_contents/aura/shadow_layer_delegate.h
@@ -0,0 +1,46 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_WEB_CONTENTS_AURA_SHADOW_LAYER_DELEGATE_H_
+#define CONTENT_BROWSER_WEB_CONTENTS_AURA_SHADOW_LAYER_DELEGATE_H_
+
+#include "base/compiler_specific.h"
+#include "base/memory/scoped_ptr.h"
+#include "ui/compositor/layer_delegate.h"
+
+namespace aura {
+class Window;
+}
+
+namespace ui {
+class Layer;
+}
+
+namespace content {
+
+// ShadowLayerDelegate takes care of drawing a shadow on the left edge of a
+// window.
+class ShadowLayerDelegate : public ui::LayerDelegate {
+ public:
+  explicit ShadowLayerDelegate(aura::Window* shadow_for);
+  virtual ~ShadowLayerDelegate();
+
+  // Returns the layer for the shadow. Note that the ShadowLayerDelegate owns
+  // the layer, and the layer is destroyed when the delegate is destroyed.
+  ui::Layer* layer() { return layer_.get(); }
+
+ private:
+  // Overridden from ui::LayerDelegate:
+  virtual void OnPaintLayer(gfx::Canvas* canvas) OVERRIDE;
+  virtual void OnDeviceScaleFactorChanged(float device_scale_factor) OVERRIDE;
+  virtual base::Closure PrepareForLayerBoundsChange() OVERRIDE;
+
+  scoped_ptr<ui::Layer> layer_;
+
+  DISALLOW_COPY_AND_ASSIGN(ShadowLayerDelegate);
+};
+
+}  // namespace content
+
+#endif  //  CONTENT_BROWSER_WEB_CONTENTS_AURA_SHADOW_LAYER_DELEGATE_H_
diff --git a/content/browser/web_contents/debug_urls.cc b/content/browser/web_contents/debug_urls.cc
index f62f0b3..c321b05 100644
--- a/content/browser/web_contents/debug_urls.cc
+++ b/content/browser/web_contents/debug_urls.cc
@@ -42,7 +42,7 @@
   if (!(transition & PAGE_TRANSITION_FROM_ADDRESS_BAR))
     return false;
 
-  if (url.host() == chrome::kChromeUIBrowserCrashHost) {
+  if (url.host() == kChromeUIBrowserCrashHost) {
     // Induce an intentional crash in the browser process.
     CHECK(false);
     return true;
diff --git a/content/browser/web_contents/interstitial_page_impl.cc b/content/browser/web_contents/interstitial_page_impl.cc
index 7e62376..9673e98 100644
--- a/content/browser/web_contents/interstitial_page_impl.cc
+++ b/content/browser/web_contents/interstitial_page_impl.cc
@@ -34,6 +34,7 @@
 #include "content/public/browser/notification_service.h"
 #include "content/public/browser/notification_source.h"
 #include "content/public/browser/storage_partition.h"
+#include "content/public/browser/web_contents_delegate.h"
 #include "content/public/common/bindings_policy.h"
 #include "content/public/common/page_transition_types.h"
 #include "net/base/escape.h"
@@ -147,11 +148,10 @@
       should_revert_web_contents_title_(false),
       web_contents_was_loading_(false),
       resource_dispatcher_host_notified_(false),
-      ALLOW_THIS_IN_INITIALIZER_LIST(rvh_delegate_view_(
-          new InterstitialPageRVHDelegateView(this))),
+      rvh_delegate_view_(new InterstitialPageRVHDelegateView(this)),
       create_view_(true),
       delegate_(delegate),
-      ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) {
+      weak_ptr_factory_(this) {
   InitInterstitialPageMap();
   // It would be inconsistent to create an interstitial with no new navigation
   // (which is the case when the interstitial was triggered by a sub-resource on
@@ -268,7 +268,8 @@
 
   // Shutdown the RVH asynchronously, as we may have been called from a RVH
   // delegate method, and we can't delete the RVH out from under itself.
-  MessageLoop::current()->PostNonNestableTask(FROM_HERE,
+  base::MessageLoop::current()->PostNonNestableTask(
+      FROM_HERE,
       base::Bind(&InterstitialPageImpl::Shutdown,
                  weak_ptr_factory_.GetWeakPtr(),
                  render_view_host_));
@@ -357,9 +358,10 @@
   return url_;
 }
 
-void InterstitialPageImpl::RenderViewGone(RenderViewHost* render_view_host,
-                                          base::TerminationStatus status,
-                                          int error_code) {
+void InterstitialPageImpl::RenderViewTerminated(
+    RenderViewHost* render_view_host,
+    base::TerminationStatus status,
+    int error_code) {
   // Our renderer died. This should not happen in normal cases.
   // If we haven't already started shutdown, just dismiss the interstitial.
   // We cannot check for enabled() here, because we may have called Disable
@@ -450,9 +452,9 @@
   return renderer_preferences_;
 }
 
-webkit_glue::WebPreferences InterstitialPageImpl::GetWebkitPrefs() {
+WebPreferences InterstitialPageImpl::GetWebkitPrefs() {
   if (!enabled())
-    return webkit_glue::WebPreferences();
+    return WebPreferences();
 
   return WebContentsImpl::GetWebkitPrefs(render_view_host_, url_);
 }
@@ -476,6 +478,13 @@
     web_contents_->HandleKeyboardEvent(event);
 }
 
+#if defined(OS_WIN) && defined(USE_AURA)
+gfx::NativeViewAccessible
+InterstitialPageImpl::GetParentNativeViewAccessible() {
+  return web_contents_->GetParentNativeViewAccessible();
+}
+#endif
+
 WebContents* InterstitialPageImpl::web_contents() const {
   return web_contents_;
 }
@@ -775,6 +784,9 @@
 }
 
 void InterstitialPageImpl::InterstitialPageRVHDelegateView::GotFocus() {
+  WebContents* web_contents = interstitial_page_->web_contents();
+  if (web_contents && web_contents->GetDelegate())
+    web_contents->GetDelegate()->WebContentsFocused(web_contents);
 }
 
 void InterstitialPageImpl::InterstitialPageRVHDelegateView::TakeFocus(
diff --git a/content/browser/web_contents/interstitial_page_impl.h b/content/browser/web_contents/interstitial_page_impl.h
index 2d56015..2b3108a 100644
--- a/content/browser/web_contents/interstitial_page_impl.h
+++ b/content/browser/web_contents/interstitial_page_impl.h
@@ -92,9 +92,9 @@
   // RenderViewHostDelegate implementation:
   virtual RenderViewHostDelegateView* GetDelegateView() OVERRIDE;
   virtual const GURL& GetURL() const OVERRIDE;
-  virtual void RenderViewGone(RenderViewHost* render_view_host,
-                              base::TerminationStatus status,
-                              int error_code) OVERRIDE;
+  virtual void RenderViewTerminated(RenderViewHost* render_view_host,
+                                    base::TerminationStatus status,
+                                    int error_code) OVERRIDE;
   virtual void DidNavigate(
       RenderViewHost* render_view_host,
       const ViewHostMsg_FrameNavigate_Params& params) OVERRIDE;
@@ -104,7 +104,7 @@
                            base::i18n::TextDirection title_direction) OVERRIDE;
   virtual RendererPreferences GetRendererPrefs(
       BrowserContext* browser_context) const OVERRIDE;
-  virtual webkit_glue::WebPreferences GetWebkitPrefs() OVERRIDE;
+  virtual WebPreferences GetWebkitPrefs() OVERRIDE;
   virtual gfx::Rect GetRootWindowResizerRect() const OVERRIDE;
   virtual void CreateNewWindow(
       int route_id,
@@ -132,6 +132,9 @@
       bool* is_keyboard_shortcut) OVERRIDE;
   virtual void HandleKeyboardEvent(
       const NativeWebKeyboardEvent& event) OVERRIDE;
+#if defined(OS_WIN) && defined(USE_AURA)
+  virtual gfx::NativeViewAccessible GetParentNativeViewAccessible() OVERRIDE;
+#endif
 
   bool enabled() const { return enabled_; }
   WebContents* web_contents() const;
diff --git a/content/browser/web_contents/navigation_controller_impl.cc b/content/browser/web_contents/navigation_controller_impl.cc
index c8218af..f7c8215 100644
--- a/content/browser/web_contents/navigation_controller_impl.cc
+++ b/content/browser/web_contents/navigation_controller_impl.cc
@@ -5,7 +5,6 @@
 #include "content/browser/web_contents/navigation_controller_impl.h"
 
 #include "base/bind.h"
-#include "base/command_line.h"
 #include "base/file_util.h"
 #include "base/logging.h"
 #include "base/string_number_conversions.h"  // Temporary
@@ -22,6 +21,7 @@
 #include "content/browser/web_contents/interstitial_page_impl.h"
 #include "content/browser/web_contents/navigation_entry_impl.h"
 #include "content/browser/web_contents/web_contents_impl.h"
+#include "content/browser/web_contents/web_contents_screenshot_manager.h"
 #include "content/common/view_messages.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/content_browser_client.h"
@@ -36,13 +36,11 @@
 #include "content/public/browser/web_contents_delegate.h"
 #include "content/public/common/content_client.h"
 #include "content/public/common/content_constants.h"
-#include "content/public/common/content_switches.h"
 #include "content/public/common/url_constants.h"
 #include "net/base/escape.h"
 #include "net/base/mime_util.h"
 #include "net/base/net_util.h"
 #include "skia/ext/platform_canvas.h"
-#include "ui/gfx/codec/png_codec.h"
 #include "webkit/glue/glue_serialize.h"
 
 namespace content {
@@ -215,12 +213,12 @@
       transient_entry_index_(-1),
       web_contents_(web_contents),
       max_restored_page_id_(-1),
-      ALLOW_THIS_IN_INITIALIZER_LIST(ssl_manager_(this)),
+      ssl_manager_(this),
       needs_reload_(false),
       is_initial_navigation_(true),
       pending_reload_(NO_RELOAD),
       get_timestamp_callback_(base::Bind(&base::Time::Now)),
-      ALLOW_THIS_IN_INITIALIZER_LIST(take_screenshot_factory_(this)) {
+      screenshot_manager_(new WebContentsScreenshotManager(this)) {
   DCHECK(browser_context_);
 }
 
@@ -476,151 +474,13 @@
 }
 
 void NavigationControllerImpl::TakeScreenshot() {
-  static bool overscroll_enabled = !CommandLine::ForCurrentProcess()->
-      HasSwitch(switches::kDisableOverscrollHistoryNavigation);
-  if (!overscroll_enabled)
-    return;
-
-  NavigationEntryImpl* entry =
-      NavigationEntryImpl::FromNavigationEntry(GetLastCommittedEntry());
-  if (!entry)
-    return;
-
-  RenderViewHost* render_view_host = web_contents_->GetRenderViewHost();
-  if (!static_cast<RenderViewHostImpl*>
-      (render_view_host)->overscroll_controller()) {
-    return;
-  }
-  content::RenderWidgetHostView* view = render_view_host->GetView();
-  if (!view)
-    return;
-
-  if (!take_screenshot_callback_.is_null())
-    take_screenshot_callback_.Run(render_view_host);
-
-  render_view_host->CopyFromBackingStore(gfx::Rect(),
-      view->GetViewBounds().size(),
-      base::Bind(&NavigationControllerImpl::OnScreenshotTaken,
-                 take_screenshot_factory_.GetWeakPtr(),
-                 entry->GetUniqueID()));
+  screenshot_manager_->TakeScreenshot();
 }
 
-void NavigationControllerImpl::OnScreenshotTaken(
-    int unique_id,
-    bool success,
-    const SkBitmap& bitmap) {
-  NavigationEntryImpl* entry = NULL;
-  for (NavigationEntries::iterator i = entries_.begin();
-       i != entries_.end();
-       ++i) {
-    if ((*i)->GetUniqueID() == unique_id) {
-      entry = (*i).get();
-      break;
-    }
-  }
-
-  if (!entry) {
-    LOG(ERROR) << "Invalid entry with unique id: " << unique_id;
-    return;
-  }
-
-  if (!success || bitmap.empty() || bitmap.isNull()) {
-    ClearScreenshot(entry);
-    return;
-  }
-
-  std::vector<unsigned char> data;
-  if (gfx::PNGCodec::EncodeBGRASkBitmap(bitmap, true, &data)) {
-    entry->SetScreenshotPNGData(data);
-    PurgeScreenshotsIfNecessary();
-  } else {
-    ClearScreenshot(entry);
-  }
-}
-
-bool NavigationControllerImpl::ClearScreenshot(NavigationEntryImpl* entry) {
-  if (!entry->screenshot())
-    return false;
-
-  entry->SetScreenshotPNGData(std::vector<unsigned char>());
-  return true;
-}
-
-void NavigationControllerImpl::PurgeScreenshotsIfNecessary() {
-  // Allow only a certain number of entries to keep screenshots.
-  const int kMaxScreenshots = 10;
-  int screenshot_count = GetScreenshotCount();
-  if (screenshot_count < kMaxScreenshots)
-    return;
-
-  const int current = GetCurrentEntryIndex();
-  const int num_entries = GetEntryCount();
-  int available_slots = kMaxScreenshots;
-  if (NavigationEntryImpl::FromNavigationEntry(
-          GetEntryAtIndex(current))->screenshot())
-    --available_slots;
-
-  // Keep screenshots closer to the current navigation entry, and purge the ones
-  // that are farther away from it. So in each step, look at the entries at
-  // each offset on both the back and forward history, and start counting them
-  // to make sure that the correct number of screenshots are kept in memory.
-  // Note that it is possible for some entries to be missing screenshots (e.g.
-  // when taking the screenshot failed for some reason). So there may be a state
-  // where there are a lot of entries in the back history, but none of them has
-  // any screenshot. In such cases, keep the screenshots for |kMaxScreenshots|
-  // entries in the forward history list.
-  int back = current - 1;
-  int forward = current + 1;
-  while (available_slots > 0 && (back >= 0 || forward < num_entries)) {
-    if (back >= 0) {
-      NavigationEntryImpl* entry = NavigationEntryImpl::FromNavigationEntry(
-          GetEntryAtIndex(back));
-      if (entry->screenshot())
-        --available_slots;
-      --back;
-    }
-
-    if (available_slots > 0 && forward < num_entries) {
-      NavigationEntryImpl* entry = NavigationEntryImpl::FromNavigationEntry(
-          GetEntryAtIndex(forward));
-      if (entry->screenshot())
-        --available_slots;
-      ++forward;
-    }
-  }
-
-  // Purge any screenshot at |back| or lower indices, and |forward| or higher
-  // indices.
-
-  while (screenshot_count > kMaxScreenshots && back >= 0) {
-    NavigationEntryImpl* entry = NavigationEntryImpl::FromNavigationEntry(
-        GetEntryAtIndex(back));
-    if (ClearScreenshot(entry))
-      --screenshot_count;
-    --back;
-  }
-
-  while (screenshot_count > kMaxScreenshots && forward < num_entries) {
-    NavigationEntryImpl* entry = NavigationEntryImpl::FromNavigationEntry(
-        GetEntryAtIndex(forward));
-    if (ClearScreenshot(entry))
-      --screenshot_count;
-    ++forward;
-  }
-  CHECK_GE(screenshot_count, 0);
-  CHECK_LE(screenshot_count, kMaxScreenshots);
-}
-
-int NavigationControllerImpl::GetScreenshotCount() const {
-  int count = 0;
-  for (NavigationEntries::const_iterator it = entries_.begin();
-       it != entries_.end(); ++it) {
-    NavigationEntryImpl* entry =
-        NavigationEntryImpl::FromNavigationEntry(it->get());
-    if (entry->screenshot())
-      count++;
-  }
-  return count;
+void NavigationControllerImpl::SetScreenshotManager(
+    WebContentsScreenshotManager* manager) {
+  screenshot_manager_.reset(manager ? manager :
+                            new WebContentsScreenshotManager(this));
 }
 
 bool NavigationControllerImpl::CanGoBack() const {
@@ -799,6 +659,7 @@
           browser_context_));
   if (params.is_cross_site_redirect)
     entry->set_should_replace_entry(true);
+  entry->set_should_clear_history_list(params.should_clear_history_list);
   entry->SetIsOverridingUserAgent(override);
   entry->set_transferred_global_request_id(
       params.transferred_global_request_id);
@@ -921,6 +782,10 @@
   // the renderer.
   active_entry->set_is_renderer_initiated(false);
 
+  // Once committed, we no longer need to track whether the session history was
+  // cleared. Navigating to this entry again shouldn't clear it again.
+  active_entry->set_should_clear_history_list(false);
+
   // The active entry's SiteInstance should match our SiteInstance.
   CHECK(active_entry->site_instance() == web_contents_->GetSiteInstance());
 
@@ -983,6 +848,9 @@
     return NAVIGATION_TYPE_NEW_SUBFRAME;
   }
 
+  // We only clear the session history when navigating to a new page.
+  DCHECK(!params.history_list_was_cleared);
+
   // Now we know that the notification is for an existing page. Find that entry.
   int existing_entry_index = GetEntryIndexWithPageID(
       web_contents_->GetSiteInstance(),
@@ -1128,6 +996,16 @@
   new_entry->SetOriginalRequestURL(params.original_request_url);
   new_entry->SetIsOverridingUserAgent(params.is_overriding_user_agent);
 
+  DCHECK(!params.history_list_was_cleared || !replace_entry);
+  // The browser requested to clear the session history when it initiated the
+  // navigation. Now we know that the renderer has updated its state accordingly
+  // and it is safe to also clear the browser side history.
+  if (params.history_list_was_cleared) {
+    DiscardNonCommittedEntriesInternal();
+    entries_.clear();
+    last_committed_entry_index_ = -1;
+  }
+
   InsertOrReplaceEntry(new_entry, replace_entry);
 }
 
@@ -1458,14 +1336,8 @@
   }
 }
 
-// Implemented here and not in NavigationEntry because this controller caches
-// the total number of screen shots across all entries.
 void NavigationControllerImpl::ClearAllScreenshots() {
-  for (NavigationEntries::iterator it = entries_.begin();
-       it != entries_.end();
-       ++it)
-    ClearScreenshot(it->get());
-  DCHECK_EQ(GetScreenshotCount(), 0);
+  screenshot_manager_->ClearAllScreenshots();
 }
 
 void NavigationControllerImpl::SetSessionStorageNamespace(
@@ -1812,9 +1684,4 @@
   get_timestamp_callback_ = get_timestamp_callback;
 }
 
-void NavigationControllerImpl::SetTakeScreenshotCallbackForTest(
-    const base::Callback<void(RenderViewHost*)>& take_screenshot_callback) {
-  take_screenshot_callback_ = take_screenshot_callback;
-}
-
 }  // namespace content
diff --git a/content/browser/web_contents/navigation_controller_impl.h b/content/browser/web_contents/navigation_controller_impl.h
index 5027990..5e50d10 100644
--- a/content/browser/web_contents/navigation_controller_impl.h
+++ b/content/browser/web_contents/navigation_controller_impl.h
@@ -15,13 +15,13 @@
 #include "content/public/browser/navigation_controller.h"
 #include "content/public/browser/navigation_type.h"
 
-class SkBitmap;
 struct ViewHostMsg_FrameNavigate_Params;
 
 namespace content {
 class NavigationEntryImpl;
 class RenderViewHost;
 class WebContentsImpl;
+class WebContentsScreenshotManager;
 class SiteInstance;
 struct LoadCommittedDetails;
 
@@ -188,8 +188,12 @@
   // Takes a screenshot of the page at the current state.
   void TakeScreenshot();
 
-  void SetTakeScreenshotCallbackForTest(
-      const base::Callback<void(RenderViewHost*)>& take_screenshot_callback);
+  // Sets the screenshot manager for this NavigationControllerImpl. The
+  // controller takes ownership of the screenshot manager and destroys it when
+  // a new screenshot-manager is set, or when the controller is destroyed.
+  // Setting a NULL manager recreates the default screenshot manager and uses
+  // that.
+  void SetScreenshotManager(WebContentsScreenshotManager* manager);
 
  private:
   friend class RestoreHelper;
@@ -311,24 +315,6 @@
   // specified |offset|.  The index returned is not guaranteed to be valid.
   int GetIndexForOffset(int offset) const;
 
-  // The callback invoked when taking the screenshot of the page is complete.
-  // This sets the screenshot on the navigation entry.
-  void OnScreenshotTaken(int unique_id,
-                         bool success,
-                         const SkBitmap& bitmap);
-
-  // Removes the screenshot for the entry, returning true if the entry had a
-  // screenshot.
-  bool ClearScreenshot(NavigationEntryImpl* entry);
-
-  // The screenshots in the NavigationEntryImpls can accumulate and consume a
-  // large amount of memory. This function makes sure that the memory
-  // consumption is within a certain limit.
-  void PurgeScreenshotsIfNecessary();
-
-  // Returns the number of entries with screenshots.
-  int GetScreenshotCount() const;
-
   // ---------------------------------------------------------------------------
 
   // The user browser context associated with this controller.
@@ -399,15 +385,6 @@
   // Used to get timestamps for newly-created navigation entries.
   base::Callback<base::Time()> get_timestamp_callback_;
 
-  // A callback that gets called before taking the screenshot of the page. This
-  // is used only for testing.
-  base::Callback<void(RenderViewHost*)> take_screenshot_callback_;
-
-  // Taking a screenshot can be async. So use a weakptr for the callback to make
-  // sure that the screenshot completion callback does not trigger on a
-  // destroyed NavigationControllerImpl.
-  base::WeakPtrFactory<NavigationControllerImpl> take_screenshot_factory_;
-
   // Used to smooth out timestamps from |get_timestamp_callback_|.
   // Without this, whenever there is a run of redirects or
   // code-generated navigations, those navigations may occur within
@@ -415,6 +392,8 @@
   // the wrong order in the history view.
   TimeSmoother time_smoother_;
 
+  scoped_ptr<WebContentsScreenshotManager> screenshot_manager_;
+
   DISALLOW_COPY_AND_ASSIGN(NavigationControllerImpl);
 };
 
diff --git a/content/browser/web_contents/navigation_controller_impl_unittest.cc b/content/browser/web_contents/navigation_controller_impl_unittest.cc
index 0f25e2e..4a51897 100644
--- a/content/browser/web_contents/navigation_controller_impl_unittest.cc
+++ b/content/browser/web_contents/navigation_controller_impl_unittest.cc
@@ -24,6 +24,7 @@
 #include "content/browser/web_contents/navigation_controller_impl.h"
 #include "content/browser/web_contents/navigation_entry_impl.h"
 #include "content/browser/web_contents/web_contents_impl.h"
+#include "content/browser/web_contents/web_contents_screenshot_manager.h"
 #include "content/common/view_messages.h"
 #include "content/public/browser/navigation_details.h"
 #include "content/public/browser/notification_registrar.h"
@@ -33,6 +34,7 @@
 #include "content/public/browser/web_contents_delegate.h"
 #include "content/public/test/mock_render_process_host.h"
 #include "content/public/test/test_notification_tracker.h"
+#include "content/public/test/test_utils.h"
 #include "content/test/test_web_contents.h"
 #include "net/base/net_util.h"
 #include "skia/ext/platform_canvas.h"
@@ -69,6 +71,57 @@
                 a_bitmap.getSize()) == 0;
 }
 
+class MockScreenshotManager : public content::WebContentsScreenshotManager {
+ public:
+  explicit MockScreenshotManager(content::NavigationControllerImpl* owner)
+      : content::WebContentsScreenshotManager(owner),
+        encoding_screenshot_in_progress_(false) {
+  }
+
+  virtual ~MockScreenshotManager() {
+  }
+
+  void TakeScreenshotFor(content::NavigationEntryImpl* entry) {
+    SkBitmap bitmap;
+    bitmap.setConfig(SkBitmap::kARGB_8888_Config, 1, 1);
+    bitmap.allocPixels();
+    bitmap.eraseRGB(0, 0, 0);
+    encoding_screenshot_in_progress_ = true;
+    OnScreenshotTaken(entry->GetUniqueID(), true, bitmap);
+    WaitUntilScreenshotIsReady();
+  }
+
+  int GetScreenshotCount() {
+    return content::WebContentsScreenshotManager::GetScreenshotCount();
+  }
+
+  void WaitUntilScreenshotIsReady() {
+    if (!encoding_screenshot_in_progress_)
+      return;
+    message_loop_runner_ = new content::MessageLoopRunner;
+    message_loop_runner_->Run();
+  }
+
+ private:
+  // Overridden from content::WebContentsScreenshotManager:
+  virtual void TakeScreenshotImpl(
+      content::RenderViewHost* host,
+      content::NavigationEntryImpl* entry) OVERRIDE {
+  }
+
+  virtual void OnScreenshotSet(content::NavigationEntryImpl* entry) OVERRIDE {
+    encoding_screenshot_in_progress_ = false;
+    WebContentsScreenshotManager::OnScreenshotSet(entry);
+    if (message_loop_runner_)
+      message_loop_runner_->Quit();
+  }
+
+  scoped_refptr<content::MessageLoopRunner> message_loop_runner_;
+  bool encoding_screenshot_in_progress_;
+
+  DISALLOW_COPY_AND_ASSIGN(MockScreenshotManager);
+};
+
 }  // namespace
 
 namespace content {
@@ -3190,11 +3243,6 @@
 TEST_F(NavigationControllerTest, MAYBE_PurgeScreenshot) {
   NavigationControllerImpl& controller = controller_impl();
 
-  // Prepare some data to use as screenshot for each navigation.
-  SkBitmap bitmap;
-  bitmap.setConfig(SkBitmap::kARGB_8888_Config, 1, 1);
-  ASSERT_TRUE(bitmap.allocPixels());
-  bitmap.eraseRGB(0, 0, 0);
   NavigationEntryImpl* entry;
 
   // Navigate enough times to make sure that some screenshots are purged.
@@ -3204,10 +3252,13 @@
     EXPECT_EQ(i, controller.GetCurrentEntryIndex());
   }
 
+  MockScreenshotManager* screenshot_manager =
+      new MockScreenshotManager(&controller);
+  controller.SetScreenshotManager(screenshot_manager);
   for (int i = 0; i < controller.GetEntryCount(); ++i) {
     entry = NavigationEntryImpl::FromNavigationEntry(
         controller.GetEntryAtIndex(i));
-    controller.OnScreenshotTaken(entry->GetUniqueID(), true, bitmap);
+    screenshot_manager->TakeScreenshotFor(entry);
     EXPECT_TRUE(entry->screenshot());
   }
 
@@ -3215,7 +3266,7 @@
   EXPECT_EQ(13, controller.GetEntryCount());
   entry = NavigationEntryImpl::FromNavigationEntry(
       controller.GetEntryAtIndex(11));
-  controller.OnScreenshotTaken(entry->GetUniqueID(), true, bitmap);
+  screenshot_manager->TakeScreenshotFor(entry);
 
   for (int i = 0; i < 2; ++i) {
     entry = NavigationEntryImpl::FromNavigationEntry(
@@ -3236,14 +3287,14 @@
   for (int i = 0; i < controller.GetEntryCount() - 1; ++i) {
     entry = NavigationEntryImpl::FromNavigationEntry(
         controller.GetEntryAtIndex(i));
-    controller.OnScreenshotTaken(entry->GetUniqueID(), true, bitmap);
+    screenshot_manager->TakeScreenshotFor(entry);
   }
 
   for (int i = 10; i <= 12; ++i) {
     entry = NavigationEntryImpl::FromNavigationEntry(
         controller.GetEntryAtIndex(i));
     EXPECT_FALSE(entry->screenshot()) << "Screenshot " << i << " not purged";
-    controller.OnScreenshotTaken(entry->GetUniqueID(), true, bitmap);
+    screenshot_manager->TakeScreenshotFor(entry);
   }
 
   // Navigate to index 7 and assign screenshot to all entries.
@@ -3253,7 +3304,7 @@
   for (int i = 0; i < controller.GetEntryCount() - 1; ++i) {
     entry = NavigationEntryImpl::FromNavigationEntry(
         controller.GetEntryAtIndex(i));
-    controller.OnScreenshotTaken(entry->GetUniqueID(), true, bitmap);
+    screenshot_manager->TakeScreenshotFor(entry);
   }
 
   for (int i = 0; i < 2; ++i) {
@@ -3264,9 +3315,9 @@
 
   // Clear all screenshots.
   EXPECT_EQ(13, controller.GetEntryCount());
-  EXPECT_EQ(10, controller.GetScreenshotCount());
+  EXPECT_EQ(10, screenshot_manager->GetScreenshotCount());
   controller.ClearAllScreenshots();
-  EXPECT_EQ(0, controller.GetScreenshotCount());
+  EXPECT_EQ(0, screenshot_manager->GetScreenshotCount());
   for (int i = 0; i < controller.GetEntryCount(); ++i) {
     entry = NavigationEntryImpl::FromNavigationEntry(
         controller.GetEntryAtIndex(i));
@@ -3274,6 +3325,55 @@
   }
 }
 
+// Test that the navigation controller clears its session history when a
+// navigation commits with the clear history list flag set.
+TEST_F(NavigationControllerTest, ClearHistoryList) {
+  const GURL url1("http://foo1");
+  const GURL url2("http://foo2");
+  const GURL url3("http://foo3");
+  const GURL url4("http://foo4");
+
+  NavigationControllerImpl& controller = controller_impl();
+
+  // Create a session history with three entries, second entry is active.
+  NavigateAndCommit(url1);
+  NavigateAndCommit(url2);
+  NavigateAndCommit(url3);
+  controller.GoBack();
+  contents()->CommitPendingNavigation();
+  EXPECT_EQ(3, controller.GetEntryCount());
+  EXPECT_EQ(1, controller.GetCurrentEntryIndex());
+
+  // Create a new pending navigation, and indicate that the session history
+  // should be cleared.
+  NavigationController::LoadURLParams params(url4);
+  params.should_clear_history_list = true;
+  controller.LoadURLWithParams(params);
+
+  // Verify that the pending entry correctly indicates that the session history
+  // should be cleared.
+  NavigationEntryImpl* entry =
+      NavigationEntryImpl::FromNavigationEntry(
+          controller.GetPendingEntry());
+  ASSERT_TRUE(entry);
+  EXPECT_TRUE(entry->should_clear_history_list());
+
+  // Assume that the RV correctly cleared its history and commit the navigation.
+  static_cast<TestRenderViewHost*>(contents()->GetPendingRenderViewHost())->
+      set_simulate_history_list_was_cleared(true);
+  contents()->CommitPendingNavigation();
+
+  // Verify that the NavigationController's session history was correctly
+  // cleared.
+  EXPECT_EQ(1, controller.GetEntryCount());
+  EXPECT_EQ(0, controller.GetCurrentEntryIndex());
+  EXPECT_EQ(0, controller.GetLastCommittedEntryIndex());
+  EXPECT_EQ(-1, controller.GetPendingEntryIndex());
+  EXPECT_FALSE(controller.CanGoBack());
+  EXPECT_FALSE(controller.CanGoForward());
+  EXPECT_EQ(url4, controller.GetActiveEntry()->GetURL());
+}
+
 /* TODO(brettw) These test pass on my local machine but fail on the XP buildbot
    (but not Vista) cleaning up the directory after they run.
    This should be fixed.
@@ -3322,8 +3422,8 @@
     HistoryService* history = HistoryServiceFactory::GetForProfiles(
         profile(), Profile::IMPLICIT_ACCESS);
     if (history) {
-      history->SetOnBackendDestroyTask(MessageLoop::QuitClosure());
-      MessageLoop::current()->Run();
+      history->SetOnBackendDestroyTask(base::MessageLoop::QuitClosure());
+      base::MessageLoop::current()->Run();
     }
 
     // Do normal cleanup before deleting the profile directory below.
diff --git a/content/browser/web_contents/navigation_entry_impl.cc b/content/browser/web_contents/navigation_entry_impl.cc
index dafc2e0..b904acf 100644
--- a/content/browser/web_contents/navigation_entry_impl.cc
+++ b/content/browser/web_contents/navigation_entry_impl.cc
@@ -50,6 +50,7 @@
       is_overriding_user_agent_(false),
       is_renderer_initiated_(false),
       should_replace_entry_(false),
+      should_clear_history_list_(false),
       can_load_local_resources_(false) {
 }
 
@@ -76,6 +77,7 @@
       is_overriding_user_agent_(false),
       is_renderer_initiated_(is_renderer_initiated),
       should_replace_entry_(false),
+      should_clear_history_list_(false),
       can_load_local_resources_(false) {
 }
 
@@ -310,8 +312,8 @@
 }
 
 void NavigationEntryImpl::SetScreenshotPNGData(
-    const std::vector<unsigned char>& png_data) {
-  screenshot_ = png_data.empty() ? NULL : new base::RefCountedBytes(png_data);
+    scoped_refptr<base::RefCountedBytes> png_data) {
+  screenshot_ = png_data;
   if (screenshot_)
     UMA_HISTOGRAM_MEMORY_KB("Overscroll.ScreenshotSize", screenshot_->size());
 }
diff --git a/content/browser/web_contents/navigation_entry_impl.h b/content/browser/web_contents/navigation_entry_impl.h
index 62234bf..c956867 100644
--- a/content/browser/web_contents/navigation_entry_impl.h
+++ b/content/browser/web_contents/navigation_entry_impl.h
@@ -185,11 +185,20 @@
     should_replace_entry_ = should_replace_entry;
   }
 
-  void SetScreenshotPNGData(const std::vector<unsigned char>& png_data);
+  void SetScreenshotPNGData(scoped_refptr<base::RefCountedBytes> png_data);
   const scoped_refptr<base::RefCountedBytes> screenshot() const {
     return screenshot_;
   }
 
+  // Whether this (pending) navigation should clear the session history. Resets
+  // to false after commit.
+  bool should_clear_history_list() const {
+    return should_clear_history_list_;
+  }
+  void set_should_clear_history_list(bool should_clear_history_list) {
+    should_clear_history_list_ = should_clear_history_list;
+  }
+
  private:
   // WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
   // Session/Tab restore save portions of this class so that it can be recreated
@@ -275,6 +284,13 @@
   // doing the redirect).
   bool should_replace_entry_;
 
+  // This is set to true when this entry's navigation should clear the session
+  // history both on the renderer and browser side. The browser side history
+  // won't be cleared until the renderer has committed this navigation. This
+  // entry is not persisted by the session restore system, as it is always
+  // reset to false after commit.
+  bool should_clear_history_list_;
+
   // Set when this entry should be able to access local file:// resources. This
   // value is not needed after the entry commits and is not persisted.
   bool can_load_local_resources_;
diff --git a/content/browser/web_contents/navigation_entry_impl_unittest.cc b/content/browser/web_contents/navigation_entry_impl_unittest.cc
index 00857ed..8bc5de1 100644
--- a/content/browser/web_contents/navigation_entry_impl_unittest.cc
+++ b/content/browser/web_contents/navigation_entry_impl_unittest.cc
@@ -61,23 +61,23 @@
 
   EXPECT_EQ(GURL(), entry1_->GetURL());
   EXPECT_EQ(GURL(), entry1_->GetVirtualURL());
-  EXPECT_TRUE(entry1_->GetTitleForDisplay("").empty());
+  EXPECT_TRUE(entry1_->GetTitleForDisplay(std::string()).empty());
 
   // Setting URL affects virtual_url and GetTitleForDisplay
   entry1_->SetURL(GURL("http://www.google.com"));
   EXPECT_EQ(GURL("http://www.google.com"), entry1_->GetURL());
   EXPECT_EQ(GURL("http://www.google.com"), entry1_->GetVirtualURL());
   EXPECT_EQ(ASCIIToUTF16("www.google.com"),
-            entry1_->GetTitleForDisplay(""));
+            entry1_->GetTitleForDisplay(std::string()));
 
   // file:/// URLs should only show the filename.
   entry1_->SetURL(GURL("file:///foo/bar baz.txt"));
   EXPECT_EQ(ASCIIToUTF16("bar baz.txt"),
-            entry1_->GetTitleForDisplay(""));
+            entry1_->GetTitleForDisplay(std::string()));
 
   // Title affects GetTitleForDisplay
   entry1_->SetTitle(ASCIIToUTF16("Google"));
-  EXPECT_EQ(ASCIIToUTF16("Google"), entry1_->GetTitleForDisplay(""));
+  EXPECT_EQ(ASCIIToUTF16("Google"), entry1_->GetTitleForDisplay(std::string()));
 
   // Setting virtual_url doesn't affect URL
   entry2_->SetVirtualURL(GURL("display:url"));
@@ -86,7 +86,7 @@
   EXPECT_EQ(GURL("display:url"), entry2_->GetVirtualURL());
 
   // Having a title set in constructor overrides virtual URL
-  EXPECT_EQ(ASCIIToUTF16("title"), entry2_->GetTitleForDisplay(""));
+  EXPECT_EQ(ASCIIToUTF16("title"), entry2_->GetTitleForDisplay(std::string()));
 
   // User typed URL is independent of the others
   EXPECT_EQ(GURL(), entry1_->GetUserTypedURL());
diff --git a/content/browser/web_contents/render_view_host_manager.cc b/content/browser/web_contents/render_view_host_manager.cc
index 84694be..208829a 100644
--- a/content/browser/web_contents/render_view_host_manager.cc
+++ b/content/browser/web_contents/render_view_host_manager.cc
@@ -197,7 +197,8 @@
     // false (meaning the navigation should not proceed), but we'll ignore it
     // in this case because it took too long.
     if (pending_render_view_host_->are_navigations_suspended())
-      pending_render_view_host_->SetNavigationsSuspended(false);
+      pending_render_view_host_->SetNavigationsSuspended(
+          false, base::TimeTicks::Now());
   } else {
     // The request has been started and paused while we're waiting for the
     // unload handler to finish.  We'll pretend that it did, by notifying the
@@ -264,36 +265,6 @@
   }
 }
 
-void RenderViewHostManager::DidUpdateFrameTree(
-    RenderViewHost* render_view_host) {
-  // TODO(nasko): This used to be a CHECK_EQ, but it causes more crashes than
-  // expected. Changing to if statement and the root cause will be tracked by
-  // http://crbug.com/147613.
-  if (render_view_host != current_host())
-    return;
-
-  RenderViewHostImpl* render_view_host_impl = static_cast<RenderViewHostImpl*>(
-      render_view_host);
-
-  for (RenderViewHostMap::iterator iter = swapped_out_hosts_.begin();
-       iter != swapped_out_hosts_.end();
-       ++iter) {
-    DCHECK_NE(iter->second->GetSiteInstance(),
-        current_host()->GetSiteInstance());
-
-    // Send updates to the other swapped out RVHs, unless it's the pending RVH
-    // (which is in the process of navigating).
-    // TODO(nasko): Don't send updates across BrowsingInstances.
-    // See http://crbug.com/150855.
-    if (iter->second != pending_render_view_host_) {
-      iter->second->UpdateFrameTree(
-          render_view_host_impl->GetProcess()->GetID(),
-          render_view_host_impl->GetRoutingID(),
-          render_view_host_impl->frame_tree());
-    }
-  }
-}
-
 void RenderViewHostManager::RendererAbortedProvisionalLoad(
     RenderViewHost* render_view_host) {
   // We used to cancel the pending renderer here for cross-site downloads.
@@ -346,10 +317,7 @@
       // is ok to do nothing here.
       if (pending_render_view_host_ &&
           pending_render_view_host_->are_navigations_suspended()) {
-        pending_render_view_host_->SetNavigationsSuspended(false);
-        if (!proceed_time.is_null()) {
-          pending_render_view_host_->SetNavigationStartTime(proceed_time);
-        }
+        pending_render_view_host_->SetNavigationsSuspended(false, proceed_time);
       }
     } else {
       // Current page says to cancel.
@@ -407,9 +375,13 @@
 }
 
 bool RenderViewHostManager::ShouldTransitionCrossSite() {
+  // False in the single-process mode, as it makes RVHs to accumulate
+  // in swapped_out_hosts_.
   // True if we are using process-per-site-instance (default) or
   // process-per-site (kProcessPerSite).
-  return !CommandLine::ForCurrentProcess()->HasSwitch(switches::kProcessPerTab);
+  return
+      !CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess) &&
+      !CommandLine::ForCurrentProcess()->HasSwitch(switches::kProcessPerTab);
 }
 
 bool RenderViewHostManager::ShouldSwapProcessesForNavigation(
@@ -480,10 +452,14 @@
     SiteInstance* curr_instance) {
   // NOTE: This is only called when ShouldTransitionCrossSite is true.
 
-  const GURL& dest_url = entry.GetURL();
   NavigationControllerImpl& controller =
       delegate_->GetControllerForRenderManager();
   BrowserContext* browser_context = controller.GetBrowserContext();
+  const GURL& dest_url = GetContentClient()->browser()->
+      GetPossiblyPrivilegedURL(browser_context,
+                               entry.GetURL(),
+                               entry.is_renderer_initiated(),
+                               curr_instance);
 
   // If the entry has an instance already we should use it.
   if (entry.site_instance())
@@ -664,9 +640,6 @@
     if (success) {
       // Don't show the view until we get a DidNavigate from it.
       new_render_view_host->GetView()->Hide();
-
-      // TODO(nasko): Send a frame tree update when creating the RV
-      // once http://crbug.com/153701 is fixed.
     } else if (!swapped_out) {
       CancelPending();
     }
@@ -701,9 +674,9 @@
   // |pending_web_ui_|, or clear |web_ui_| if there is no pending WebUI, or
   // leave |web_ui_| as is if reusing it.
   DCHECK(!(pending_web_ui_.get() && pending_and_current_web_ui_.get()));
-  if (pending_web_ui_.get())
+  if (pending_web_ui_)
     web_ui_.reset(pending_web_ui_.release());
-  else if (!pending_and_current_web_ui_.get())
+  else if (!pending_and_current_web_ui_)
     web_ui_.reset();
 
   // It's possible for the pending_render_view_host_ to be NULL when we aren't
@@ -863,26 +836,35 @@
     render_view_host_->Send(
         new ViewMsg_Stop(render_view_host_->GetRoutingID()));
 
+    // We need to wait until the beforeunload handler has run, unless we are
+    // transferring an existing request (in which case it has already run).
     // Suspend the new render view (i.e., don't let it send the cross-site
     // Navigate message) until we hear back from the old renderer's
-    // onbeforeunload handler.  If the handler returns false, we'll have to
+    // beforeunload handler.  If the handler returns false, we'll have to
     // cancel the request.
     DCHECK(!pending_render_view_host_->are_navigations_suspended());
-    pending_render_view_host_->SetNavigationsSuspended(true);
+    bool is_transfer =
+        entry.transferred_global_request_id() != GlobalRequestID();
+    if (!is_transfer) {
+      pending_render_view_host_->SetNavigationsSuspended(true,
+                                                         base::TimeTicks());
+    }
 
     // Tell the CrossSiteRequestManager that this RVH has a pending cross-site
     // request, so that ResourceDispatcherHost will know to tell us to run the
-    // old page's onunload handler before it sends the response.
+    // old page's unload handler before it sends the response.
     pending_render_view_host_->SetHasPendingCrossSiteRequest(true, -1);
 
     // We now have a pending RVH.
     DCHECK(!cross_navigation_pending_);
     cross_navigation_pending_ = true;
 
-    // Tell the old render view to run its onbeforeunload handler, since it
+    // Unless we are transferring an existing request, we should now
+    // tell the old render view to run its beforeunload handler, since it
     // doesn't otherwise know that the cross-site request is happening.  This
     // will trigger a call to ShouldClosePage with the reply.
-    render_view_host_->FirePageBeforeUnload(true);
+    if (!is_transfer)
+      render_view_host_->FirePageBeforeUnload(true);
 
     return pending_render_view_host_;
   } else {
@@ -929,7 +911,7 @@
   // swap it back in and then canceled.  If so, make sure it gets swapped out
   // again.  If it's not on the swapped out list (e.g., aborting a pending
   // load), then it's safe to shut down.
-  if (IsSwappedOut(pending_render_view_host)) {
+  if (IsOnSwappedOutList(pending_render_view_host)) {
     // Any currently suspended navigations are no longer needed.
     pending_render_view_host->CancelSuspendedNavigations();
 
@@ -973,12 +955,16 @@
   }
 }
 
-bool RenderViewHostManager::IsSwappedOut(RenderViewHost* rvh) {
+bool RenderViewHostManager::IsOnSwappedOutList(RenderViewHost* rvh) const {
   if (!rvh->GetSiteInstance())
     return false;
 
-  return swapped_out_hosts_.find(rvh->GetSiteInstance()->GetId()) !=
-      swapped_out_hosts_.end();
+  RenderViewHostMap::const_iterator iter = swapped_out_hosts_.find(
+      rvh->GetSiteInstance()->GetId());
+  if (iter == swapped_out_hosts_.end())
+    return false;
+
+  return iter->second == rvh;
 }
 
 RenderViewHostImpl* RenderViewHostManager::GetSwappedOutRenderViewHost(
diff --git a/content/browser/web_contents/render_view_host_manager.h b/content/browser/web_contents/render_view_host_manager.h
index 3e31c08..d8b4001 100644
--- a/content/browser/web_contents/render_view_host_manager.h
+++ b/content/browser/web_contents/render_view_host_manager.h
@@ -171,9 +171,6 @@
   // Called when a renderer sets its opener to null.
   void DidDisownOpener(RenderViewHost* render_view_host);
 
-  // Called when a renderer has navigated and when its frame tree is updated.
-  void DidUpdateFrameTree(RenderViewHost* render_view_host);
-
   // Helper method to create a RenderViewHost.  If |swapped_out| is true, it
   // will be initially placed on the swapped out hosts list.  Otherwise, it
   // will be used for a pending cross-site navigation.
@@ -221,7 +218,7 @@
 
   // Returns whether the given RenderViewHost is on the list of swapped out
   // RenderViewHosts.
-  bool IsSwappedOut(RenderViewHost* rvh);
+  bool IsOnSwappedOutList(RenderViewHost* rvh) const;
 
   // Returns the swapped out RenderViewHost for the given SiteInstance, if any.
   RenderViewHostImpl* GetSwappedOutRenderViewHost(SiteInstance* instance);
@@ -326,6 +323,6 @@
   DISALLOW_COPY_AND_ASSIGN(RenderViewHostManager);
 };
 
-}  // namespace content      
+}  // namespace content
 
 #endif  // CONTENT_BROWSER_WEB_CONTENTS_RENDER_VIEW_HOST_MANAGER_H_
diff --git a/content/browser/web_contents/render_view_host_manager_unittest.cc b/content/browser/web_contents/render_view_host_manager_unittest.cc
index f9f3f09..c4fd94a 100644
--- a/content/browser/web_contents/render_view_host_manager_unittest.cc
+++ b/content/browser/web_contents/render_view_host_manager_unittest.cc
@@ -130,7 +130,7 @@
 // a regression test for bug 9364.
 TEST_F(RenderViewHostManagerTest, NewTabPageProcesses) {
   set_should_create_webui(true);
-  BrowserThreadImpl ui_thread(BrowserThread::UI, MessageLoop::current());
+  BrowserThreadImpl ui_thread(BrowserThread::UI, base::MessageLoop::current());
   const GURL kChromeUrl("chrome://foo");
   const GURL kDestUrl("http://www.google.com/");
 
@@ -195,7 +195,7 @@
 // for synchronous messages, which cannot be ignored without leaving the
 // renderer in a stuck state.  See http://crbug.com/93427.
 TEST_F(RenderViewHostManagerTest, FilterMessagesWhileSwappedOut) {
-  BrowserThreadImpl ui_thread(BrowserThread::UI, MessageLoop::current());
+  BrowserThreadImpl ui_thread(BrowserThread::UI, base::MessageLoop::current());
   const GURL kChromeURL("chrome://foo");
   const GURL kDestUrl("http://www.google.com/");
 
@@ -272,7 +272,7 @@
 // EnableViewSourceMode message is sent on every navigation regardless
 // RenderView is being newly created or reused.
 TEST_F(RenderViewHostManagerTest, AlwaysSendEnableViewSourceMode) {
-  BrowserThreadImpl ui_thread(BrowserThread::UI, MessageLoop::current());
+  BrowserThreadImpl ui_thread(BrowserThread::UI, base::MessageLoop::current());
   const GURL kChromeUrl("chrome://foo");
   const GURL kUrl("view-source:http://foo");
 
@@ -288,8 +288,9 @@
   controller().LoadURL(
       kUrl, Referrer(), PAGE_TRANSITION_TYPED, std::string());
   // Simulate response from RenderView for FirePageBeforeUnload.
+  base::TimeTicks now = base::TimeTicks::Now();
   test_rvh()->OnMessageReceived(ViewHostMsg_ShouldClose_ACK(
-      rvh()->GetRoutingID(), true, base::TimeTicks(), base::TimeTicks()));
+      rvh()->GetRoutingID(), true, now, now));
   ASSERT_TRUE(pending_rvh());  // New pending RenderViewHost will be created.
   RenderViewHost* last_rvh = pending_rvh();
   int32 new_id = contents()->GetMaxPageIDForSiteInstance(
@@ -590,7 +591,7 @@
 // Tests WebUI creation.
 TEST_F(RenderViewHostManagerTest, WebUI) {
   set_should_create_webui(true);
-  BrowserThreadImpl ui_thread(BrowserThread::UI, MessageLoop::current());
+  BrowserThreadImpl ui_thread(BrowserThread::UI, base::MessageLoop::current());
   SiteInstance* instance = SiteInstance::Create(browser_context());
 
   scoped_ptr<TestWebContents> web_contents(
@@ -814,20 +815,20 @@
                   rvh2->GetSiteInstance()));
 
   // Ensure rvh1 is placed on swapped out list of the current tab.
-  EXPECT_TRUE(manager->IsSwappedOut(rvh1));
+  EXPECT_TRUE(manager->IsOnSwappedOutList(rvh1));
   EXPECT_EQ(rvh1,
             manager->GetSwappedOutRenderViewHost(rvh1->GetSiteInstance()));
 
   // Ensure a swapped out RVH is created in the first opener tab.
   TestRenderViewHost* opener1_rvh = static_cast<TestRenderViewHost*>(
       opener1_manager->GetSwappedOutRenderViewHost(rvh2->GetSiteInstance()));
-  EXPECT_TRUE(opener1_manager->IsSwappedOut(opener1_rvh));
+  EXPECT_TRUE(opener1_manager->IsOnSwappedOutList(opener1_rvh));
   EXPECT_TRUE(opener1_rvh->is_swapped_out());
 
   // Ensure a swapped out RVH is created in the second opener tab.
   TestRenderViewHost* opener2_rvh = static_cast<TestRenderViewHost*>(
       opener2_manager->GetSwappedOutRenderViewHost(rvh2->GetSiteInstance()));
-  EXPECT_TRUE(opener2_manager->IsSwappedOut(opener2_rvh));
+  EXPECT_TRUE(opener2_manager->IsOnSwappedOutList(opener2_rvh));
   EXPECT_TRUE(opener2_rvh->is_swapped_out());
 
   // Navigate to a cross-BrowsingInstance URL.
@@ -879,7 +880,7 @@
   // Ensure a swapped out RVH is created in the first opener tab.
   TestRenderViewHost* opener1_rvh = static_cast<TestRenderViewHost*>(
       opener1_manager->GetSwappedOutRenderViewHost(rvh2->GetSiteInstance()));
-  EXPECT_TRUE(opener1_manager->IsSwappedOut(opener1_rvh));
+  EXPECT_TRUE(opener1_manager->IsOnSwappedOutList(opener1_rvh));
   EXPECT_TRUE(opener1_rvh->is_swapped_out());
 
   // Ensure the new RVH has WebUI bindings.
diff --git a/content/browser/web_contents/touch_editable_impl_aura.cc b/content/browser/web_contents/touch_editable_impl_aura.cc
new file mode 100644
index 0000000..d782b8c
--- /dev/null
+++ b/content/browser/web_contents/touch_editable_impl_aura.cc
@@ -0,0 +1,310 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/web_contents/touch_editable_impl_aura.h"
+
+#include "content/browser/renderer_host/render_widget_host_impl.h"
+#include "content/browser/renderer_host/render_widget_host_view_aura.h"
+#include "content/common/view_messages.h"
+#include "content/public/browser/render_widget_host.h"
+#include "grit/ui_strings.h"
+#include "ui/aura/client/activation_client.h"
+#include "ui/aura/client/screen_position_client.h"
+#include "ui/aura/root_window.h"
+#include "ui/aura/window.h"
+#include "ui/base/clipboard/clipboard.h"
+#include "ui/base/range/range.h"
+#include "ui/base/ui_base_switches_util.h"
+
+namespace content {
+
+////////////////////////////////////////////////////////////////////////////////
+// TouchEditableImplAura, public:
+
+TouchEditableImplAura::~TouchEditableImplAura() {
+  Cleanup();
+}
+
+// static
+TouchEditableImplAura* TouchEditableImplAura::Create() {
+  if (switches::IsTouchEditingEnabled())
+    return new TouchEditableImplAura();
+  return NULL;
+}
+
+void TouchEditableImplAura::AttachToView(RenderWidgetHostViewAura* view) {
+  if (rwhva_ == view)
+    return;
+
+  Cleanup();
+  if (!view)
+    return;
+
+  rwhva_ = view;
+  rwhva_->set_touch_editing_client(this);
+}
+
+void TouchEditableImplAura::UpdateEditingController() {
+  if (!rwhva_)
+    return;
+
+  // If touch editing handles were not visible, we bring them up only if
+  // there is non-zero selection on the page. And the current event is a
+  // gesture event (we dont want to show handles if the user is selecting
+  // using mouse or keyboard).
+  if (selection_gesture_in_process_ &&
+      selection_anchor_rect_ != selection_focus_rect_)
+    StartTouchEditing();
+
+  if (text_input_type_ != ui::TEXT_INPUT_TYPE_NONE ||
+      selection_anchor_rect_ != selection_focus_rect_) {
+    if (touch_selection_controller_)
+      touch_selection_controller_->SelectionChanged();
+  } else {
+    EndTouchEditing();
+  }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// TouchEditableImplAura, RenderWidgetHostViewAura::TouchEditingClient
+// implementation:
+
+void TouchEditableImplAura::StartTouchEditing() {
+  if (!touch_selection_controller_) {
+    touch_selection_controller_.reset(
+        ui::TouchSelectionController::create(this));
+  }
+  if (touch_selection_controller_)
+    touch_selection_controller_->SelectionChanged();
+}
+
+void TouchEditableImplAura::EndTouchEditing() {
+  if (touch_selection_controller_) {
+    if (touch_selection_controller_->IsHandleDragInProgress())
+      touch_selection_controller_->SelectionChanged();
+    else
+      touch_selection_controller_.reset();
+  }
+}
+
+void TouchEditableImplAura::OnSelectionOrCursorChanged(const gfx::Rect& anchor,
+                                                       const gfx::Rect& focus) {
+  selection_anchor_rect_ = anchor;
+  selection_focus_rect_ = focus;
+  UpdateEditingController();
+}
+
+void TouchEditableImplAura::OnTextInputTypeChanged(ui::TextInputType type) {
+  text_input_type_ = type;
+}
+
+bool TouchEditableImplAura::HandleInputEvent(const ui::Event* event) {
+  DCHECK(rwhva_);
+  if (event->IsTouchEvent())
+    return false;
+
+  if (!event->IsGestureEvent()) {
+    EndTouchEditing();
+    return false;
+  }
+
+  const ui::GestureEvent* gesture_event =
+      static_cast<const ui::GestureEvent*>(event);
+  switch (event->type()) {
+    case ui::ET_GESTURE_TAP:
+      if (gesture_event->details().tap_count() > 1)
+        selection_gesture_in_process_ = true;
+      // When the user taps, we want to show touch editing handles if user
+      // tapped on selected text.
+      if (selection_anchor_rect_ != selection_focus_rect_) {
+        // UnionRects only works for rects with non-zero width.
+        gfx::Rect anchor(selection_anchor_rect_.origin(),
+                         gfx::Size(1, selection_anchor_rect_.height()));
+        gfx::Rect focus(selection_focus_rect_.origin(),
+                        gfx::Size(1, selection_focus_rect_.height()));
+        gfx::Rect selection_rect = gfx::UnionRects(anchor, focus);
+        if (selection_rect.Contains(gesture_event->location())) {
+          StartTouchEditing();
+          return true;
+        }
+      }
+      break;
+    case ui::ET_GESTURE_LONG_PRESS:
+      selection_gesture_in_process_ = true;
+      break;
+    default:
+      break;
+  }
+  return false;
+}
+
+void TouchEditableImplAura::GestureEventAck(int gesture_event_type) {
+  DCHECK(rwhva_);
+  if (gesture_event_type == WebKit::WebInputEvent::GestureTap &&
+      text_input_type_ != ui::TEXT_INPUT_TYPE_NONE) {
+    StartTouchEditing();
+    if (touch_selection_controller_)
+      touch_selection_controller_->SelectionChanged();
+  }
+
+  if (gesture_event_type == WebKit::WebInputEvent::GestureLongPress ||
+      gesture_event_type == WebKit::WebInputEvent::GestureTap)
+    selection_gesture_in_process_ = false;
+}
+
+void TouchEditableImplAura::OnViewDestroyed() {
+  Cleanup();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// TouchEditableImplAura, ui::TouchEditable implementation:
+
+void TouchEditableImplAura::SelectRect(const gfx::Point& start,
+                                       const gfx::Point& end) {
+  if (!rwhva_)
+    return;
+
+  RenderWidgetHostImpl* host = RenderWidgetHostImpl::From(
+      rwhva_->GetRenderWidgetHost());
+  host->SelectRange(start, end);
+}
+
+void TouchEditableImplAura::MoveCaretTo(const gfx::Point& point) {
+  if (!rwhva_)
+    return;
+
+  RenderWidgetHostImpl* host = RenderWidgetHostImpl::From(
+      rwhva_->GetRenderWidgetHost());
+  host->MoveCaret(point);
+}
+
+void TouchEditableImplAura::GetSelectionEndPoints(gfx::Rect* p1,
+                                                  gfx::Rect* p2) {
+  *p1 = selection_anchor_rect_;
+  *p2 = selection_focus_rect_;
+}
+
+gfx::Rect TouchEditableImplAura::GetBounds() {
+  return rwhva_ ? rwhva_->GetNativeView()->bounds() : gfx::Rect();
+}
+
+gfx::NativeView TouchEditableImplAura::GetNativeView() {
+  return rwhva_ ? rwhva_->GetNativeView()->GetRootWindow() : NULL;
+}
+
+void TouchEditableImplAura::ConvertPointToScreen(gfx::Point* point) {
+  if (!rwhva_)
+    return;
+  aura::Window* window = rwhva_->GetNativeView();
+  aura::client::ScreenPositionClient* screen_position_client =
+      aura::client::GetScreenPositionClient(window->GetRootWindow());
+  if (screen_position_client)
+    screen_position_client->ConvertPointToScreen(window, point);
+}
+
+void TouchEditableImplAura::ConvertPointFromScreen(gfx::Point* point) {
+  if (!rwhva_)
+    return;
+  aura::Window* window = rwhva_->GetNativeView();
+  aura::client::ScreenPositionClient* screen_position_client =
+      aura::client::GetScreenPositionClient(window->GetRootWindow());
+  if (screen_position_client)
+    screen_position_client->ConvertPointFromScreen(window, point);
+}
+
+bool TouchEditableImplAura::DrawsHandles() {
+  return false;
+}
+
+void TouchEditableImplAura::OpenContextMenu(const gfx::Point anchor) {
+  if (!rwhva_)
+    return;
+  RenderWidgetHost* host = rwhva_->GetRenderWidgetHost();
+  host->Send(new ViewMsg_ShowContextMenu(host->GetRoutingID()));
+  EndTouchEditing();
+}
+
+bool TouchEditableImplAura::IsCommandIdChecked(int command_id) const {
+  NOTREACHED();
+  return false;
+}
+
+bool TouchEditableImplAura::IsCommandIdEnabled(int command_id) const {
+  if (!rwhva_)
+    return false;
+  bool editable = rwhva_->GetTextInputType() != ui::TEXT_INPUT_TYPE_NONE;
+  ui::Range selection_range;
+  rwhva_->GetSelectionRange(&selection_range);
+  bool has_selection = !selection_range.is_empty();
+  switch (command_id) {
+    case IDS_APP_CUT:
+      return editable && has_selection;
+    case IDS_APP_COPY:
+      return has_selection;
+    case IDS_APP_PASTE: {
+      string16 result;
+      ui::Clipboard::GetForCurrentThread()->ReadText(
+          ui::Clipboard::BUFFER_STANDARD, &result);
+      return editable && !result.empty();
+    }
+    case IDS_APP_DELETE:
+      return editable && has_selection;
+    case IDS_APP_SELECT_ALL:
+      return true;
+    default:
+      return false;
+  }
+}
+
+bool TouchEditableImplAura::GetAcceleratorForCommandId(
+    int command_id,
+    ui::Accelerator* accelerator) {
+  return false;
+}
+
+void TouchEditableImplAura::ExecuteCommand(int command_id, int event_flags) {
+  if (!rwhva_)
+    return;
+  RenderWidgetHost* host = rwhva_->GetRenderWidgetHost();
+  switch (command_id) {
+    case IDS_APP_CUT:
+      host->Cut();
+      break;
+    case IDS_APP_COPY:
+      host->Copy();
+      break;
+    case IDS_APP_PASTE:
+      host->Paste();
+      break;
+    case IDS_APP_DELETE:
+      host->Delete();
+      break;
+    case IDS_APP_SELECT_ALL:
+      host->SelectAll();
+      break;
+    default:
+      NOTREACHED();
+      break;
+  }
+  EndTouchEditing();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// TouchEditableImplAura, private:
+
+TouchEditableImplAura::TouchEditableImplAura()
+    : text_input_type_(ui::TEXT_INPUT_TYPE_NONE),
+      rwhva_(NULL),
+      selection_gesture_in_process_(false) {
+}
+
+void TouchEditableImplAura::Cleanup() {
+  if (rwhva_) {
+    rwhva_->set_touch_editing_client(NULL);
+    rwhva_ = NULL;
+  }
+  touch_selection_controller_.reset();
+}
+
+}  // namespace content
diff --git a/content/browser/web_contents/touch_editable_impl_aura.h b/content/browser/web_contents/touch_editable_impl_aura.h
new file mode 100644
index 0000000..f29dfd3
--- /dev/null
+++ b/content/browser/web_contents/touch_editable_impl_aura.h
@@ -0,0 +1,95 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_WEB_CONTENTS_TOUCH_EDITABLE_IMPL_AURA_H_
+#define CONTENT_BROWSER_WEB_CONTENTS_TOUCH_EDITABLE_IMPL_AURA_H_
+
+#include <deque>
+#include <map>
+
+#include "content/browser/renderer_host/render_widget_host_view_aura.h"
+#include "ui/aura/window_observer.h"
+#include "ui/base/touch/touch_editing_controller.h"
+#include "ui/gfx/native_widget_types.h"
+#include "ui/gfx/point.h"
+#include "ui/gfx/rect.h"
+
+namespace ui {
+class Accelerator;
+}
+
+namespace content {
+class TouchEditableImplAuraTest;
+
+// Aura specific implementation of ui::TouchEditable for a RenderWidgetHostView.
+class CONTENT_EXPORT TouchEditableImplAura
+    : public ui::TouchEditable,
+      public NON_EXPORTED_BASE(RenderWidgetHostViewAura::TouchEditingClient) {
+ public:
+  virtual ~TouchEditableImplAura();
+
+  static TouchEditableImplAura* Create();
+
+  void AttachToView(RenderWidgetHostViewAura* view);
+
+  // Updates the |touch_selection_controller_| or ends touch editing session
+  // depending on the current selection and cursor state.
+  void UpdateEditingController();
+
+  // Overridden from RenderWidgetHostViewAura::TouchEditingClient.
+  virtual void StartTouchEditing() OVERRIDE;
+  virtual void EndTouchEditing() OVERRIDE;
+  virtual void OnSelectionOrCursorChanged(const gfx::Rect& anchor,
+                                          const gfx::Rect& focus) OVERRIDE;
+  virtual void OnTextInputTypeChanged(ui::TextInputType type) OVERRIDE;
+  virtual bool HandleInputEvent(const ui::Event* event) OVERRIDE;
+  virtual void GestureEventAck(int gesture_event_type) OVERRIDE;
+  virtual void OnViewDestroyed() OVERRIDE;
+
+  // Overridden from ui::TouchEditable:
+  virtual void SelectRect(const gfx::Point& start,
+                          const gfx::Point& end) OVERRIDE;
+  virtual void MoveCaretTo(const gfx::Point& point) OVERRIDE;
+  virtual void GetSelectionEndPoints(gfx::Rect* p1, gfx::Rect* p2) OVERRIDE;
+  virtual gfx::Rect GetBounds() OVERRIDE;
+  virtual gfx::NativeView GetNativeView() OVERRIDE;
+  virtual void ConvertPointToScreen(gfx::Point* point) OVERRIDE;
+  virtual void ConvertPointFromScreen(gfx::Point* point) OVERRIDE;
+  virtual bool DrawsHandles() OVERRIDE;
+  virtual void OpenContextMenu(const gfx::Point anchor) OVERRIDE;
+  virtual bool IsCommandIdChecked(int command_id) const OVERRIDE;
+  virtual bool IsCommandIdEnabled(int command_id) const OVERRIDE;
+  virtual bool GetAcceleratorForCommandId(
+      int command_id,
+      ui::Accelerator* accelerator) OVERRIDE;
+  virtual void ExecuteCommand(int command_id, int event_flags) OVERRIDE;
+
+ protected:
+  TouchEditableImplAura();
+
+ private:
+  friend class TouchEditableImplAuraTest;
+
+  void Cleanup();
+
+  // Rectangles for the selection anchor and focus.
+  gfx::Rect selection_anchor_rect_;
+  gfx::Rect selection_focus_rect_;
+
+  // The current text input type.
+  ui::TextInputType text_input_type_;
+
+  RenderWidgetHostViewAura* rwhva_;
+  scoped_ptr<ui::TouchSelectionController> touch_selection_controller_;
+
+  // True if |rwhva_| is currently handling a gesture that could result in a
+  // change in selection.
+  bool selection_gesture_in_process_;
+
+  DISALLOW_COPY_AND_ASSIGN(TouchEditableImplAura);
+};
+
+}  // namespace content
+
+#endif  // CONTENT_BROWSER_WEB_CONTENTS_TOUCH_EDITABLE_IMPL_AURA_H_
diff --git a/content/browser/web_contents/touch_editable_impl_aura_browsertest.cc b/content/browser/web_contents/touch_editable_impl_aura_browsertest.cc
new file mode 100644
index 0000000..12fa687
--- /dev/null
+++ b/content/browser/web_contents/touch_editable_impl_aura_browsertest.cc
@@ -0,0 +1,285 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/web_contents/touch_editable_impl_aura.h"
+
+#include "base/command_line.h"
+#include "base/run_loop.h"
+#include "base/test/test_timeouts.h"
+#include "base/utf_string_conversions.h"
+#include "base/values.h"
+#include "content/browser/renderer_host/render_view_host_impl.h"
+#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/browser/web_contents/web_contents_view_aura.h"
+#include "content/public/browser/web_contents_view.h"
+#include "content/public/common/content_switches.h"
+#include "content/public/test/browser_test_utils.h"
+#include "content/public/test/test_utils.h"
+#include "content/shell/shell.h"
+#include "content/test/content_browser_test.h"
+#include "content/test/content_browser_test_utils.h"
+#include "ui/aura/root_window.h"
+#include "ui/aura/test/event_generator.h"
+#include "ui/aura/window.h"
+#include "ui/base/events/event_utils.h"
+#include "ui/base/ui_base_switches.h"
+#include "ui/compositor/scoped_animation_duration_scale_mode.h"
+
+namespace content {
+
+class TestTouchEditableImplAura : public TouchEditableImplAura {
+ public:
+  TestTouchEditableImplAura()
+      : selection_changed_callback_arrived_(false),
+        waiting_for_selection_changed_callback_(false),
+        gesture_ack_callback_arrived_(false),
+        waiting_for_gesture_ack_callback_(false) {}
+
+  void Reset() {
+    selection_changed_callback_arrived_ = false;
+    waiting_for_selection_changed_callback_ = false;
+    gesture_ack_callback_arrived_ = false;
+    waiting_for_gesture_ack_callback_ = false;
+  }
+
+  void OnSelectionOrCursorChanged(const gfx::Rect& anchor,
+                                  const gfx::Rect& focus) OVERRIDE {
+    selection_changed_callback_arrived_ = true;
+    TouchEditableImplAura::OnSelectionOrCursorChanged(anchor, focus);
+    if (waiting_for_selection_changed_callback_)
+      selection_changed_wait_run_loop_->Quit();
+  }
+
+  void GestureEventAck(int gesture_event_type) OVERRIDE {
+    gesture_ack_callback_arrived_ = true;
+    TouchEditableImplAura::GestureEventAck(gesture_event_type);
+    if (waiting_for_gesture_ack_callback_)
+      gesture_ack_wait_run_loop_->Quit();
+  }
+
+  void WaitForSelectionChangeCallback() {
+    if (selection_changed_callback_arrived_)
+      return;
+    waiting_for_selection_changed_callback_ = true;
+    selection_changed_wait_run_loop_.reset(new base::RunLoop());
+    selection_changed_wait_run_loop_->Run();
+  }
+
+  void WaitForGestureAck() {
+    if (gesture_ack_callback_arrived_)
+      return;
+    waiting_for_gesture_ack_callback_ = true;
+    gesture_ack_wait_run_loop_.reset(new base::RunLoop());
+    gesture_ack_wait_run_loop_->Run();
+  }
+
+ protected:
+  virtual ~TestTouchEditableImplAura() {}
+
+ private:
+  bool selection_changed_callback_arrived_;
+  bool waiting_for_selection_changed_callback_;
+  bool gesture_ack_callback_arrived_;
+  bool waiting_for_gesture_ack_callback_;
+  scoped_ptr<base::RunLoop> selection_changed_wait_run_loop_;
+  scoped_ptr<base::RunLoop> gesture_ack_wait_run_loop_;
+
+  DISALLOW_COPY_AND_ASSIGN(TestTouchEditableImplAura);
+};
+
+class TouchEditableImplAuraTest : public ContentBrowserTest {
+ public:
+  TouchEditableImplAuraTest() {}
+
+  virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
+    command_line->AppendSwitch(switches::kEnableTouchEditing);
+  }
+
+  // Executes the javascript synchronously and makes sure the returned value is
+  // freed properly.
+  void ExecuteSyncJSFunction(RenderViewHost* rvh, const std::string& jscript) {
+    scoped_ptr<base::Value> value =
+        content::ExecuteScriptAndGetValue(rvh, jscript);
+  }
+
+  // Starts the test server and navigates to the given url. Sets a large enough
+  // size to the root window.  Returns after the navigation to the url is
+  // complete.
+  void StartTestWithPage(const std::string& url) {
+    ASSERT_TRUE(test_server()->Start());
+    GURL test_url(test_server()->GetURL(url));
+    NavigateToURL(shell(), test_url);
+    aura::Window* content =
+        shell()->web_contents()->GetView()->GetContentNativeView();
+    content->GetRootWindow()->SetHostSize(gfx::Size(800, 600));
+  }
+
+  void TestTouchSelectionOriginatingFromWebpage() {
+    ASSERT_NO_FATAL_FAILURE(
+        StartTestWithPage("files/touch_selection.html"));
+    WebContentsImpl* web_contents =
+        static_cast<WebContentsImpl*>(shell()->web_contents());
+    RenderViewHostImpl* view_host = static_cast<RenderViewHostImpl*>(
+        web_contents->GetRenderViewHost());
+    WebContentsViewAura* view_aura = static_cast<WebContentsViewAura*>(
+        web_contents->GetView());
+    TestTouchEditableImplAura* touch_editable = new TestTouchEditableImplAura;
+    view_aura->SetTouchEditableForTest(touch_editable);
+    RenderWidgetHostViewAura* rwhva = static_cast<RenderWidgetHostViewAura*>(
+        web_contents->GetRenderWidgetHostView());
+    aura::Window* content = web_contents->GetView()->GetContentNativeView();
+    aura::test::EventGenerator generator(content->GetRootWindow(), content);
+    gfx::Rect bounds = content->GetBoundsInRootWindow();
+
+    touch_editable->Reset();
+    ExecuteSyncJSFunction(view_host, "select_all_text()");
+    touch_editable->WaitForSelectionChangeCallback();
+
+    // Tap inside selection to bring up selection handles.
+    generator.GestureTapAt(gfx::Point(bounds.x() + 10, bounds.y() + 10));
+    EXPECT_EQ(touch_editable->rwhva_, rwhva);
+
+    scoped_ptr<base::Value> value =
+        content::ExecuteScriptAndGetValue(view_host, "get_selection()");
+    std::string selection;
+    value->GetAsString(&selection);
+
+    // Check if selection handles are showing.
+    EXPECT_TRUE(touch_editable->touch_selection_controller_.get());
+    EXPECT_STREQ("Some text we can select", selection.c_str());
+
+    // Lets move the handles a bit to modify the selection
+    touch_editable->Reset();
+    generator.GestureScrollSequence(
+        gfx::Point(10, 37),
+        gfx::Point(30, 37),
+        base::TimeDelta::FromMilliseconds(20),
+        1);
+    EXPECT_TRUE(touch_editable->touch_selection_controller_.get());
+    value = content::ExecuteScriptAndGetValue(view_host, "get_selection()");
+    value->GetAsString(&selection);
+
+    // It is hard to tell what exactly the selection would be now. But it would
+    // definitely be less than whatever was selected before.
+    EXPECT_GT(std::strlen("Some text we can select"), selection.size());
+  }
+
+  void TestTouchSelectionOnLongPress() {
+    ASSERT_NO_FATAL_FAILURE(
+        StartTestWithPage("files/touch_selection.html"));
+    WebContentsImpl* web_contents =
+        static_cast<WebContentsImpl*>(shell()->web_contents());
+    RenderViewHostImpl* view_host = static_cast<RenderViewHostImpl*>(
+        web_contents->GetRenderViewHost());
+    WebContentsViewAura* view_aura = static_cast<WebContentsViewAura*>(
+        web_contents->GetView());
+    TestTouchEditableImplAura* touch_editable = new TestTouchEditableImplAura;
+    view_aura->SetTouchEditableForTest(touch_editable);
+    RenderWidgetHostViewAura* rwhva = static_cast<RenderWidgetHostViewAura*>(
+        web_contents->GetRenderWidgetHostView());
+    aura::Window* content = web_contents->GetView()->GetContentNativeView();
+    aura::test::EventGenerator generator(content->GetRootWindow(), content);
+    gfx::Rect bounds = content->GetBoundsInRootWindow();
+    EXPECT_EQ(touch_editable->rwhva_, rwhva);
+
+    // Long press to select word.
+    ui::GestureEvent long_press(ui::ET_GESTURE_LONG_PRESS,
+                                10,
+                                10,
+                                0,
+                                ui::EventTimeForNow(),
+                                ui::GestureEventDetails(
+                                    ui::ET_GESTURE_LONG_PRESS, 0, 0),
+                                1);
+    touch_editable->Reset();
+    rwhva->OnGestureEvent(&long_press);
+    touch_editable->WaitForSelectionChangeCallback();
+
+    // Check if selection handles are showing.
+    ui::TouchSelectionController* controller =
+        touch_editable->touch_selection_controller_.get();
+    EXPECT_TRUE(controller);
+
+    scoped_ptr<base::Value> value =
+        content::ExecuteScriptAndGetValue(view_host, "get_selection()");
+    std::string selection;
+    value->GetAsString(&selection);
+    EXPECT_STREQ("Some", selection.c_str());
+  }
+
+  void TestTouchCursorInTextfield() {
+    ASSERT_NO_FATAL_FAILURE(
+        StartTestWithPage("files/touch_selection.html"));
+    WebContentsImpl* web_contents =
+        static_cast<WebContentsImpl*>(shell()->web_contents());
+    RenderViewHostImpl* view_host = static_cast<RenderViewHostImpl*>(
+        web_contents->GetRenderViewHost());
+    WebContentsViewAura* view_aura = static_cast<WebContentsViewAura*>(
+        web_contents->GetView());
+    TestTouchEditableImplAura* touch_editable = new TestTouchEditableImplAura;
+    view_aura->SetTouchEditableForTest(touch_editable);
+    RenderWidgetHostViewAura* rwhva = static_cast<RenderWidgetHostViewAura*>(
+        web_contents->GetRenderWidgetHostView());
+    aura::Window* content = web_contents->GetView()->GetContentNativeView();
+    aura::test::EventGenerator generator(content->GetRootWindow(), content);
+    gfx::Rect bounds = content->GetBoundsInRootWindow();
+    EXPECT_EQ(touch_editable->rwhva_, rwhva);
+    ExecuteSyncJSFunction(view_host, "focus_textfield()");
+
+    // Tap textfield
+    touch_editable->Reset();
+    generator.GestureTapAt(gfx::Point(bounds.x() + 50, bounds.y() + 40));
+    touch_editable->WaitForGestureAck();  // Wait for Tap Down Ack
+    touch_editable->Reset();
+    touch_editable->WaitForGestureAck();  // Wait for Tap Ack.
+
+    // Check if cursor handle is showing.
+    ui::TouchSelectionController* controller =
+        touch_editable->touch_selection_controller_.get();
+    EXPECT_NE(ui::TEXT_INPUT_TYPE_NONE, touch_editable->text_input_type_);
+    EXPECT_TRUE(controller);
+
+    scoped_ptr<base::Value> value =
+        content::ExecuteScriptAndGetValue(view_host, "get_cursor_position()");
+    int cursor_pos = -1;
+    value->GetAsInteger(&cursor_pos);
+    EXPECT_NE(-1, cursor_pos);
+
+    // Move the cursor handle.
+    generator.GestureScrollSequence(
+        gfx::Point(50, 59),
+        gfx::Point(10, 59),
+        base::TimeDelta::FromMilliseconds(20),
+        1);
+    EXPECT_TRUE(touch_editable->touch_selection_controller_.get());
+    value = content::ExecuteScriptAndGetValue(
+        view_host, "get_cursor_position()");
+    int new_cursor_pos = -1;
+    value->GetAsInteger(&new_cursor_pos);
+    EXPECT_NE(-1, new_cursor_pos);
+    // Cursor should have moved.
+    EXPECT_NE(new_cursor_pos, cursor_pos);
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(TouchEditableImplAuraTest);
+};
+
+IN_PROC_BROWSER_TEST_F(TouchEditableImplAuraTest,
+                       TouchSelectionOriginatingFromWebpageTest) {
+  TestTouchSelectionOriginatingFromWebpage();
+}
+
+IN_PROC_BROWSER_TEST_F(TouchEditableImplAuraTest,
+                       TouchSelectionOnLongPressTest) {
+  TestTouchSelectionOnLongPress();
+}
+
+// TODO(miu): Disabled test due to flakiness.  http://crbug.com/235991
+IN_PROC_BROWSER_TEST_F(TouchEditableImplAuraTest,
+                       DISABLED_TouchCursorInTextfieldTest) {
+  TestTouchCursorInTextfield();
+}
+
+}  // namespace content
diff --git a/content/browser/web_contents/web_contents_drag_win.cc b/content/browser/web_contents/web_contents_drag_win.cc
index 0b7fac4..8174c97 100644
--- a/content/browser/web_contents/web_contents_drag_win.cc
+++ b/content/browser/web_contents/web_contents_drag_win.cc
@@ -46,6 +46,8 @@
 namespace content {
 namespace {
 
+bool run_do_drag_drop = true;
+
 HHOOK msg_hook = NULL;
 DWORD drag_out_thread_id = 0;
 bool mouse_up_received = false;
@@ -176,7 +178,7 @@
   DCHECK(!drag_drop_thread_.get());
   drag_drop_thread_.reset(new DragDropThread(this));
   base::Thread::Options options;
-  options.message_loop_type = MessageLoop::TYPE_UI;
+  options.message_loop_type = base::MessageLoop::TYPE_UI;
   if (drag_drop_thread_->StartWithOptions(options)) {
     drag_drop_thread_->message_loop()->PostTask(
         FROM_HERE,
@@ -353,18 +355,22 @@
 
   // We need to enable recursive tasks on the message loop so we can get
   // updates while in the system DoDragDrop loop.
-  DWORD effect;
-  {
+  DWORD effect = DROPEFFECT_NONE;
+  if (run_do_drag_drop) {
     // Keep a reference count such that |drag_source_| will not get deleted
     // if the contents view window is gone in the nested message loop invoked
     // from DoDragDrop.
-    scoped_refptr<WebDragSource> retain_this(drag_source_);
+    scoped_refptr<WebDragSource> retain_source(drag_source_);
+    retain_source->set_data(&data);
+    data.SetInDragLoop(true);
 
-    MessageLoop::ScopedNestableTaskAllower allow(MessageLoop::current());
+    base::MessageLoop::ScopedNestableTaskAllower allow(
+        base::MessageLoop::current());
     DoDragDrop(ui::OSExchangeDataProviderWin::GetIDataObject(data),
                drag_source_,
                WebDragOpMaskToWinDragOpMask(ops),
                &effect);
+    retain_source->set_data(NULL);
   }
 
   // Bail out immediately if the contents view window is gone.
@@ -430,4 +436,9 @@
       base::Bind(&WebContentsDragWin::CloseThread, this));
 }
 
+// static
+void WebContentsDragWin::DisableDragDropForTesting() {
+  run_do_drag_drop = false;
+}
+
 }  // namespace content
diff --git a/content/browser/web_contents/web_contents_drag_win.h b/content/browser/web_contents/web_contents_drag_win.h
index 12f07cc..b7ffb30 100644
--- a/content/browser/web_contents/web_contents_drag_win.h
+++ b/content/browser/web_contents/web_contents_drag_win.h
@@ -56,6 +56,9 @@
   virtual void OnWaitForData();
   virtual void OnDataObjectDisposed();
 
+  // Don't invoke OLE DoDragDrop during tests.
+  static void DisableDragDropForTesting();
+
  private:
   // Called on either UI thread or drag-and-drop thread.
   void PrepareDragForDownload(const WebDropData& drop_data,
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
index 12c4c07..43ec8e5 100644
--- a/content/browser/web_contents/web_contents_impl.cc
+++ b/content/browser/web_contents/web_contents_impl.cc
@@ -42,7 +42,7 @@
 #include "content/browser/webui/web_ui_impl.h"
 #include "content/common/browser_plugin/browser_plugin_constants.h"
 #include "content/common/browser_plugin/browser_plugin_messages.h"
-#include "content/common/icon_messages.h"
+#include "content/common/image_messages.h"
 #include "content/common/ssl_status_serialization.h"
 #include "content/common/view_messages.h"
 #include "content/port/browser/render_view_host_delegate_view.h"
@@ -86,6 +86,7 @@
 #include "webkit/glue/webpreferences.h"
 
 #if defined(OS_ANDROID)
+#include "content/public/browser/android/content_view_core.h"
 #include "content/browser/android/date_time_chooser_android.h"
 #endif
 
@@ -140,8 +141,6 @@
 //   the user goes back.  The process only stays live if another tab is using
 //   it, but if so, the existing frame relationships will be maintained.
 
-using webkit_glue::WebPreferences;
-
 namespace content {
 namespace {
 
@@ -157,13 +156,13 @@
                          const GURL& url,
                          bool is_favicon,
                          int image_size) {
-  static int g_next_favicon_download_id = 0;
-  rvh->Send(new IconMsg_DownloadFavicon(rvh->GetRoutingID(),
-                                        ++g_next_favicon_download_id,
-                                        url,
-                                        is_favicon,
-                                        image_size));
-  return g_next_favicon_download_id;
+  static int g_next_image_download_id = 0;
+  rvh->Send(new ImageMsg_DownloadImage(rvh->GetRoutingID(),
+                                       ++g_next_image_download_id,
+                                       url,
+                                       is_favicon,
+                                       image_size));
+  return g_next_image_download_id;
 }
 
 ViewMsg_Navigate_Type::Value GetNavigationType(
@@ -198,9 +197,20 @@
                         NavigationController::ReloadType reload_type,
                         ViewMsg_Navigate_Params* params) {
   params->page_id = entry.GetPageID();
-  params->pending_history_list_offset = controller.GetIndexOfEntry(&entry);
-  params->current_history_list_offset = controller.GetLastCommittedEntryIndex();
-  params->current_history_list_length = controller.GetEntryCount();
+  params->should_clear_history_list = entry.should_clear_history_list();
+  if (entry.should_clear_history_list()) {
+    // Set the history list related parameters to the same values a
+    // NavigationController would return before its first navigation. This will
+    // fully clear the RenderView's view of the session history.
+    params->pending_history_list_offset = -1;
+    params->current_history_list_offset = -1;
+    params->current_history_list_length = 0;
+  } else {
+    params->pending_history_list_offset = controller.GetIndexOfEntry(&entry);
+    params->current_history_list_offset =
+        controller.GetLastCommittedEntryIndex();
+    params->current_history_list_length = controller.GetEntryCount();
+  }
   if (!entry.GetBaseURLForDataURL().is_empty()) {
     params->base_url_for_data_url = entry.GetBaseURLForDataURL();
     params->history_url_for_data_url = entry.GetVirtualURL();
@@ -280,10 +290,13 @@
     BrowserContext* browser_context,
     WebContentsImpl* opener)
     : delegate_(NULL),
-      ALLOW_THIS_IN_INITIALIZER_LIST(controller_(this, browser_context)),
+      controller_(this, browser_context),
       render_view_host_delegate_view_(NULL),
       opener_(opener),
-      ALLOW_THIS_IN_INITIALIZER_LIST(render_manager_(this, this, this)),
+#if defined(OS_WIN) && defined(USE_AURA)
+      accessible_parent_(NULL),
+#endif
+      render_manager_(this, this, this),
       is_loading_(false),
       crashed_status_(base::TERMINATION_STATUS_STILL_RUNNING),
       crashed_error_code_(0),
@@ -399,7 +412,6 @@
 
   const CommandLine& command_line = *CommandLine::ForCurrentProcess();
 
-  prefs.developer_extras_enabled = true;
   prefs.javascript_enabled =
       !command_line.HasSwitch(switches::kDisableJavaScript);
   prefs.web_security_enabled =
@@ -409,8 +421,6 @@
   prefs.java_enabled =
       !command_line.HasSwitch(switches::kDisableJava);
 
-  prefs.uses_page_cache =
-      command_line.HasSwitch(switches::kEnableFastback);
   prefs.remote_fonts_enabled =
       !command_line.HasSwitch(switches::kDisableRemoteFonts);
   prefs.xss_auditor_enabled =
@@ -501,8 +511,18 @@
       command_line.HasSwitch(switches::kEnableExperimentalWebKitFeatures);
   prefs.css_grid_layout_enabled =
       command_line.HasSwitch(switches::kEnableExperimentalWebKitFeatures);
+  prefs.lazy_layout_enabled =
+      command_line.HasSwitch(switches::kEnableExperimentalWebKitFeatures);
+
+  // TODO(abarth, eseidel): Enable threaded_html_parser by default on Android
+  // once crbug 230542 is resolved.
+#if defined(OS_ANDROID)
+  prefs.threaded_html_parser = false;
+#else
   prefs.threaded_html_parser =
       !command_line.HasSwitch(switches::kDisableThreadedHTMLParser);
+#endif
+
 #if defined(OS_ANDROID)
   prefs.user_gesture_required_for_media_playback = !command_line.HasSwitch(
       switches::kDisableGestureRequirementForMediaPlayback);
@@ -546,42 +566,8 @@
   prefs.visual_word_movement_enabled =
       command_line.HasSwitch(switches::kEnableVisualWordMovement);
 
-  {  // Certain GPU features might have been blacklisted.
-    GpuDataManagerImpl* gpu_data_manager = GpuDataManagerImpl::GetInstance();
-    DCHECK(gpu_data_manager);
-    uint32 blacklist_type = gpu_data_manager->GetBlacklistedFeatures();
-    if (blacklist_type & GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING)
-      prefs.accelerated_compositing_enabled = false;
-    if (blacklist_type & GPU_FEATURE_TYPE_WEBGL)
-      prefs.experimental_webgl_enabled = false;
-    if (blacklist_type & GPU_FEATURE_TYPE_FLASH3D)
-      prefs.flash_3d_enabled = false;
-    if (blacklist_type & GPU_FEATURE_TYPE_FLASH_STAGE3D) {
-      prefs.flash_stage3d_enabled = false;
-      prefs.flash_stage3d_baseline_enabled = false;
-    }
-    if (blacklist_type & GPU_FEATURE_TYPE_FLASH_STAGE3D_BASELINE)
-      prefs.flash_stage3d_baseline_enabled = false;
-    if (blacklist_type & GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS)
-      prefs.accelerated_2d_canvas_enabled = false;
-    if (blacklist_type & GPU_FEATURE_TYPE_MULTISAMPLING)
-      prefs.gl_multisampling_enabled = false;
-    if (blacklist_type & GPU_FEATURE_TYPE_3D_CSS) {
-      prefs.accelerated_compositing_for_3d_transforms_enabled = false;
-      prefs.accelerated_compositing_for_animation_enabled = false;
-    }
-    if (blacklist_type & GPU_FEATURE_TYPE_ACCELERATED_VIDEO)
-      prefs.accelerated_compositing_for_video_enabled = false;
-
-    // Accelerated video and animation are slower than regular when using a
-    // software 3d rasterizer. 3D CSS may also be too slow to be worthwhile.
-    if (gpu_data_manager->ShouldUseSoftwareRendering()) {
-      prefs.accelerated_compositing_for_video_enabled = false;
-      prefs.accelerated_compositing_for_animation_enabled = false;
-      prefs.accelerated_compositing_for_3d_transforms_enabled = false;
-      prefs.accelerated_compositing_for_plugins_enabled = false;
-    }
-  }
+  // Certain GPU features might have been blacklisted.
+  GpuDataManagerImpl::GetInstance()->UpdateRendererWebPrefs(&prefs);
 
   if (ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
           rvh->GetProcess()->GetID())) {
@@ -623,6 +609,9 @@
       command_line.HasSwitch(switches::kEnableDeferredImageDecoding) ||
       cc::switches::IsImplSidePaintingEnabled();
 
+  prefs.spatial_navigation_enabled = command_line.HasSwitch(
+      switches::kEnableSpatialNavigation);
+
   GetContentClient()->browser()->OverrideWebkitPrefs(rvh, url, &prefs);
 
   // Disable compositing in guests until we have compositing path implemented
@@ -695,8 +684,8 @@
                                 OnBrowserPluginMessage(message))
     IPC_MESSAGE_HANDLER_GENERIC(BrowserPluginHostMsg_Attach,
                                 OnBrowserPluginMessage(message))
-    IPC_MESSAGE_HANDLER(IconHostMsg_DidDownloadFavicon, OnDidDownloadFavicon)
-    IPC_MESSAGE_HANDLER(IconHostMsg_UpdateFaviconURL, OnUpdateFaviconURL)
+    IPC_MESSAGE_HANDLER(ImageHostMsg_DidDownloadImage, OnDidDownloadImage)
+    IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateFaviconURL, OnUpdateFaviconURL)
 #if defined(OS_ANDROID)
     IPC_MESSAGE_HANDLER(ViewHostMsg_FindMatchRects_Reply,
                         OnFindMatchRectsReply)
@@ -869,6 +858,13 @@
   return renderer_preferences_.user_agent_override;
 }
 
+#if defined(OS_WIN) && defined(USE_AURA)
+void WebContentsImpl::SetParentNativeViewAccessible(
+gfx::NativeViewAccessible accessible_parent) {
+  accessible_parent_ = accessible_parent;
+}
+#endif
+
 const string16& WebContentsImpl::GetTitle() const {
   // Transient entries take precedence. They are used for interstitial pages
   // that are shown on top of existing pages.
@@ -1141,13 +1137,13 @@
 
   view_.reset(GetContentClient()->browser()->
       OverrideCreateWebContentsView(this, &render_view_host_delegate_view_));
-  if (view_.get()) {
+  if (view_) {
     CHECK(render_view_host_delegate_view_);
   } else {
     WebContentsViewDelegate* delegate =
         GetContentClient()->browser()->GetWebContentsViewDelegate(this);
 
-    if (browser_plugin_guest_.get()) {
+    if (browser_plugin_guest_) {
       WebContentsViewPort* platform_view = CreateWebContentsView(
           this, delegate, &render_view_host_delegate_view_);
 
@@ -1267,16 +1263,30 @@
 
 bool WebContentsImpl::PreHandleWheelEvent(
     const WebKit::WebMouseWheelEvent& event) {
+#if !defined(OS_MACOSX)
+  // On platforms other than Mac, control+mousewheel changes zoom. On Mac, this
+  // isn't done for two reasons:
+  //   -the OS already has a gesture to do this through pinch-zoom
+  //   -if a user starts an inertial scroll, let's go, and presses control
+  //      (i.e. control+tab) then the OS's buffered scroll events will come in
+  //      with control key set which isn't what the user wants
   if (delegate_ &&
       event.wheelTicksY &&
       (event.modifiers & WebKit::WebInputEvent::ControlKey)) {
     delegate_->ContentsZoomChange(event.wheelTicksY > 0);
     return true;
   }
+#endif
 
   return false;
 }
 
+#if defined(OS_WIN) && defined(USE_AURA)
+gfx::NativeViewAccessible WebContentsImpl::GetParentNativeViewAccessible() {
+  return accessible_parent_;
+}
+#endif
+
 void WebContentsImpl::HandleMouseDown() {
   if (delegate_)
     delegate_->HandleMouseDown();
@@ -1383,20 +1393,21 @@
     WebContentsImpl* new_contents_impl =
         static_cast<WebContentsImpl*>(new_contents);
     new_contents_impl->browser_plugin_guest_.reset(
-        BrowserPluginGuest::Create(instance_id, new_contents_impl));
+        BrowserPluginGuest::CreateWithOpener(instance_id, new_contents_impl,
+            GetBrowserPluginGuest(), !!new_contents_impl->opener()));
   }
   new_contents->Init(create_params);
 
   // Save the window for later if we're not suppressing the opener (since it
-  // will be shown immediately) and if it's not a guest (since we separately
-  // track when to show guests).
-  if (!params.opener_suppressed && !is_guest) {
-    WebContentsViewPort* new_view = new_contents->view_.get();
+  // will be shown immediately).
+  if (!params.opener_suppressed) {
+    if (!is_guest) {
+      WebContentsViewPort* new_view = new_contents->view_.get();
 
-    // TODO(brettw): It seems bogus that we have to call this function on the
-    // newly created object and give it one of its own member variables.
-    new_view->CreateViewForWidget(new_contents->GetRenderViewHost());
-
+      // TODO(brettw): It seems bogus that we have to call this function on the
+      // newly created object and give it one of its own member variables.
+      new_view->CreateViewForWidget(new_contents->GetRenderViewHost());
+    }
     // Save the created window associated with the route so we can show it
     // later.
     DCHECK_NE(MSG_ROUTING_NONE, route_id);
@@ -1540,6 +1551,10 @@
   registrar_.Remove(this, NOTIFICATION_WEB_CONTENTS_DESTROYED,
                     Source<WebContents>(new_contents));
 
+  // Don't initialize the guest WebContents immediately.
+  if (new_contents->GetRenderProcessHost()->IsGuest())
+    return new_contents;
+
   if (!new_contents->GetRenderProcessHost()->HasConnection() ||
       !new_contents->GetRenderViewHost()->GetView())
     return NULL;
@@ -1584,7 +1599,7 @@
   if (delegate_)
     delegate_->RequestMediaAccessPermission(this, request, callback);
   else
-    callback.Run(MediaStreamDevices());
+    callback.Run(MediaStreamDevices(), scoped_ptr<MediaStreamUI>());
 }
 
 void WebContentsImpl::UpdatePreferredSize(const gfx::Size& pref_size) {
@@ -1839,11 +1854,33 @@
     close_start_time_ = base::TimeTicks::Now();
 }
 
+void WebContentsImpl::DragSourceEndedAt(int client_x, int client_y,
+    int screen_x, int screen_y, WebKit::WebDragOperation operation) {
+  if (browser_plugin_embedder_.get())
+    browser_plugin_embedder_->DragSourceEndedAt(client_x, client_y,
+        screen_x, screen_y, operation);
+  if (GetRenderViewHost())
+    GetRenderViewHostImpl()->DragSourceEndedAt(client_x, client_y,
+        screen_x, screen_y, operation);
+}
+
+void WebContentsImpl::DragSourceMovedTo(int client_x, int client_y,
+                                        int screen_x, int screen_y) {
+  if (browser_plugin_embedder_.get())
+    browser_plugin_embedder_->DragSourceMovedTo(client_x, client_y,
+                                                screen_x, screen_y);
+  if (GetRenderViewHost())
+    GetRenderViewHostImpl()->DragSourceMovedTo(client_x, client_y,
+                                               screen_x, screen_y);
+}
+
 void WebContentsImpl::SystemDragEnded() {
   if (GetRenderViewHost())
     GetRenderViewHostImpl()->DragSourceSystemDragEnded();
   if (delegate_)
     delegate_->DragEnded();
+  if (browser_plugin_embedder_.get())
+    browser_plugin_embedder_->SystemDragEnded();
 }
 
 void WebContentsImpl::UserGestureDone() {
@@ -1927,46 +1964,6 @@
   return content_restrictions_;
 }
 
-WebUI* WebContentsImpl::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.
-  //
-  // The confusion comes because there are multiple possibilities for the
-  // 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 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/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 Web UI if any.
-  //
-  //  - First load in second tab: no committed nav entry + pending nav entry +
-  //    no pending Web UI:
-  //    -> Use the committed Web UI if any.
-  //
-  //  - Second navigation in any tab: committed nav entry + pending nav entry:
-  //    -> Use pending Web UI if any.
-  //
-  //  - Normal state with no load: committed nav entry + no pending nav entry:
-  //    -> Use committed Web UI.
-  if (controller_.GetPendingEntry() &&
-      (controller_.GetLastCommittedEntry() ||
-       render_manager_.pending_web_ui()))
-    return render_manager_.pending_web_ui();
-  return render_manager_.web_ui();
-}
-
 bool WebContentsImpl::GotResponseToLockMouseRequest(bool allowed) {
   return GetRenderViewHost() ?
       GetRenderViewHostImpl()->GotResponseToLockMouseRequest(allowed) : false;
@@ -1989,20 +1986,17 @@
   color_chooser_ = NULL;
 }
 
-int WebContentsImpl::DownloadFavicon(const GURL& url,
-                              bool is_favicon,
-                              int image_size,
-                              const FaviconDownloadCallback& callback) {
+int WebContentsImpl::DownloadImage(const GURL& url,
+                                   bool is_favicon,
+                                   int image_size,
+                                   const ImageDownloadCallback& callback) {
   RenderViewHost* host = GetRenderViewHost();
   int id = StartDownload(host, url, is_favicon, image_size);
-  favicon_download_map_[id] = callback;
+  image_download_map_[id] = callback;
   return id;
 }
 
 bool WebContentsImpl::FocusLocationBarByDefault() {
-  WebUI* web_ui = GetWebUIForCurrentState();
-  if (web_ui)
-    return web_ui->ShouldFocusLocationBarByDefault();
   NavigationEntry* entry = controller_.GetActiveEntry();
   if (entry && entry->GetURL() == GURL(chrome::kAboutBlankURL))
     return true;
@@ -2313,8 +2307,8 @@
 void WebContentsImpl::OnOpenDateTimeDialog(
     const ViewHostMsg_DateTimeDialogValue_Params& value) {
   date_time_chooser_->ShowDialog(
-      view_->GetContentNativeView(), GetRenderViewHost(), value.dialog_type,
-      value.year, value.month, value.day, value.hour,
+      ContentViewCore::FromWebContents(this), GetRenderViewHost(),
+      value.dialog_type, value.year, value.month, value.day, value.hour,
       value.minute, value.second);
 }
 
@@ -2407,13 +2401,13 @@
   browser_plugin_embedder_->OnMessageReceived(message);
 }
 
-void WebContentsImpl::OnDidDownloadFavicon(
+void WebContentsImpl::OnDidDownloadImage(
     int id,
     const GURL& image_url,
     int requested_size,
     const std::vector<SkBitmap>& bitmaps) {
-  FaviconDownloadMap::iterator iter = favicon_download_map_.find(id);
-  if (iter == favicon_download_map_.end()) {
+  ImageDownloadMap::iterator iter = image_download_map_.find(id);
+  if (iter == image_download_map_.end()) {
     // Currently WebContents notifies us of ANY downloads so that it is
     // possible to get here.
     return;
@@ -2421,7 +2415,7 @@
   if (!iter->second.is_null()) {
     iter->second.Run(id, image_url, requested_size, bitmaps);
   }
-  favicon_download_map_.erase(id);
+  image_download_map_.erase(id);
 }
 
 void WebContentsImpl::OnUpdateFaviconURL(
@@ -2640,7 +2634,7 @@
 }
 
 void WebContentsImpl::RemoveBrowserPluginEmbedder() {
-  if (browser_plugin_embedder_.get())
+  if (browser_plugin_embedder_)
     browser_plugin_embedder_.reset();
 }
 
@@ -2700,9 +2694,9 @@
   FOR_EACH_OBSERVER(WebContentsObserver, observers_, RenderViewReady());
 }
 
-void WebContentsImpl::RenderViewGone(RenderViewHost* rvh,
-                                     base::TerminationStatus status,
-                                     int error_code) {
+void WebContentsImpl::RenderViewTerminated(RenderViewHost* rvh,
+                                           base::TerminationStatus status,
+                                           int error_code) {
   if (rvh != GetRenderViewHost()) {
     // The pending page's RenderViewHost is gone.
     return;
@@ -2810,7 +2804,7 @@
                                   const std::string& state) {
   // Ensure that this state update comes from either the active RVH or one of
   // the swapped out RVHs.  We don't expect to hear from any other RVHs.
-  DCHECK(rvh == GetRenderViewHost() || render_manager_.IsSwappedOut(rvh));
+  DCHECK(rvh == GetRenderViewHost() || render_manager_.IsOnSwappedOutList(rvh));
 
   // We must be prepared to handle state updates for any page, these occur
   // when the user is scrolling and entering form data, as well as when we're
@@ -2912,7 +2906,10 @@
 void WebContentsImpl::DidStopLoading(RenderViewHost* render_view_host) {
   scoped_ptr<LoadNotificationDetails> details;
 
-  NavigationEntry* entry = controller_.GetActiveEntry();
+  // Use the last committed entry rather than the active one, in case a
+  // pending entry has been created.
+  NavigationEntry* entry = controller_.GetLastCommittedEntry();
+
   // An entry may not exist for a stop when loading an initial blank page or
   // if an iframe injected by script into a blank page finishes loading.
   if (entry) {
@@ -2948,11 +2945,13 @@
 }
 
 void WebContentsImpl::DidDisownOpener(RenderViewHost* rvh) {
-  // Clear our opener so that future cross-process navigations don't have an
-  // opener assigned.
-  registrar_.Remove(this, NOTIFICATION_WEB_CONTENTS_DESTROYED,
-                    Source<WebContents>(opener_));
-  opener_ = NULL;
+  if (opener_) {
+    // Clear our opener so that future cross-process navigations don't have an
+    // opener assigned.
+    registrar_.Remove(this, NOTIFICATION_WEB_CONTENTS_DESTROYED,
+                      Source<WebContents>(opener_));
+    opener_ = NULL;
+  }
 
   // Notify all swapped out RenderViewHosts for this tab.  This is important
   // in case we go back to them, or if another window in those processes tries
@@ -2960,10 +2959,6 @@
   render_manager_.DidDisownOpener(rvh);
 }
 
-void WebContentsImpl::DidUpdateFrameTree(RenderViewHost* rvh) {
-  render_manager_.DidUpdateFrameTree(rvh);
-}
-
 void WebContentsImpl::DocumentAvailableInMainFrame(
     RenderViewHost* render_view_host) {
   FOR_EACH_OBSERVER(WebContentsObserver, observers_,
@@ -3067,11 +3062,6 @@
 
   ViewMsg_PostMessage_Params new_params(params);
 
-  // If the renderer has changed while the post message is being routed,
-  // drop the message, as it will not be delivered to the right target.
-  // TODO(nasko): Check for process ID and target frame id mismatch, once
-  // http://crbug.com/153701 is fixed.
-
   // If there is a source_routing_id, translate it to the routing ID for
   // the equivalent swapped out RVH in the target process.  If we need
   // to create a swapped out RVH for the source tab, we create its opener
@@ -3294,7 +3284,7 @@
 void WebContentsImpl::RenderViewGoneFromRenderManager(
     RenderViewHost* render_view_host) {
   DCHECK(crashed_status_ != base::TERMINATION_STATUS_STILL_RUNNING);
-  RenderViewGone(render_view_host, crashed_status_, crashed_error_code_);
+  RenderViewTerminated(render_view_host, crashed_status_, crashed_error_code_);
 }
 
 void WebContentsImpl::UpdateRenderViewSizeForRenderManager() {
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h
index c9d6443..39cf2ae 100644
--- a/content/browser/web_contents/web_contents_impl.h
+++ b/content/browser/web_contents/web_contents_impl.h
@@ -25,6 +25,7 @@
 #include "content/public/common/renderer_preferences.h"
 #include "content/public/common/three_d_api_types.h"
 #include "net/base/load_states.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebDragOperation.h"
 #include "ui/gfx/rect_f.h"
 #include "ui/gfx/size.h"
 #include "webkit/glue/resource_type.h"
@@ -91,7 +92,7 @@
       int guest_instance_id);
 
   // Returns the content specific prefs for the given RVH.
-  static webkit_glue::WebPreferences GetWebkitPrefs(
+  static WebPreferences GetWebkitPrefs(
       RenderViewHost* rvh, const GURL& url);
 
   // Creates a swapped out RenderView. This is used by the browser plugin to
@@ -172,6 +173,17 @@
   // Invoked before a form repost warning is shown.
   void NotifyBeforeFormRepostWarningShow();
 
+
+  // Informs the render view host and the BrowserPluginEmbedder, if present, of
+  // a Drag Source End.
+  void DragSourceEndedAt(int client_x, int client_y, int screen_x,
+      int screen_y, WebKit::WebDragOperation operation);
+
+  // Informs the render view host and the BrowserPluginEmbedder, if present, of
+  // a Drag Source Move.
+  void DragSourceMovedTo(int client_x, int client_y,
+                         int screen_x, int screen_y);
+
   // WebContents ------------------------------------------------------
   virtual WebContentsDelegate* GetDelegate() OVERRIDE;
   virtual void SetDelegate(WebContentsDelegate* delegate) OVERRIDE;
@@ -194,6 +206,10 @@
   virtual WebUI* GetCommittedWebUI() const OVERRIDE;
   virtual void SetUserAgentOverride(const std::string& override) OVERRIDE;
   virtual const std::string& GetUserAgentOverride() const OVERRIDE;
+#if defined(OS_WIN) && defined(USE_AURA)
+  virtual void SetParentNativeViewAccessible(
+      gfx::NativeViewAccessible accessible_parent) OVERRIDE;
+#endif
   virtual const string16& GetTitle() const OVERRIDE;
   virtual int32 GetMaxPageID() OVERRIDE;
   virtual int32 GetMaxPageIDForSiteInstance(
@@ -259,16 +275,15 @@
   virtual int GetMaximumZoomPercent() const OVERRIDE;
   virtual gfx::Size GetPreferredSize() const OVERRIDE;
   virtual int GetContentRestrictions() const OVERRIDE;
-  virtual WebUI* GetWebUIForCurrentState() OVERRIDE;
   virtual bool GotResponseToLockMouseRequest(bool allowed) OVERRIDE;
   virtual bool HasOpener() const OVERRIDE;
   virtual void DidChooseColorInColorChooser(int color_chooser_id,
                                             SkColor color) OVERRIDE;
   virtual void DidEndColorChooser(int color_chooser_id) OVERRIDE;
-  virtual int DownloadFavicon(const GURL& url,
-                              bool is_favicon,
-                              int image_size,
-                              const FaviconDownloadCallback& callback) OVERRIDE;
+  virtual int DownloadImage(const GURL& url,
+                            bool is_favicon,
+                            int image_size,
+                            const ImageDownloadCallback& callback) OVERRIDE;
 
   // Implementation of PageNavigator.
   virtual WebContents* OpenURL(const OpenURLParams& params) OVERRIDE;
@@ -288,9 +303,9 @@
   virtual gfx::Rect GetRootWindowResizerRect() const OVERRIDE;
   virtual void RenderViewCreated(RenderViewHost* render_view_host) OVERRIDE;
   virtual void RenderViewReady(RenderViewHost* render_view_host) OVERRIDE;
-  virtual void RenderViewGone(RenderViewHost* render_view_host,
-                              base::TerminationStatus status,
-                              int error_code) OVERRIDE;
+  virtual void RenderViewTerminated(RenderViewHost* render_view_host,
+                                    base::TerminationStatus status,
+                                    int error_code) OVERRIDE;
   virtual void RenderViewDeleted(RenderViewHost* render_view_host) OVERRIDE;
   virtual void DidStartProvisionalLoadForFrame(
       RenderViewHost* render_view_host,
@@ -328,7 +343,6 @@
   virtual void DidCancelLoading() OVERRIDE;
   virtual void DidChangeLoadProgress(double progress) OVERRIDE;
   virtual void DidDisownOpener(RenderViewHost* rvh) OVERRIDE;
-  virtual void DidUpdateFrameTree(RenderViewHost* rvh) OVERRIDE;
   virtual void DocumentAvailableInMainFrame(
       RenderViewHost* render_view_host) OVERRIDE;
   virtual void DocumentOnLoadCompletedInMainFrame(
@@ -368,7 +382,7 @@
                                    const string16& source_id) OVERRIDE;
   virtual RendererPreferences GetRendererPrefs(
       BrowserContext* browser_context) const OVERRIDE;
-  virtual webkit_glue::WebPreferences GetWebkitPrefs() OVERRIDE;
+  virtual WebPreferences GetWebkitPrefs() OVERRIDE;
   virtual void OnUserGesture() OVERRIDE;
   virtual void OnIgnoredUIEvent() OVERRIDE;
   virtual void RendererUnresponsive(RenderViewHost* render_view_host,
@@ -429,6 +443,9 @@
       const NativeWebKeyboardEvent& event) OVERRIDE;
   virtual bool PreHandleWheelEvent(
       const WebKit::WebMouseWheelEvent& event) OVERRIDE;
+#if defined(OS_WIN) && defined(USE_AURA)
+  virtual gfx::NativeViewAccessible GetParentNativeViewAccessible() OVERRIDE;
+#endif
 
   // RenderViewHostManager::Delegate -------------------------------------------
 
@@ -565,10 +582,10 @@
                                       const GURL& url,
                                       const base::FilePath& plugin_path);
   void OnBrowserPluginMessage(const IPC::Message& message);
-  void OnDidDownloadFavicon(int id,
-                            const GURL& image_url,
-                            int requested_size,
-                            const std::vector<SkBitmap>& bitmaps);
+  void OnDidDownloadImage(int id,
+                          const GURL& image_url,
+                          int requested_size,
+                          const std::vector<SkBitmap>& bitmaps);
   void OnUpdateFaviconURL(int32 page_id,
                           const std::vector<FaviconURL>& candidates);
   void OnFrameDetached(int64 frame_id);
@@ -719,6 +736,10 @@
   // is closed.
   WebContentsImpl* opener_;
 
+#if defined(OS_WIN) && defined(USE_AURA)
+  gfx::NativeViewAccessible accessible_parent_;
+#endif
+
   // Helper classes ------------------------------------------------------------
 
   // Manages creation and swapping of render views.
@@ -871,9 +892,9 @@
   // Routing id of the shown fullscreen widget or MSG_ROUTING_NONE otherwise.
   int fullscreen_widget_routing_id_;
 
-  // Maps the ids of pending favicon downloads to their callbacks
-  typedef std::map<int, FaviconDownloadCallback> FaviconDownloadMap;
-  FaviconDownloadMap favicon_download_map_;
+  // Maps the ids of pending image downloads to their callbacks
+  typedef std::map<int, ImageDownloadCallback> ImageDownloadMap;
+  ImageDownloadMap image_download_map_;
 
   DISALLOW_COPY_AND_ASSIGN(WebContentsImpl);
 };
diff --git a/content/browser/web_contents/web_contents_impl_browsertest.cc b/content/browser/web_contents/web_contents_impl_browsertest.cc
new file mode 100644
index 0000000..f3830f1
--- /dev/null
+++ b/content/browser/web_contents/web_contents_impl_browsertest.cc
@@ -0,0 +1,124 @@
+// Copyright 2013 The Chromium Authors. 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 "content/browser/web_contents/web_contents_impl.h"
+#include "content/public/browser/load_notification_details.h"
+#include "content/public/browser/navigation_controller.h"
+#include "content/public/browser/notification_details.h"
+#include "content/public/browser/notification_observer.h"
+#include "content/public/browser/notification_types.h"
+#include "content/public/test/browser_test_utils.h"
+#include "content/public/test/test_utils.h"
+#include "content/shell/shell.h"
+#include "content/test/content_browser_test.h"
+#include "content/test/content_browser_test_utils.h"
+#include "net/test/spawned_test_server.h"
+
+namespace content {
+
+class WebContentsImplBrowserTest : public ContentBrowserTest {
+ public:
+  WebContentsImplBrowserTest() {}
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(WebContentsImplBrowserTest);
+};
+
+// Keeps track of data from LoadNotificationDetails so we can later verify that
+// they are correct, after the LoadNotificationDetails object is deleted.
+class LoadStopNotificationObserver : public WindowedNotificationObserver {
+ public:
+  LoadStopNotificationObserver(NavigationController* controller)
+      : WindowedNotificationObserver(NOTIFICATION_LOAD_STOP,
+                                     Source<NavigationController>(controller)),
+        session_index_(-1),
+        controller_(NULL) {
+  }
+  virtual void Observe(int type,
+                       const NotificationSource& source,
+                       const NotificationDetails& details) OVERRIDE {
+    if (type == NOTIFICATION_LOAD_STOP) {
+      const Details<LoadNotificationDetails> load_details(details);
+      url_ = load_details->url;
+      session_index_ = load_details->session_index;
+      controller_ = load_details->controller;
+    }
+    WindowedNotificationObserver::Observe(type, source, details);
+  }
+
+  GURL url_;
+  int session_index_;
+  NavigationController* controller_;
+};
+
+// Starts a new navigation as soon as the current one commits, but does not
+// wait for it to complete.  This allows us to observe DidStopLoading while
+// a pending entry is present.
+class NavigateOnCommitObserver : public WindowedNotificationObserver {
+ public:
+  NavigateOnCommitObserver(Shell* shell, GURL url)
+      : WindowedNotificationObserver(
+            NOTIFICATION_NAV_ENTRY_COMMITTED,
+            Source<NavigationController>(
+                &shell->web_contents()->GetController())),
+        shell_(shell),
+        url_(url),
+        done_(false) {
+  }
+  virtual void Observe(int type,
+                       const NotificationSource& source,
+                       const NotificationDetails& details) OVERRIDE {
+    if (type == NOTIFICATION_NAV_ENTRY_COMMITTED && !done_) {
+      done_ = true;
+      shell_->LoadURL(url_);
+    }
+    WindowedNotificationObserver::Observe(type, source, details);
+  }
+
+  Shell* shell_;
+  GURL url_;
+  bool done_;
+};
+
+// Test that DidStopLoading includes the correct URL in the details.
+IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, DidStopLoadingDetails) {
+  ASSERT_TRUE(test_server()->Start());
+
+  LoadStopNotificationObserver load_observer(
+      &shell()->web_contents()->GetController());
+  NavigateToURL(shell(), test_server()->GetURL("files/title1.html"));
+  load_observer.Wait();
+
+  EXPECT_EQ("/files/title1.html", load_observer.url_.path());
+  EXPECT_EQ(0, load_observer.session_index_);
+  EXPECT_EQ(&shell()->web_contents()->GetController(),
+            load_observer.controller_);
+}
+
+// Test that DidStopLoading includes the correct URL in the details when a
+// pending entry is present.
+IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
+                       DidStopLoadingDetailsWithPending) {
+  ASSERT_TRUE(test_server()->Start());
+
+  // Listen for the first load to stop.
+  LoadStopNotificationObserver load_observer(
+      &shell()->web_contents()->GetController());
+  // Start a new pending navigation as soon as the first load commits.
+  // We will hear a DidStopLoading from the first load as the new load
+  // is started.
+  NavigateOnCommitObserver commit_observer(
+      shell(), test_server()->GetURL("files/title2.html"));
+  NavigateToURL(shell(), test_server()->GetURL("files/title1.html"));
+  commit_observer.Wait();
+  load_observer.Wait();
+
+  EXPECT_EQ("/files/title1.html", load_observer.url_.path());
+  EXPECT_EQ(0, load_observer.session_index_);
+  EXPECT_EQ(&shell()->web_contents()->GetController(),
+            load_observer.controller_);
+}
+
+}  // namespace content
diff --git a/content/browser/web_contents/web_contents_impl_unittest.cc b/content/browser/web_contents/web_contents_impl_unittest.cc
index 80b8713..cb702a4 100644
--- a/content/browser/web_contents/web_contents_impl_unittest.cc
+++ b/content/browser/web_contents/web_contents_impl_unittest.cc
@@ -156,8 +156,9 @@
     DidNavigate(GetRenderViewHostForTesting(), params);
   }
 
-  void TestRenderViewGone(base::TerminationStatus status, int error_code) {
-    RenderViewGone(GetRenderViewHostForTesting(), status, error_code);
+  void TestRenderViewTerminated(base::TerminationStatus status,
+                                int error_code) {
+    RenderViewTerminated(GetRenderViewHostForTesting(), status, error_code);
   }
 
   bool is_showing() const {
@@ -438,7 +439,8 @@
   EXPECT_NE(instance1, instance2);
   EXPECT_TRUE(contents()->GetPendingRenderViewHost() == NULL);
   // We keep the original RVH around, swapped out.
-  EXPECT_TRUE(contents()->GetRenderManagerForTesting()->IsSwappedOut(orig_rvh));
+  EXPECT_TRUE(contents()->GetRenderManagerForTesting()->IsOnSwappedOutList(
+      orig_rvh));
   EXPECT_EQ(orig_rvh_delete_count, 0);
 
   // Going back should switch SiteInstances again.  The first SiteInstance is
@@ -463,7 +465,7 @@
   EXPECT_EQ(instance1, contents()->GetSiteInstance());
   // The pending RVH should now be swapped out, not deleted.
   EXPECT_TRUE(contents()->GetRenderManagerForTesting()->
-      IsSwappedOut(pending_rvh));
+      IsOnSwappedOutList(pending_rvh));
   EXPECT_EQ(pending_rvh_delete_count, 0);
 
   // Close contents and ensure RVHs are deleted.
@@ -682,8 +684,8 @@
   controller().LoadURL(
       url2, Referrer(), PAGE_TRANSITION_TYPED, std::string());
   EXPECT_TRUE(orig_rvh->is_waiting_for_beforeunload_ack());
-  orig_rvh->OnMessageReceived(ViewHostMsg_ShouldClose_ACK(
-      0, false, base::TimeTicks(), base::TimeTicks()));
+  base::TimeTicks now = base::TimeTicks::Now();
+  orig_rvh->OnMessageReceived(ViewHostMsg_ShouldClose_ACK(0, false, now, now));
   EXPECT_FALSE(orig_rvh->is_waiting_for_beforeunload_ack());
   EXPECT_FALSE(contents()->cross_navigation_pending());
   EXPECT_EQ(orig_rvh, contents()->GetRenderViewHost());
@@ -692,8 +694,8 @@
   controller().LoadURL(
       url2, Referrer(), PAGE_TRANSITION_TYPED, std::string());
   EXPECT_TRUE(orig_rvh->is_waiting_for_beforeunload_ack());
-  orig_rvh->OnMessageReceived(ViewHostMsg_ShouldClose_ACK(
-      0, true, base::TimeTicks(), base::TimeTicks()));
+  now = base::TimeTicks::Now();
+  orig_rvh->OnMessageReceived(ViewHostMsg_ShouldClose_ACK(0, true, now, now));
   EXPECT_FALSE(orig_rvh->is_waiting_for_beforeunload_ack());
   EXPECT_TRUE(contents()->cross_navigation_pending());
   TestRenderViewHost* pending_rvh = static_cast<TestRenderViewHost*>(
@@ -734,8 +736,8 @@
   controller().LoadURL(
       url2, Referrer(), PAGE_TRANSITION_TYPED, std::string());
   EXPECT_TRUE(orig_rvh->is_waiting_for_beforeunload_ack());
-  orig_rvh->OnMessageReceived(ViewHostMsg_ShouldClose_ACK(
-      0, true, base::TimeTicks(), base::TimeTicks()));
+  base::TimeTicks now = base::TimeTicks::Now();
+  orig_rvh->OnMessageReceived(ViewHostMsg_ShouldClose_ACK(0, true, now, now));
   EXPECT_TRUE(contents()->cross_navigation_pending());
 
   // Suppose the original renderer navigates before the new one is ready.
@@ -779,8 +781,8 @@
 
   // Simulate beforeunload approval.
   EXPECT_TRUE(ntp_rvh->is_waiting_for_beforeunload_ack());
-  ntp_rvh->OnMessageReceived(ViewHostMsg_ShouldClose_ACK(
-      0, true, base::TimeTicks(), base::TimeTicks()));
+  base::TimeTicks now = base::TimeTicks::Now();
+  ntp_rvh->OnMessageReceived(ViewHostMsg_ShouldClose_ACK(0, true, now, now));
 
   // DidNavigate from the pending page.
   contents()->TestDidNavigate(
@@ -828,8 +830,8 @@
 
   // Simulate beforeunload approval.
   EXPECT_TRUE(google_rvh->is_waiting_for_beforeunload_ack());
-  google_rvh->OnMessageReceived(ViewHostMsg_ShouldClose_ACK(
-      0, true, base::TimeTicks(), base::TimeTicks()));
+  now = base::TimeTicks::Now();
+  google_rvh->OnMessageReceived(ViewHostMsg_ShouldClose_ACK(0, true, now, now));
 
   // DidNavigate from the first back. This aborts the second back's pending RVH.
   contents()->TestDidNavigate(google_rvh, 1, url2, PAGE_TRANSITION_TYPED);
@@ -877,8 +879,8 @@
 
   // Now simulate the onbeforeunload approval and verify the navigation is
   // not canceled.
-  orig_rvh->OnMessageReceived(ViewHostMsg_ShouldClose_ACK(
-      0, true, base::TimeTicks(), base::TimeTicks()));
+  base::TimeTicks now = base::TimeTicks::Now();
+  orig_rvh->OnMessageReceived(ViewHostMsg_ShouldClose_ACK(0, true, now, now));
   EXPECT_FALSE(orig_rvh->is_waiting_for_beforeunload_ack());
   EXPECT_TRUE(contents()->cross_navigation_pending());
 }
@@ -941,8 +943,8 @@
   const GURL url2("http://www.yahoo.com");
   controller().LoadURL(
       url2, Referrer(), PAGE_TRANSITION_TYPED, std::string());
-  orig_rvh->OnMessageReceived(ViewHostMsg_ShouldClose_ACK(
-      0, true, base::TimeTicks(), base::TimeTicks()));
+  base::TimeTicks now = base::TimeTicks::Now();
+  orig_rvh->OnMessageReceived(ViewHostMsg_ShouldClose_ACK(0, true, now, now));
   EXPECT_TRUE(contents()->cross_navigation_pending());
   TestRenderViewHost* pending_rvh = static_cast<TestRenderViewHost*>(
       contents()->GetPendingRenderViewHost());
@@ -993,8 +995,8 @@
   const GURL url2("http://www.yahoo.com");
   controller().LoadURL(url2, Referrer(), PAGE_TRANSITION_TYPED, std::string());
   EXPECT_TRUE(orig_rvh->is_waiting_for_beforeunload_ack());
-  orig_rvh->OnMessageReceived(ViewHostMsg_ShouldClose_ACK(
-      0, true, base::TimeTicks(), base::TimeTicks()));
+  base::TimeTicks now = base::TimeTicks::Now();
+  orig_rvh->OnMessageReceived(ViewHostMsg_ShouldClose_ACK(0, true, now, now));
   EXPECT_TRUE(contents()->cross_navigation_pending());
 
   // Simulate swap out message when the response arrives.
@@ -1805,7 +1807,7 @@
   TestInterstitialPageStateGuard state_guard(interstitial);
   interstitial->Show();
   // Simulate a renderer crash before the interstitial is shown.
-  interstitial->TestRenderViewGone(
+  interstitial->TestRenderViewTerminated(
       base::TERMINATION_STATUS_PROCESS_CRASHED, -1);
   // The interstitial should have been dismissed.
   EXPECT_EQ(TestInterstitialPage::CANCELED, state);
@@ -1818,7 +1820,7 @@
   interstitial->Show();
   interstitial->TestDidNavigate(1, url);
   // Simulate a renderer crash.
-  interstitial->TestRenderViewGone(
+  interstitial->TestRenderViewTerminated(
       base::TERMINATION_STATUS_PROCESS_CRASHED, -1);
   // The interstitial should have been dismissed.
   EXPECT_EQ(TestInterstitialPage::CANCELED, state);
diff --git a/content/browser/web_contents/web_contents_screenshot_manager.cc b/content/browser/web_contents/web_contents_screenshot_manager.cc
new file mode 100644
index 0000000..49cb0c6
--- /dev/null
+++ b/content/browser/web_contents/web_contents_screenshot_manager.cc
@@ -0,0 +1,272 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/web_contents/web_contents_screenshot_manager.h"
+
+#include "base/command_line.h"
+#include "base/threading/worker_pool.h"
+#include "content/browser/renderer_host/render_view_host_impl.h"
+#include "content/browser/web_contents/navigation_controller_impl.h"
+#include "content/browser/web_contents/navigation_entry_impl.h"
+#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/public/browser/render_widget_host.h"
+#include "content/public/browser/render_widget_host_view.h"
+#include "content/public/common/content_switches.h"
+#include "ui/gfx/codec/png_codec.h"
+
+namespace {
+
+// Minimum delay between taking screenshots.
+const int kMinScreenshotIntervalMS = 1000;
+
+}
+
+namespace content {
+
+// Encodes an SkBitmap to PNG data in a worker thread.
+class ScreenshotData : public base::RefCountedThreadSafe<ScreenshotData> {
+ public:
+  ScreenshotData() {
+  }
+
+  void EncodeScreenshot(const SkBitmap& bitmap, base::Closure callback) {
+    if (!base::WorkerPool::PostTaskAndReply(FROM_HERE,
+            base::Bind(&ScreenshotData::EncodeOnWorker,
+                       this,
+                       bitmap),
+            callback,
+            true)) {
+      callback.Run();
+    }
+  }
+
+  scoped_refptr<base::RefCountedBytes> data() const { return data_; }
+
+ private:
+  friend class base::RefCountedThreadSafe<ScreenshotData>;
+  virtual ~ScreenshotData() {
+  }
+
+  void EncodeOnWorker(const SkBitmap& bitmap) {
+    std::vector<unsigned char> data;
+    if (gfx::PNGCodec::EncodeBGRASkBitmap(bitmap, true, &data))
+      data_ = new base::RefCountedBytes(data);
+  }
+
+  scoped_refptr<base::RefCountedBytes> data_;
+
+  DISALLOW_COPY_AND_ASSIGN(ScreenshotData);
+};
+
+WebContentsScreenshotManager::WebContentsScreenshotManager(
+    NavigationControllerImpl* owner)
+    : owner_(owner),
+      screenshot_factory_(this),
+      min_screenshot_interval_ms_(kMinScreenshotIntervalMS) {
+}
+
+WebContentsScreenshotManager::~WebContentsScreenshotManager() {
+}
+
+void WebContentsScreenshotManager::TakeScreenshot() {
+  static bool overscroll_enabled = CommandLine::ForCurrentProcess()->
+      GetSwitchValueASCII(switches::kOverscrollHistoryNavigation) != "0";
+  if (!overscroll_enabled)
+    return;
+
+  NavigationEntryImpl* entry =
+      NavigationEntryImpl::FromNavigationEntry(owner_->GetLastCommittedEntry());
+  if (!entry)
+    return;
+
+  RenderViewHost* render_view_host =
+      owner_->web_contents()->GetRenderViewHost();
+  if (!static_cast<RenderViewHostImpl*>
+      (render_view_host)->overscroll_controller()) {
+    return;
+  }
+  content::RenderWidgetHostView* view = render_view_host->GetView();
+  if (!view)
+    return;
+
+  // Make sure screenshots aren't taken too frequently.
+  base::Time now = base::Time::Now();
+  if (now - last_screenshot_time_ <
+          base::TimeDelta::FromMilliseconds(min_screenshot_interval_ms_)) {
+    return;
+  }
+
+  last_screenshot_time_ = now;
+
+  TakeScreenshotImpl(render_view_host, entry);
+}
+
+// Implemented here and not in NavigationEntry because this manager keeps track
+// of the total number of screen shots across all entries.
+void WebContentsScreenshotManager::ClearAllScreenshots() {
+  int count = owner_->GetEntryCount();
+  for (int i = 0; i < count; ++i) {
+    ClearScreenshot(NavigationEntryImpl::FromNavigationEntry(
+        owner_->GetEntryAtIndex(i)));
+  }
+  DCHECK_EQ(GetScreenshotCount(), 0);
+}
+
+void WebContentsScreenshotManager::TakeScreenshotImpl(
+    RenderViewHost* host,
+    NavigationEntryImpl* entry) {
+  DCHECK(host && host->GetView());
+  DCHECK(entry);
+  host->CopyFromBackingStore(gfx::Rect(),
+      host->GetView()->GetViewBounds().size(),
+      base::Bind(&WebContentsScreenshotManager::OnScreenshotTaken,
+                 screenshot_factory_.GetWeakPtr(),
+                 entry->GetUniqueID()));
+}
+
+void WebContentsScreenshotManager::SetMinScreenshotIntervalMS(int interval_ms) {
+  DCHECK_GE(interval_ms, 0);
+  min_screenshot_interval_ms_ = interval_ms;
+}
+
+void WebContentsScreenshotManager::OnScreenshotTaken(int unique_id,
+                                                     bool success,
+                                                     const SkBitmap& bitmap) {
+  NavigationEntryImpl* entry = NULL;
+  int entry_count = owner_->GetEntryCount();
+  for (int i = 0; i < entry_count; ++i) {
+    NavigationEntry* iter = owner_->GetEntryAtIndex(i);
+    if (iter->GetUniqueID() == unique_id) {
+      entry = NavigationEntryImpl::FromNavigationEntry(iter);
+      break;
+    }
+  }
+
+  if (!entry) {
+    LOG(ERROR) << "Invalid entry with unique id: " << unique_id;
+    return;
+  }
+
+  if (!success || bitmap.empty() || bitmap.isNull()) {
+    ClearScreenshot(entry);
+    return;
+  }
+
+  scoped_refptr<ScreenshotData> screenshot = new ScreenshotData();
+  screenshot->EncodeScreenshot(
+      bitmap,
+      base::Bind(&WebContentsScreenshotManager::OnScreenshotEncodeComplete,
+                 screenshot_factory_.GetWeakPtr(),
+                 unique_id,
+                 screenshot));
+}
+
+int WebContentsScreenshotManager::GetScreenshotCount() const {
+  int screenshot_count = 0;
+  int entry_count = owner_->GetEntryCount();
+  for (int i = 0; i < entry_count; ++i) {
+    NavigationEntryImpl* entry =
+        NavigationEntryImpl::FromNavigationEntry(owner_->GetEntryAtIndex(i));
+    if (entry->screenshot())
+      screenshot_count++;
+  }
+  return screenshot_count;
+}
+
+void WebContentsScreenshotManager::OnScreenshotEncodeComplete(
+    int unique_id,
+    scoped_refptr<ScreenshotData> screenshot) {
+  NavigationEntryImpl* entry = NULL;
+  int entry_count = owner_->GetEntryCount();
+  for (int i = 0; i < entry_count; ++i) {
+    NavigationEntry* iter = owner_->GetEntryAtIndex(i);
+    if (iter->GetUniqueID() == unique_id) {
+      entry = NavigationEntryImpl::FromNavigationEntry(iter);
+      break;
+    }
+  }
+  if (!entry)
+    return;
+  entry->SetScreenshotPNGData(screenshot->data());
+  OnScreenshotSet(entry);
+}
+
+void WebContentsScreenshotManager::OnScreenshotSet(NavigationEntryImpl* entry) {
+  PurgeScreenshotsIfNecessary();
+}
+
+bool WebContentsScreenshotManager::ClearScreenshot(NavigationEntryImpl* entry) {
+  if (!entry->screenshot())
+    return false;
+
+  entry->SetScreenshotPNGData(NULL);
+  return true;
+}
+
+void WebContentsScreenshotManager::PurgeScreenshotsIfNecessary() {
+  // Allow only a certain number of entries to keep screenshots.
+  const int kMaxScreenshots = 10;
+  int screenshot_count = GetScreenshotCount();
+  if (screenshot_count < kMaxScreenshots)
+    return;
+
+  const int current = owner_->GetCurrentEntryIndex();
+  const int num_entries = owner_->GetEntryCount();
+  int available_slots = kMaxScreenshots;
+  if (NavigationEntryImpl::FromNavigationEntry(
+          owner_->GetEntryAtIndex(current))->screenshot()) {
+    --available_slots;
+  }
+
+  // Keep screenshots closer to the current navigation entry, and purge the ones
+  // that are farther away from it. So in each step, look at the entries at
+  // each offset on both the back and forward history, and start counting them
+  // to make sure that the correct number of screenshots are kept in memory.
+  // Note that it is possible for some entries to be missing screenshots (e.g.
+  // when taking the screenshot failed for some reason). So there may be a state
+  // where there are a lot of entries in the back history, but none of them has
+  // any screenshot. In such cases, keep the screenshots for |kMaxScreenshots|
+  // entries in the forward history list.
+  int back = current - 1;
+  int forward = current + 1;
+  while (available_slots > 0 && (back >= 0 || forward < num_entries)) {
+    if (back >= 0) {
+      NavigationEntryImpl* entry = NavigationEntryImpl::FromNavigationEntry(
+          owner_->GetEntryAtIndex(back));
+      if (entry->screenshot())
+        --available_slots;
+      --back;
+    }
+
+    if (available_slots > 0 && forward < num_entries) {
+      NavigationEntryImpl* entry = NavigationEntryImpl::FromNavigationEntry(
+          owner_->GetEntryAtIndex(forward));
+      if (entry->screenshot())
+        --available_slots;
+      ++forward;
+    }
+  }
+
+  // Purge any screenshot at |back| or lower indices, and |forward| or higher
+  // indices.
+  while (screenshot_count > kMaxScreenshots && back >= 0) {
+    NavigationEntryImpl* entry = NavigationEntryImpl::FromNavigationEntry(
+        owner_->GetEntryAtIndex(back));
+    if (ClearScreenshot(entry))
+      --screenshot_count;
+    --back;
+  }
+
+  while (screenshot_count > kMaxScreenshots && forward < num_entries) {
+    NavigationEntryImpl* entry = NavigationEntryImpl::FromNavigationEntry(
+        owner_->GetEntryAtIndex(forward));
+    if (ClearScreenshot(entry))
+      --screenshot_count;
+    ++forward;
+  }
+  CHECK_GE(screenshot_count, 0);
+  CHECK_LE(screenshot_count, kMaxScreenshots);
+}
+
+}  // namespace content
diff --git a/content/browser/web_contents/web_contents_screenshot_manager.h b/content/browser/web_contents/web_contents_screenshot_manager.h
new file mode 100644
index 0000000..2162cf4
--- /dev/null
+++ b/content/browser/web_contents/web_contents_screenshot_manager.h
@@ -0,0 +1,89 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_WEB_CONTENTS_WEB_CONTENTS_SCREENSHOT_MANAGER_H_
+#define CONTENT_BROWSER_WEB_CONTENTS_WEB_CONTENTS_SCREENSHOT_MANAGER_H_
+
+#include "base/compiler_specific.h"
+#include "base/memory/weak_ptr.h"
+#include "base/time.h"
+#include "content/common/content_export.h"
+
+class SkBitmap;
+
+namespace content {
+
+class NavigationControllerImpl;
+class NavigationEntryImpl;
+class RenderViewHost;
+class ScreenshotData;
+
+// WebContentsScreenshotManager takes care of taking image-captures for the
+// current navigation entry of a NavigationControllerImpl, and managing these
+// captured images. These image-captures are used for history navigation using
+// overscroll gestures.
+class CONTENT_EXPORT WebContentsScreenshotManager {
+ public:
+  explicit WebContentsScreenshotManager(NavigationControllerImpl* controller);
+  virtual ~WebContentsScreenshotManager();
+
+  // Takes a screenshot of the last-committed entry of the controller.
+  void TakeScreenshot();
+
+  // Clears screenshots of all navigation entries.
+  void ClearAllScreenshots();
+
+ protected:
+  virtual void TakeScreenshotImpl(RenderViewHost* host,
+                                  NavigationEntryImpl* entry);
+
+  // Called after a screenshot has been set on an NavigationEntryImpl.
+  // Overridden in tests to get notified of when a screenshot is set.
+  virtual void OnScreenshotSet(NavigationEntryImpl* entry);
+
+  NavigationControllerImpl* owner() { return owner_; }
+
+  void SetMinScreenshotIntervalMS(int interval_ms);
+
+  // The callback invoked when taking the screenshot of the page is complete.
+  // This sets the screenshot on the navigation entry.
+  void OnScreenshotTaken(int unique_id,
+                         bool success,
+                         const SkBitmap& bitmap);
+
+  // Returns the number of entries with screenshots.
+  int GetScreenshotCount() const;
+
+ private:
+  // This is called when the screenshot data has beene encoded to PNG in a
+  // worker thread.
+  void OnScreenshotEncodeComplete(int unique_id,
+                                  scoped_refptr<ScreenshotData> data);
+
+  // Removes the screenshot for the entry, returning true if the entry had a
+  // screenshot.
+  bool ClearScreenshot(NavigationEntryImpl* entry);
+
+  // The screenshots in the NavigationEntryImpls can accumulate and consume a
+  // large amount of memory. This function makes sure that the memory
+  // consumption is within a certain limit.
+  void PurgeScreenshotsIfNecessary();
+
+  // The navigation controller that owns this screenshot-manager.
+  NavigationControllerImpl* owner_;
+
+  // Taking a screenshot and encoding them can be async. So use a weakptr for
+  // the callback to make sure that the screenshot/encoding completion callback
+  // does not trigger on a destroyed WebContentsScreenshotManager.
+  base::WeakPtrFactory<WebContentsScreenshotManager> screenshot_factory_;
+
+  base::Time last_screenshot_time_;
+  int min_screenshot_interval_ms_;
+
+  DISALLOW_COPY_AND_ASSIGN(WebContentsScreenshotManager);
+};
+
+}  // namespace content
+
+#endif  // CONTENT_BROWSER_WEB_CONTENTS_WEB_CONTENTS_SCREENSHOT_MANAGER_H_
diff --git a/content/browser/web_contents/web_contents_view_android.cc b/content/browser/web_contents/web_contents_view_android.cc
index 28ce304..1540d95 100644
--- a/content/browser/web_contents/web_contents_view_android.cc
+++ b/content/browser/web_contents/web_contents_view_android.cc
@@ -6,7 +6,7 @@
 
 #include "base/logging.h"
 #include "content/browser/android/content_view_core_impl.h"
-#include "content/browser/android/media_player_manager_android.h"
+#include "content/browser/android/media_player_manager_impl.h"
 #include "content/browser/renderer_host/render_widget_host_view_android.h"
 #include "content/browser/renderer_host/render_view_host_factory.h"
 #include "content/browser/renderer_host/render_view_host_impl.h"
@@ -54,17 +54,25 @@
   }
 }
 
+#if defined(GOOGLE_TV)
 void WebContentsViewAndroid::RequestExternalVideoSurface(int player_id) {
   if (content_view_core_)
     content_view_core_->RequestExternalVideoSurface(player_id);
 }
 
+void WebContentsViewAndroid::NotifyGeometryChange(int player_id,
+                                                  const gfx::RectF& rect) {
+  if (content_view_core_)
+    content_view_core_->NotifyGeometryChange(player_id, rect);
+}
+#endif
+
 gfx::NativeView WebContentsViewAndroid::GetNativeView() const {
-  return content_view_core_;
+  return content_view_core_->GetViewAndroid();
 }
 
 gfx::NativeView WebContentsViewAndroid::GetContentNativeView() const {
-  return content_view_core_;
+  return content_view_core_->GetViewAndroid();
 }
 
 gfx::NativeWindow WebContentsViewAndroid::GetTopLevelNativeWindow() const {
@@ -177,7 +185,7 @@
 void WebContentsViewAndroid::ShowContextMenu(
     const ContextMenuParams& params,
     ContextMenuSourceType type) {
-  if (delegate_.get())
+  if (delegate_)
     delegate_->ShowContextMenu(params, type);
 }
 
diff --git a/content/browser/web_contents/web_contents_view_android.h b/content/browser/web_contents/web_contents_view_android.h
index a882ae5..dcfaf39 100644
--- a/content/browser/web_contents/web_contents_view_android.h
+++ b/content/browser/web_contents/web_contents_view_android.h
@@ -11,6 +11,7 @@
 #include "content/port/browser/web_contents_view_port.h"
 #include "content/public/browser/web_contents_view_delegate.h"
 #include "content/public/common/context_menu_params.h"
+#include "ui/gfx/rect_f.h"
 
 namespace content {
 class ContentViewCoreImpl;
@@ -28,7 +29,10 @@
   // by the UI frontend.
   void SetContentViewCore(ContentViewCoreImpl* content_view_core);
 
+#if defined(GOOGLE_TV)
   void RequestExternalVideoSurface(int player_id);
+  void NotifyGeometryChange(int player_id, const gfx::RectF& rect);
+#endif
 
   // WebContentsView implementation --------------------------------------------
   virtual gfx::NativeView GetNativeView() const OVERRIDE;
diff --git a/content/browser/web_contents/web_contents_view_aura.cc b/content/browser/web_contents/web_contents_view_aura.cc
index 791bbd3..7fe338c 100644
--- a/content/browser/web_contents/web_contents_view_aura.cc
+++ b/content/browser/web_contents/web_contents_view_aura.cc
@@ -13,8 +13,11 @@
 #include "content/browser/renderer_host/render_view_host_impl.h"
 #include "content/browser/renderer_host/render_widget_host_impl.h"
 #include "content/browser/renderer_host/render_widget_host_view_aura.h"
+#include "content/browser/web_contents/aura/image_window_delegate.h"
+#include "content/browser/web_contents/aura/shadow_layer_delegate.h"
 #include "content/browser/web_contents/interstitial_page_impl.h"
 #include "content/browser/web_contents/navigation_entry_impl.h"
+#include "content/browser/web_contents/touch_editable_impl_aura.h"
 #include "content/browser/web_contents/web_contents_impl.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
@@ -29,7 +32,6 @@
 #include "content/public/browser/web_contents_view_delegate.h"
 #include "content/public/browser/web_drag_dest_delegate.h"
 #include "third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h"
-#include "third_party/skia/include/effects/SkGradientShader.h"
 #include "ui/aura/client/aura_constants.h"
 #include "ui/aura/client/drag_drop_client.h"
 #include "ui/aura/client/drag_drop_delegate.h"
@@ -51,7 +53,6 @@
 #include "ui/gfx/image/image_png_rep.h"
 #include "ui/gfx/image/image_skia.h"
 #include "ui/gfx/screen.h"
-#include "ui/gfx/skia_util.h"
 #include "webkit/glue/webdropdata.h"
 
 #if defined(OS_WIN)
@@ -70,18 +71,6 @@
 
 namespace {
 
-const SkColor kShadowLightColor = SkColorSetARGB(0x0, 0, 0, 0);
-const SkColor kShadowDarkColor = SkColorSetARGB(0x70, 0, 0, 0);
-const int kShadowThick = 7;
-
-enum ShadowEdge {
-  SHADOW_NONE,
-  SHADOW_LEFT,
-  SHADOW_RIGHT,
-  SHADOW_TOP,
-  SHADOW_BOTTOM
-};
-
 bool ShouldNavigateForward(const NavigationController& controller,
                            OverscrollMode mode) {
   return mode == (base::i18n::IsRTL() ? OVERSCROLL_EAST : OVERSCROLL_WEST) &&
@@ -94,15 +83,25 @@
          controller.CanGoBack();
 }
 
+RenderWidgetHostViewAura* ToRenderWidgetHostViewAura(
+    RenderWidgetHostView* view) {
+  if (!view || RenderViewHostFactory::has_factory())
+    return NULL;  // Can't cast to RenderWidgetHostViewAura in unit tests.
+  RenderProcessHostImpl* process = static_cast<RenderProcessHostImpl*>(
+      view->GetRenderWidgetHost()->GetProcess());
+  if (process->IsGuest())
+    return NULL;
+  return static_cast<RenderWidgetHostViewAura*>(view);
+}
+
 // The window delegate for the overscroll window. This redirects trackpad events
 // to the web-contents window. The delegate destroys itself when the window is
 // destroyed.
-class OverscrollWindowDelegate : public aura::WindowDelegate {
+class OverscrollWindowDelegate : public ImageWindowDelegate {
  public:
   OverscrollWindowDelegate(WebContentsImpl* web_contents,
                            OverscrollMode overscroll_mode)
       : web_contents_(web_contents),
-        show_shadow_(false),
         forward_events_(true) {
     const NavigationControllerImpl& controller = web_contents->GetController();
     const NavigationEntryImpl* entry = NULL;
@@ -113,21 +112,15 @@
       entry = NavigationEntryImpl::FromNavigationEntry(
           controller.GetEntryAtOffset(-1));
     }
-    if (!entry || !entry->screenshot())
-      return;
 
-    std::vector<gfx::ImagePNGRep> image_reps;
-    image_reps.push_back(gfx::ImagePNGRep(entry->screenshot(),
-          ui::GetScaleFactorForNativeView(web_contents_window())));
-    image_ = gfx::Image(image_reps);
-    if (image_.AsImageSkia().size() != web_contents_window()->bounds().size())
-      image_ = gfx::Image();
-  }
-
-  bool has_screenshot() const { return !image_.IsEmpty(); }
-
-  void set_show_shadow(bool show) {
-    show_shadow_ = show;
+    gfx::Image image;
+    if (entry && entry->screenshot()) {
+      std::vector<gfx::ImagePNGRep> image_reps;
+      image_reps.push_back(gfx::ImagePNGRep(entry->screenshot(),
+            ui::GetScaleFactorForNativeView(web_contents_window())));
+      image = gfx::Image(image_reps);
+    }
+    SetImage(image);
   }
 
   void stop_forwarding_events() { forward_events_ = false; }
@@ -139,94 +132,6 @@
     return web_contents_->GetView()->GetContentNativeView();
   }
 
-  // aura::WindowDelegate implementation:
-  virtual gfx::Size GetMinimumSize() const OVERRIDE {
-    return gfx::Size();
-  }
-
-  virtual gfx::Size GetMaximumSize() const OVERRIDE {
-    return gfx::Size();
-  }
-
-  virtual void OnBoundsChanged(const gfx::Rect& old_bounds,
-                               const gfx::Rect& new_bounds) OVERRIDE {
-  }
-
-  virtual gfx::NativeCursor GetCursor(const gfx::Point& point) OVERRIDE {
-    return gfx::kNullCursor;
-  }
-
-  virtual int GetNonClientComponent(const gfx::Point& point) const OVERRIDE {
-    return HTNOWHERE;
-  }
-
-  virtual bool ShouldDescendIntoChildForEventHandling(
-      aura::Window* child,
-      const gfx::Point& location) OVERRIDE {
-    return false;
-  }
-
-  virtual bool CanFocus() OVERRIDE {
-    return false;
-  }
-
-  virtual void OnCaptureLost() OVERRIDE {
-  }
-
-  virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE {
-    if (show_shadow_) {
-      canvas->Save();
-      canvas->Translate(gfx::Vector2d(kShadowThick, 0));
-    }
-    if (image_.IsEmpty())
-      canvas->DrawColor(SK_ColorGRAY);
-    else
-      canvas->DrawImageInt(image_.AsImageSkia(), 0, 0);
-
-    if (show_shadow_) {
-      canvas->Restore();
-      SkPoint points[2];
-      points[0].iset(0, 0);
-      points[1].iset(kShadowThick, 0);
-      SkColor colors[2] = { kShadowLightColor, kShadowDarkColor };
-      skia::RefPtr<SkShader> shader = skia::AdoptRef(
-          SkGradientShader::CreateLinear(points, colors, NULL,
-              arraysize(points), SkShader::kRepeat_TileMode, NULL));
-
-      SkRect rect = { SkIntToScalar(0),
-                      SkIntToScalar(0),
-                      SkIntToScalar(kShadowThick),
-                      SkIntToScalar(web_contents_window()->bounds().height()) };
-      SkPaint paint;
-      paint.setShader(shader.get());
-      canvas->sk_canvas()->drawRect(rect, paint);
-    }
-  }
-
-  virtual void OnDeviceScaleFactorChanged(float device_scale_factor) OVERRIDE {
-  }
-
-  virtual void OnWindowDestroying() OVERRIDE {
-  }
-
-  virtual void OnWindowDestroyed() OVERRIDE {
-    delete this;
-  }
-
-  virtual void OnWindowTargetVisibilityChanged(bool visible) OVERRIDE {
-  }
-
-  virtual bool HasHitTestMask() const OVERRIDE {
-    return false;
-  }
-
-  virtual void GetHitTestMask(gfx::Path* mask) const OVERRIDE {
-  }
-
-  virtual scoped_refptr<ui::Texture> CopyTexture() OVERRIDE {
-    return scoped_refptr<ui::Texture>();
-  }
-
   // Overridden from ui::EventHandler.
   virtual void OnScrollEvent(ui::ScrollEvent* event) OVERRIDE {
     if (forward_events_ && web_contents_window())
@@ -239,8 +144,6 @@
   }
 
   WebContents* web_contents_;
-  gfx::Image image_;
-  bool show_shadow_;
 
   // The window is displayed both during the gesture, and after the gesture
   // while the navigation is in progress. During the gesture, it is necessary to
@@ -255,19 +158,20 @@
 
 // Listens to all mouse drag events during a drag and drop and sends them to
 // the renderer.
-class WebDragSourceAura : public MessageLoopForUI::Observer,
+class WebDragSourceAura : public base::MessageLoopForUI::Observer,
                           public NotificationObserver {
  public:
   WebDragSourceAura(aura::Window* window, WebContentsImpl* contents)
       : window_(window),
         contents_(contents) {
-    MessageLoopForUI::current()->AddObserver(this);
-    registrar_.Add(this, NOTIFICATION_WEB_CONTENTS_DISCONNECTED,
+    base::MessageLoopForUI::current()->AddObserver(this);
+    registrar_.Add(this,
+                   NOTIFICATION_WEB_CONTENTS_DISCONNECTED,
                    Source<WebContents>(contents));
   }
 
   virtual ~WebDragSourceAura() {
-    MessageLoopForUI::current()->RemoveObserver(this);
+    base::MessageLoopForUI::current()->RemoveObserver(this);
   }
 
   // MessageLoop::Observer implementation:
@@ -291,7 +195,7 @@
           aura::Window* window = rvh->GetView()->GetNativeView();
           aura::Window::ConvertPointToTarget(window->GetRootWindow(),
               window, &client_loc);
-          rvh->DragSourceMovedTo(client_loc.x(), client_loc.y(),
+          contents_->DragSourceMovedTo(client_loc.x(), client_loc.y(),
               screen_loc.x(), screen_loc.y());
         }
         break;
@@ -446,142 +350,6 @@
 
 }  // namespace
 
-// ShadowWindow is used to paint shadows around a content window.
-// A ShadowWindow destroys itself when the content window is destroyed, and
-// updates its bounds to make sure the shadows are painted in the correct size.
-class ShadowWindow : public aura::Window,
-                     public aura::WindowObserver {
- public:
-  explicit ShadowWindow(aura::Window* window)
-      : aura::Window(NULL),
-        window_(window),
-        edge_(SHADOW_NONE) {
-    SetType(aura::client::WINDOW_TYPE_CONTROL);
-    SetTransparent(true);
-    set_owned_by_parent(false);
-    Init(ui::LAYER_NOT_DRAWN);
-    layer()->SetMasksToBounds(false);
-
-    AddChild(window);
-    window_->AddObserver(this);
-
-    SetBounds(gfx::Rect(window->bounds().size()));
-    Show();
-  }
-
-  void SetShadowEdge(ShadowEdge edge) {
-    edge_ = edge;
-    if (edge_ == SHADOW_NONE) {
-      shadow_.reset();
-      return;
-    }
-
-    shadow_.reset(new ui::Layer(ui::LAYER_TEXTURED));
-    shadow_->set_delegate(this);
-    shadow_->SetFillsBoundsOpaquely(false);
-    layer()->Add(shadow_.get());
-    layer()->StackBelow(shadow_.get(), window_->layer());
-    UpdateShadowBounds();
-  }
-
- private:
-  friend class base::DeleteHelper<content::ShadowWindow>;
-
-  virtual ~ShadowWindow() {
-  }
-
-  void UpdateShadowBounds() {
-    if (!shadow_.get())
-      return;
-    gfx::Rect bound;
-    switch (edge_) {
-      case SHADOW_LEFT:
-        bound.SetRect(-kShadowThick, 0, kShadowThick, bounds().height());
-        break;
-      case SHADOW_RIGHT:
-        bound.SetRect(bounds().right(), 0, kShadowThick, bounds().height());
-        break;
-      case SHADOW_TOP:
-        bound.SetRect(0, -kShadowThick, bounds().width(), kShadowThick);
-        break;
-      case SHADOW_BOTTOM:
-        bound.SetRect(0, bounds().bottom(), bounds().width(), kShadowThick);
-        break;
-      case SHADOW_NONE:
-        NOTREACHED();
-    }
-    shadow_->SetBounds(bound);
-  }
-
-  // Overridden from aura::WindowObserver:
-  virtual void OnWindowBoundsChanged(Window* window,
-                                     const gfx::Rect& old_bounds,
-                                     const gfx::Rect& new_bounds) OVERRIDE {
-    SetBounds(gfx::Rect(new_bounds.size()));
-    UpdateShadowBounds();
-  }
-
-  virtual void OnWindowDestroying(aura::Window* window) OVERRIDE {
-    DCHECK_EQ(window, window_);
-    window_->RemoveObserver(this);
-    window_ = NULL;
-    MessageLoop::current()->DeleteSoon(FROM_HERE, this);
-  }
-
-  // Overridden from ui::LayerDelegate:
-  virtual void OnPaintLayer(gfx::Canvas* canvas) OVERRIDE {
-    SkPoint points[2];
-    SkColor colors[2];
-
-    points[0].iset(0, 0);
-    switch (edge_) {
-      case SHADOW_LEFT:
-      case SHADOW_RIGHT:
-        points[1].iset(shadow_->bounds().width(), 0);
-        break;
-
-      case SHADOW_TOP:
-      case SHADOW_BOTTOM:
-        points[1].iset(0, shadow_->bounds().height());
-        break;
-
-      default:
-        NOTREACHED();
-    }
-
-    switch (edge_) {
-      case SHADOW_LEFT:
-      case SHADOW_TOP:
-        colors[0] = kShadowLightColor;
-        colors[1] = kShadowDarkColor;
-        break;
-
-      case SHADOW_RIGHT:
-      case SHADOW_BOTTOM:
-        colors[0] = kShadowDarkColor;
-        colors[1] = kShadowLightColor;
-        break;
-
-      default:
-        NOTREACHED();
-    }
-
-    skia::RefPtr<SkShader> shader = skia::AdoptRef(
-        SkGradientShader::CreateLinear(points, colors, NULL,
-            arraysize(points), SkShader::kRepeat_TileMode, NULL));
-
-    SkPaint paint;
-    paint.setShader(shader.get());
-    canvas->sk_canvas()->drawRect(gfx::RectToSkRect(bounds()), paint);
-  }
-
-  aura::Window* window_;
-  scoped_ptr<ui::Layer> shadow_;
-  ShadowEdge edge_;
-
-  DISALLOW_COPY_AND_ASSIGN(ShadowWindow);
-};
-
 // When a history navigation is triggered at the end of an overscroll
 // navigation, it is necessary to show the history-screenshot until the page is
 // done navigating and painting. This class accomplishes this by showing the
@@ -614,7 +382,8 @@
     received_paint_update_ = false;
     compositor_updated_ = false;
     view_ = view;
-    view_->set_paint_observer(this);
+    if (view_)
+      view_->set_paint_observer(this);
 
     // Make sure the overlay window is on top.
     if (window_.get() && window_->parent())
@@ -727,6 +496,8 @@
                                      const gfx::Rect& old_bounds,
                                      const gfx::Rect& new_bounds) OVERRIDE {
     SendScreenRects();
+    if (view_->touch_editable_)
+      view_->touch_editable_->UpdateEditingController();
   }
 
   virtual void OnWindowAddedToRootWindow(aura::Window* window) OVERRIDE {
@@ -788,16 +559,22 @@
     // We also start watching them to know when their size is updated. Of
     // course, ignore the shadow window that contains the RWHV and child windows
     // of the child windows that we are watching.
+    RenderWidgetHostViewAura* view = ToRenderWidgetHostViewAura(
+        view_->web_contents_->GetRenderWidgetHostView());
+    aura::Window* content_window = view ? view->GetNativeView() : NULL;
     if (new_window->parent() == view_->window_ &&
-        new_window != view_->content_container_) {
+        new_window != content_window) {
       new_window->AddObserver(this);
       UpdateConstrainedWindows(NULL);
     }
   }
 
   virtual void OnWillRemoveWindow(aura::Window* window) OVERRIDE {
+    RenderWidgetHostViewAura* view = ToRenderWidgetHostViewAura(
+        view_->web_contents_->GetRenderWidgetHostView());
+    aura::Window* content_window = view ? view->GetNativeView() : NULL;
     if (window->parent() == view_->window_ &&
-        window != view_->content_container_) {
+        window != content_window) {
       window->RemoveObserver(this);
       UpdateConstrainedWindows(window);
     }
@@ -807,7 +584,7 @@
                                      const gfx::Rect& old_bounds,
                                      const gfx::Rect& new_bounds) OVERRIDE {
     if (window->parent() == view_->window_ &&
-        window != view_->content_container_) {
+        window != view_->GetContentNativeView()) {
       UpdateConstrainedWindows(NULL);
     }
   }
@@ -819,21 +596,19 @@
 
  private:
   void UpdateConstrainedWindows(aura::Window* exclude) {
-    if (RenderViewHostFactory::has_factory())
-      return;  // Can't cast to RenderWidgetHostViewAura in unit tests.
-
     if (web_contents_destroyed_)
       return;
 
-    RenderWidgetHostViewAura* view = static_cast<RenderWidgetHostViewAura*>(
+    RenderWidgetHostViewAura* view = ToRenderWidgetHostViewAura(
         view_->web_contents_->GetRenderWidgetHostView());
     if (!view)
       return;
 
     std::vector<gfx::Rect> constrained_windows;
     const aura::Window::Windows& children = view_->window_->children();
+    aura::Window* content = view_->GetContentNativeView();
     for (size_t i = 0; i < children.size(); ++i) {
-      if (children[i] != view_->content_container_ && children[i] != exclude)
+      if (children[i] != content && children[i] != exclude)
         constrained_windows.push_back(children[i]->GetBoundsInRootWindow());
     }
 
@@ -858,10 +633,10 @@
       current_drag_op_(WebKit::WebDragOperationNone),
       drag_dest_delegate_(NULL),
       current_rvh_for_drag_(NULL),
-      content_container_(NULL),
       overscroll_change_brightness_(false),
       current_overscroll_gesture_(OVERSCROLL_NONE),
-      completed_overscroll_gesture_(OVERSCROLL_NONE) {
+      completed_overscroll_gesture_(OVERSCROLL_NONE),
+      touch_editable_(TouchEditableImplAura::Create()) {
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -881,10 +656,16 @@
 }
 
 void WebContentsViewAura::SetupOverlayWindowForTesting() {
-  if (navigation_overlay_.get())
+  if (navigation_overlay_)
     navigation_overlay_->SetupForTesting();
 }
 
+void WebContentsViewAura::SetTouchEditableForTest(
+    TouchEditableImplAura* touch_editable) {
+  touch_editable_.reset(touch_editable);
+  AttachTouchEditableToRenderView();
+}
+
 void WebContentsViewAura::SizeChangedCommon(const gfx::Size& size) {
   if (web_contents_->GetInterstitialPage())
     web_contents_->GetInterstitialPage()->SetSize(size);
@@ -902,8 +683,10 @@
   RenderViewHost* rvh = web_contents_->GetRenderViewHost();
   aura::Window* window = rvh->GetView()->GetNativeView();
   aura::Window::ConvertPointToTarget(root_window, window, &client_loc);
-  rvh->DragSourceEndedAt(client_loc.x(), client_loc.y(), screen_loc.x(),
-      screen_loc.y(), ops);
+  if (!web_contents_)
+    return;
+  web_contents_->DragSourceEndedAt(client_loc.x(), client_loc.y(),
+      screen_loc.x(), screen_loc.y(), ops);
 }
 
 void WebContentsViewAura::PrepareOverscrollWindow() {
@@ -912,7 +695,7 @@
   // completed immidiately, which triggers |OnImplicitAnimationsCompleted()|
   // callback, and that tries to reset |overscroll_window_| again, causing a
   // double-free. So use a temporary variable here.
-  if (overscroll_window_.get()) {
+  if (overscroll_window_) {
     base::AutoReset<OverscrollMode> reset_state(&current_overscroll_gesture_,
                                                 current_overscroll_gesture_);
     scoped_ptr<aura::Window> reset_window(overscroll_window_.release());
@@ -925,10 +708,10 @@
   overscroll_window_->SetType(aura::client::WINDOW_TYPE_CONTROL);
   overscroll_window_->SetTransparent(true);
   overscroll_window_->Init(ui::LAYER_TEXTURED);
-  overscroll_window_->layer()->SetMasksToBounds(true);
+  overscroll_window_->layer()->SetMasksToBounds(false);
   overscroll_window_->SetName("OverscrollOverlay");
 
-  overscroll_change_brightness_ = overscroll_delegate->has_screenshot();
+  overscroll_change_brightness_ = overscroll_delegate->has_image();
   window_->AddChild(overscroll_window_.get());
 
   gfx::Rect bounds = gfx::Rect(window_->bounds().size());
@@ -940,46 +723,22 @@
     bounds.Offset(base::i18n::IsRTL() ? -bounds.width() : bounds.width(), 0);
   }
 
-  if (GetWindowToAnimateForOverscroll() == overscroll_window_.get()) {
-    overscroll_delegate->set_show_shadow(true);
-    window_->StackChildAbove(overscroll_window_.get(), content_container_);
-  } else {
-    window_->StackChildBelow(overscroll_window_.get(), content_container_);
-
-    switch (current_overscroll_gesture_) {
-      case OVERSCROLL_EAST:
-        content_container_->SetShadowEdge(SHADOW_LEFT);
-        break;
-
-      case OVERSCROLL_WEST:
-        content_container_->SetShadowEdge(SHADOW_RIGHT);
-        break;
-
-      case OVERSCROLL_NORTH:
-        content_container_->SetShadowEdge(SHADOW_BOTTOM);
-        break;
-
-      case OVERSCROLL_SOUTH:
-        content_container_->SetShadowEdge(SHADOW_TOP);
-        break;
-
-      case OVERSCROLL_NONE:
-      case OVERSCROLL_COUNT:
-        NOTREACHED();
-    }
-  }
+  aura::Window* animate_window = GetWindowToAnimateForOverscroll();
+  if (animate_window == overscroll_window_)
+    window_->StackChildAbove(overscroll_window_.get(), GetContentNativeView());
+  else
+    window_->StackChildBelow(overscroll_window_.get(), GetContentNativeView());
 
   UpdateOverscrollWindowBrightness(0.f);
 
   overscroll_window_->SetBounds(bounds);
   overscroll_window_->Show();
+
+  overscroll_shadow_.reset(new ShadowLayerDelegate(animate_window));
 }
 
 void WebContentsViewAura::PrepareContentWindowForOverscroll() {
-  DCHECK(content_container_);
-  DCHECK_EQ(content_container_, GetContentNativeView()->parent());
-
-  aura::Window* content = content_container_;
+  aura::Window* content = GetContentNativeView();
   ui::ScopedLayerAnimationSettings settings(content->layer()->GetAnimator());
   settings.SetPreemptionStrategy(ui::LayerAnimator::IMMEDIATELY_SET_NEW_TARGET);
   content->SetTransform(gfx::Transform());
@@ -1043,7 +802,7 @@
 
   return ShouldNavigateForward(web_contents_->GetController(),
                                current_overscroll_gesture_) ?
-      overscroll_window_.get() : content_container_;
+      overscroll_window_.get() : GetContentNativeView();
 }
 
 gfx::Vector2d WebContentsViewAura::GetTranslationForOverscroll(int delta_x,
@@ -1069,14 +828,13 @@
 void WebContentsViewAura::PrepareOverscrollNavigationOverlay() {
   OverscrollWindowDelegate* delegate = static_cast<OverscrollWindowDelegate*>(
       overscroll_window_->delegate());
-  delegate->set_show_shadow(false);
   delegate->stop_forwarding_events();
   overscroll_window_->SchedulePaintInRect(
       gfx::Rect(overscroll_window_->bounds().size()));
   navigation_overlay_->SetOverlayWindow(overscroll_window_.Pass(),
-                                        delegate->has_screenshot());
-  navigation_overlay_->StartObservingView(static_cast<
-      RenderWidgetHostViewAura*>(web_contents_->GetRenderWidgetHostView()));
+                                        delegate->has_image());
+  navigation_overlay_->StartObservingView(ToRenderWidgetHostViewAura(
+      web_contents_->GetRenderWidgetHostView()));
 }
 
 void WebContentsViewAura::UpdateOverscrollWindowBrightness(float delta_x) {
@@ -1099,6 +857,14 @@
   window->layer()->SetLayerBrightness(brightness);
 }
 
+void WebContentsViewAura::AttachTouchEditableToRenderView() {
+  if (!touch_editable_)
+    return;
+  RenderWidgetHostViewAura* rwhva = ToRenderWidgetHostViewAura(
+      web_contents_->GetRenderWidgetHostView());
+  touch_editable_->AttachToView(rwhva);
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // WebContentsViewAura, WebContentsView implementation:
 
@@ -1161,12 +927,12 @@
 }
 
 void WebContentsViewAura::StoreFocus() {
-  if (delegate_.get())
+  if (delegate_)
     delegate_->StoreFocus();
 }
 
 void WebContentsViewAura::RestoreFocus() {
-  if (delegate_.get())
+  if (delegate_)
     delegate_->RestoreFocus();
 }
 
@@ -1218,7 +984,7 @@
   // delegate_->GetDragDestDelegate() creates a new delegate on every call.
   // Hence, we save a reference to it locally. Similar model is used on other
   // platforms as well.
-  if (delegate_.get())
+  if (delegate_)
     drag_dest_delegate_ = delegate_->GetDragDestDelegate();
 }
 
@@ -1237,12 +1003,10 @@
   RenderWidgetHostView* view =
       RenderWidgetHostView::CreateViewForWidget(render_widget_host);
   view->InitAsChild(NULL);
-  content_container_ = new ShadowWindow(view->GetNativeView());
-  GetNativeView()->AddChild(content_container_);
+  GetNativeView()->AddChild(view->GetNativeView());
 
   if (navigation_overlay_.get() && navigation_overlay_->has_window()) {
-    navigation_overlay_->StartObservingView(static_cast<
-        RenderWidgetHostViewAura*>(view));
+    navigation_overlay_->StartObservingView(ToRenderWidgetHostViewAura(view));
   }
 
   view->Show();
@@ -1256,10 +1020,11 @@
       (!web_contents_->GetDelegate() ||
        web_contents_->GetDelegate()->CanOverscrollContent())) {
     host_impl->overscroll_controller()->set_delegate(this);
-    if (!navigation_overlay_.get())
+    if (!navigation_overlay_)
       navigation_overlay_.reset(new OverscrollNavigationOverlay());
   }
 
+  AttachTouchEditableToRenderView();
   return view;
 }
 
@@ -1277,9 +1042,10 @@
 
 void WebContentsViewAura::RenderViewSwappedIn(RenderViewHost* host) {
   if (navigation_overlay_.get() && navigation_overlay_->has_window()) {
-    navigation_overlay_->StartObservingView(static_cast<
-        RenderWidgetHostViewAura*>(host->GetView()));
+    navigation_overlay_->StartObservingView(
+        ToRenderWidgetHostViewAura(host->GetView()));
   }
+  AttachTouchEditableToRenderView();
 }
 
 void WebContentsViewAura::SetOverscrollControllerEnabled(bool enabled) {
@@ -1298,8 +1064,11 @@
 void WebContentsViewAura::ShowContextMenu(
     const ContextMenuParams& params,
     ContextMenuSourceType type) {
-  if (delegate_.get())
+  if (delegate_)
     delegate_->ShowContextMenu(params, type);
+  if (touch_editable_)
+    touch_editable_->EndTouchEditing();
+
 }
 
 void WebContentsViewAura::ShowPopupMenu(const gfx::Rect& bounds,
@@ -1320,8 +1089,13 @@
     const gfx::Vector2d& image_offset,
     const DragEventSourceInfo& event_info) {
   aura::RootWindow* root_window = GetNativeView()->GetRootWindow();
-  if (!aura::client::GetDragDropClient(root_window))
+  if (!aura::client::GetDragDropClient(root_window)) {
+    web_contents_->SystemDragEnded();
     return;
+  }
+
+  if (touch_editable_)
+    touch_editable_->EndTouchEditing();
 
   ui::OSExchangeData::Provider* provider = ui::OSExchangeData::CreateProvider();
   PrepareDragData(drop_data, provider);
@@ -1341,23 +1115,29 @@
   int result_op = 0;
   {
     gfx::NativeView content_native_view = GetContentNativeView();
-    MessageLoop::ScopedNestableTaskAllower allow(MessageLoop::current());
-    result_op = aura::client::GetDragDropClient(root_window)->StartDragAndDrop(
-        data, root_window, content_native_view,
-        event_info.event_location, ConvertFromWeb(operations),
-        event_info.event_source);
+    base::MessageLoop::ScopedNestableTaskAllower allow(
+        base::MessageLoop::current());
+    result_op = aura::client::GetDragDropClient(root_window)
+        ->StartDragAndDrop(data,
+                           root_window,
+                           content_native_view,
+                           event_info.event_location,
+                           ConvertFromWeb(operations),
+                           event_info.event_source);
   }
 
   // Bail out immediately if the contents view window is gone. Note that it is
-  // not safe to access any class members after system drag-and-drop returns
-  // since the class instance might be gone. The local variable |drag_source|
-  // is still valid and we can check its window property that is set to NULL
-  // when the contents are gone.
-  if (!drag_source->window())
+  // not safe to access any class members in this case since |this| may already
+  // be destroyed. The local variable |drag_source| will still be valid though,
+  // so we can use it to determine if the window is gone.
+  if (!drag_source->window()) {
+    // Note that in this case, we don't need to call SystemDragEnded() since the
+    // renderer is going away.
     return;
+  }
 
   EndDrag(ConvertToWeb(result_op));
-  web_contents_->GetRenderViewHost()->DragSourceSystemDragEnded();
+  web_contents_->SystemDragEnded();
 }
 
 void WebContentsViewAura::UpdateDragCursor(WebKit::WebDragOperation operation) {
@@ -1413,15 +1193,8 @@
   // Reset any in-progress overscroll animation first.
   ResetOverscrollTransform();
 
-  // Make sure the content window has been prepared correctly before allowing
-  // overscroll.
-  bool content_window_ready =
-      content_container_ &&
-      GetContentNativeView() &&
-      GetContentNativeView()->parent() == content_container_;
-
   if (new_mode == OVERSCROLL_NONE ||
-      !content_window_ready ||
+      !GetContentNativeView() ||
       (navigation_overlay_.get() && navigation_overlay_->has_window())) {
     current_overscroll_gesture_ = OVERSCROLL_NONE;
   } else {
@@ -1441,6 +1214,8 @@
 // WebContentsViewAura, ui::ImplicitAnimationObserver implementation:
 
 void WebContentsViewAura::OnImplicitAnimationsCompleted() {
+  overscroll_shadow_.reset();
+
   if (ShouldNavigateForward(web_contents_->GetController(),
                             completed_overscroll_gesture_)) {
     PrepareOverscrollNavigationOverlay();
@@ -1451,10 +1226,10 @@
     web_contents_->GetController().GoBack();
   }
 
-  if (GetContentNativeView()) {
-    content_container_->SetTransform(gfx::Transform());
-    content_container_->layer()->SetLayerBrightness(0.f);
-    content_container_->SetShadowEdge(SHADOW_NONE);
+  aura::Window* content = GetContentNativeView();
+  if (content) {
+    content->SetTransform(gfx::Transform());
+    content->layer()->SetLayerBrightness(0.f);
   }
   current_overscroll_gesture_ = OVERSCROLL_NONE;
   completed_overscroll_gesture_ = OVERSCROLL_NONE;
@@ -1475,7 +1250,7 @@
 void WebContentsViewAura::OnBoundsChanged(const gfx::Rect& old_bounds,
                                           const gfx::Rect& new_bounds) {
   SizeChangedCommon(new_bounds.size());
-  if (delegate_.get())
+  if (delegate_)
     delegate_->SizeChanged(new_bounds.size());
 
   // Constrained web dialogs, need to be kept centered over our content area.
diff --git a/content/browser/web_contents/web_contents_view_aura.h b/content/browser/web_contents/web_contents_view_aura.h
index f619352..54425e2 100644
--- a/content/browser/web_contents/web_contents_view_aura.h
+++ b/content/browser/web_contents/web_contents_view_aura.h
@@ -27,7 +27,8 @@
 
 namespace content {
 class OverscrollNavigationOverlay;
-class ShadowWindow;
+class ShadowLayerDelegate;
+class TouchEditableImplAura;
 class WebContentsViewDelegate;
 class WebContentsImpl;
 class WebDragDestDelegate;
@@ -45,6 +46,8 @@
 
   void SetupOverlayWindowForTesting();
 
+  void SetTouchEditableForTest(TouchEditableImplAura* touch_editable);
+
  private:
   class WindowObserver;
 #if defined(OS_WIN)
@@ -92,6 +95,8 @@
   // overscroll (|delta_x|, in pixels).
   void UpdateOverscrollWindowBrightness(float delta_x);
 
+  void AttachTouchEditableToRenderView();
+
   // Overridden from WebContentsView:
   virtual gfx::NativeView GetNativeView() const OVERRIDE;
   virtual gfx::NativeView GetContentNativeView() const OVERRIDE;
@@ -207,10 +212,6 @@
   // pointers.
   void* current_rvh_for_drag_;
 
-  // The container for the content-window. The doc for ShadowWindow explains its
-  // lifetime and ownership.
-  ShadowWindow* content_container_;
-
   bool overscroll_change_brightness_;
 
   // The overscroll gesture currently in progress.
@@ -224,6 +225,10 @@
   // navigation triggered by the overscroll gesture.
   scoped_ptr<OverscrollNavigationOverlay> navigation_overlay_;
 
+  scoped_ptr<ShadowLayerDelegate> overscroll_shadow_;
+
+  scoped_ptr<TouchEditableImplAura> touch_editable_;
+
   DISALLOW_COPY_AND_ASSIGN(WebContentsViewAura);
 };
 
diff --git a/content/browser/web_contents/web_contents_view_aura_browsertest.cc b/content/browser/web_contents/web_contents_view_aura_browsertest.cc
index 476bec6..a5cdf57 100644
--- a/content/browser/web_contents/web_contents_view_aura_browsertest.cc
+++ b/content/browser/web_contents/web_contents_view_aura_browsertest.cc
@@ -13,6 +13,7 @@
 #include "content/browser/web_contents/navigation_controller_impl.h"
 #include "content/browser/web_contents/navigation_entry_impl.h"
 #include "content/browser/web_contents/web_contents_impl.h"
+#include "content/browser/web_contents/web_contents_screenshot_manager.h"
 #include "content/public/browser/web_contents_view.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/test/browser_test_utils.h"
@@ -27,24 +28,16 @@
 
 namespace content {
 
-// A dummy callback to reset the screenshot-taker callback.
-void DummyCallback(RenderViewHost* host) {
-}
-
 // This class keeps track of the RenderViewHost whose screenshot was captured.
-class ScreenshotTracker {
+class ScreenshotTracker : public WebContentsScreenshotManager {
  public:
   explicit ScreenshotTracker(NavigationControllerImpl* controller)
-      : screenshot_taken_for_(NULL),
-        controller_(controller) {
-    controller_->SetTakeScreenshotCallbackForTest(
-        base::Bind(&ScreenshotTracker::TakeScreenshotCallback,
-                   base::Unretained(this)));
+      : WebContentsScreenshotManager(controller),
+        screenshot_taken_for_(NULL),
+        waiting_for_screenshots_(0) {
   }
 
   virtual ~ScreenshotTracker() {
-    controller_->SetTakeScreenshotCallbackForTest(
-        base::Bind(&DummyCallback));
   }
 
   RenderViewHost* screenshot_taken_for() { return screenshot_taken_for_; }
@@ -53,20 +46,45 @@
     screenshot_taken_for_ = NULL;
   }
 
+  void SetScreenshotInterval(int interval_ms) {
+    SetMinScreenshotIntervalMS(interval_ms);
+  }
+
+  void WaitUntilScreenshotIsReady() {
+    if (!waiting_for_screenshots_)
+      return;
+    message_loop_runner_ = new content::MessageLoopRunner;
+    message_loop_runner_->Run();
+  }
+
  private:
-  void TakeScreenshotCallback(RenderViewHost* host) {
+  // Overridden from WebContentsScreenshotManager:
+  virtual void TakeScreenshotImpl(RenderViewHost* host,
+                                  NavigationEntryImpl* entry) OVERRIDE {
+    ++waiting_for_screenshots_;
     screenshot_taken_for_ = host;
+    WebContentsScreenshotManager::TakeScreenshotImpl(host, entry);
+  }
+
+  virtual void OnScreenshotSet(NavigationEntryImpl* entry) OVERRIDE {
+    --waiting_for_screenshots_;
+    WebContentsScreenshotManager::OnScreenshotSet(entry);
+    if (waiting_for_screenshots_ == 0 && message_loop_runner_)
+      message_loop_runner_->Quit();
   }
 
   RenderViewHost* screenshot_taken_for_;
-  NavigationControllerImpl* controller_;
+  scoped_refptr<content::MessageLoopRunner> message_loop_runner_;
+  int waiting_for_screenshots_;
 
   DISALLOW_COPY_AND_ASSIGN(ScreenshotTracker);
 };
 
 class WebContentsViewAuraTest : public ContentBrowserTest {
  public:
-  WebContentsViewAuraTest() {}
+  WebContentsViewAuraTest()
+      : screenshot_manager_(NULL) {
+  }
 
   // Executes the javascript synchronously and makes sure the returned value is
   // freed properly.
@@ -85,6 +103,13 @@
     aura::Window* content =
         shell()->web_contents()->GetView()->GetContentNativeView();
     content->GetRootWindow()->SetHostSize(gfx::Size(800, 600));
+
+    WebContentsImpl* web_contents =
+        static_cast<WebContentsImpl*>(shell()->web_contents());
+    NavigationControllerImpl* controller = &web_contents->GetController();
+
+    screenshot_manager_ = new ScreenshotTracker(controller);
+    controller->SetScreenshotManager(screenshot_manager_);
   }
 
   void TestOverscrollNavigation(bool touch_handler) {
@@ -190,7 +215,15 @@
     return index;
   }
 
+ protected:
+  ScreenshotTracker* screenshot_manager() { return screenshot_manager_; }
+  void set_min_screenshot_interval(int interval_ms) {
+    screenshot_manager_->SetScreenshotInterval(interval_ms);
+  }
+
  private:
+  ScreenshotTracker* screenshot_manager_;
+
   DISALLOW_COPY_AND_ASSIGN(WebContentsViewAuraTest);
 };
 
@@ -299,11 +332,14 @@
   RenderViewHostImpl* view_host = static_cast<RenderViewHostImpl*>(
       web_contents->GetRenderViewHost());
 
+  set_min_screenshot_interval(0);
+
   // Do a few navigations initiated by the page.
   ExecuteSyncJSFunction(view_host, "navigate_next()");
   EXPECT_EQ(1, GetCurrentIndex());
   ExecuteSyncJSFunction(view_host, "navigate_next()");
   EXPECT_EQ(2, GetCurrentIndex());
+  screenshot_manager()->WaitUntilScreenshotIsReady();
 
   // The current entry won't have any screenshots. But the entries in the
   // history should now have screenshots.
@@ -322,6 +358,7 @@
   // Navigate again. Index 2 should now have a screenshot.
   ExecuteSyncJSFunction(view_host, "navigate_next()");
   EXPECT_EQ(3, GetCurrentIndex());
+  screenshot_manager()->WaitUntilScreenshotIsReady();
 
   entry = NavigationEntryImpl::FromNavigationEntry(
       web_contents->GetController().GetEntryAtIndex(2));
@@ -347,6 +384,7 @@
     string16 actual_title = title_watcher.WaitAndGetTitle();
     EXPECT_EQ(expected_title, actual_title);
     EXPECT_EQ(2, GetCurrentIndex());
+    screenshot_manager()->WaitUntilScreenshotIsReady();
     entry = NavigationEntryImpl::FromNavigationEntry(
         web_contents->GetController().GetEntryAtIndex(3));
     EXPECT_TRUE(entry->screenshot().get());
@@ -357,6 +395,7 @@
   EXPECT_EQ(3, GetCurrentIndex());
   ExecuteSyncJSFunction(view_host, "navigate_next()");
   EXPECT_EQ(4, GetCurrentIndex());
+  screenshot_manager()->WaitUntilScreenshotIsReady();
   entry = NavigationEntryImpl::FromNavigationEntry(
       web_contents->GetController().GetEntryAtIndex(4));
   EXPECT_FALSE(entry->screenshot().get());
@@ -369,6 +408,7 @@
     string16 actual_title = title_watcher.WaitAndGetTitle();
     EXPECT_EQ(expected_title, actual_title);
     EXPECT_EQ(3, GetCurrentIndex());
+    screenshot_manager()->WaitUntilScreenshotIsReady();
     entry = NavigationEntryImpl::FromNavigationEntry(
         web_contents->GetController().GetEntryAtIndex(4));
     EXPECT_TRUE(entry->screenshot().get());
@@ -382,14 +422,15 @@
   ASSERT_NO_FATAL_FAILURE(
       StartTestWithPage("files/overscroll_navigation.html"));
   // Create a new server with a different site.
-  net::TestServer https_server(
-      net::TestServer::TYPE_HTTPS,
-      net::TestServer::kLocalhost,
+  net::SpawnedTestServer https_server(
+      net::SpawnedTestServer::TYPE_HTTPS,
+      net::SpawnedTestServer::kLocalhost,
       base::FilePath(FILE_PATH_LITERAL("content/test/data")));
   ASSERT_TRUE(https_server.Start());
 
   WebContentsImpl* web_contents =
       static_cast<WebContentsImpl*>(shell()->web_contents());
+  set_min_screenshot_interval(0);
 
   struct {
     GURL url;
@@ -404,7 +445,7 @@
     { GURL(), 0 }
   };
 
-  ScreenshotTracker tracker(&web_contents->GetController());
+  screenshot_manager()->Reset();
   for (int i = 0; !navigations[i].url.is_empty(); ++i) {
     // Navigate via the user initiating a navigation from the UI.
     NavigationController::LoadURLParams params(navigations[i].url);
@@ -413,11 +454,12 @@
     RenderViewHost* old_host = web_contents->GetRenderViewHost();
     web_contents->GetController().LoadURLWithParams(params);
     WaitForLoadStop(web_contents);
+    screenshot_manager()->WaitUntilScreenshotIsReady();
 
     EXPECT_NE(old_host, web_contents->GetRenderViewHost())
         << navigations[i].url.spec();
-    EXPECT_EQ(old_host, tracker.screenshot_taken_for());
-    tracker.Reset();
+    EXPECT_EQ(old_host, screenshot_manager()->screenshot_taken_for());
+    screenshot_manager()->Reset();
 
     NavigationEntryImpl* entry = NavigationEntryImpl::FromNavigationEntry(
         web_contents->GetController().GetEntryAtOffset(-1));
@@ -427,6 +469,66 @@
         web_contents->GetController().GetActiveEntry());
     EXPECT_FALSE(entry->screenshot().get());
   }
+
+  // Increase the minimum interval between taking screenshots.
+  set_min_screenshot_interval(60000);
+
+  // Navigate again. This should not take any screenshot because of the
+  // increased screenshot interval.
+  NavigationController::LoadURLParams params(navigations[0].url);
+  params.transition_type = PageTransitionFromInt(navigations[0].transition);
+  web_contents->GetController().LoadURLWithParams(params);
+  WaitForLoadStop(web_contents);
+  screenshot_manager()->WaitUntilScreenshotIsReady();
+
+  EXPECT_EQ(NULL, screenshot_manager()->screenshot_taken_for());
+}
+
+IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest,
+                       ContentWindowReparent) {
+  ASSERT_NO_FATAL_FAILURE(
+      StartTestWithPage("files/overscroll_navigation.html"));
+
+  scoped_ptr<aura::Window> window(new aura::Window(NULL));
+  window->Init(ui::LAYER_NOT_DRAWN);
+
+  WebContentsImpl* web_contents =
+      static_cast<WebContentsImpl*>(shell()->web_contents());
+  ExecuteSyncJSFunction(web_contents->GetRenderViewHost(), "navigate_next()");
+  EXPECT_EQ(1, GetCurrentIndex());
+
+  aura::Window* content = web_contents->GetView()->GetContentNativeView();
+  gfx::Rect bounds = content->GetBoundsInRootWindow();
+  aura::test::EventGenerator generator(content->GetRootWindow(), content);
+  generator.GestureScrollSequence(
+      gfx::Point(bounds.x() + 2, bounds.y() + 10),
+      gfx::Point(bounds.right() - 10, bounds.y() + 10),
+      base::TimeDelta::FromMilliseconds(20),
+      1);
+
+  window->AddChild(shell()->web_contents()->GetView()->GetContentNativeView());
+}
+
+IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest,
+                       ContentWindowClose) {
+  ASSERT_NO_FATAL_FAILURE(
+      StartTestWithPage("files/overscroll_navigation.html"));
+
+  WebContentsImpl* web_contents =
+      static_cast<WebContentsImpl*>(shell()->web_contents());
+  ExecuteSyncJSFunction(web_contents->GetRenderViewHost(), "navigate_next()");
+  EXPECT_EQ(1, GetCurrentIndex());
+
+  aura::Window* content = web_contents->GetView()->GetContentNativeView();
+  gfx::Rect bounds = content->GetBoundsInRootWindow();
+  aura::test::EventGenerator generator(content->GetRootWindow(), content);
+  generator.GestureScrollSequence(
+      gfx::Point(bounds.x() + 2, bounds.y() + 10),
+      gfx::Point(bounds.right() - 10, bounds.y() + 10),
+      base::TimeDelta::FromMilliseconds(20),
+      1);
+
+  delete web_contents->GetView()->GetContentNativeView();
 }
 
 }  // namespace content
diff --git a/content/browser/web_contents/web_contents_view_gtk.cc b/content/browser/web_contents/web_contents_view_gtk.cc
index 4e529b4..9cb9212 100644
--- a/content/browser/web_contents/web_contents_view_gtk.cc
+++ b/content/browser/web_contents/web_contents_view_gtk.cc
@@ -100,7 +100,7 @@
   gtk_widget_show(expanded_.get());
   drag_source_.reset(new WebDragSourceGtk(web_contents));
 
-  if (delegate_.get())
+  if (delegate_)
     delegate_->Initialize(expanded_.get(), &focus_store_);
 }
 
@@ -109,7 +109,7 @@
 }
 
 gfx::NativeView WebContentsViewGtk::GetNativeView() const {
-  if (delegate_.get())
+  if (delegate_)
     return delegate_->GetNativeView();
 
   return expanded_.get();
@@ -151,7 +151,7 @@
 void WebContentsViewGtk::Focus() {
   if (web_contents_->ShowingInterstitialPage()) {
     web_contents_->GetInterstitialPage()->Focus();
-  } else if (delegate_.get()) {
+  } else if (delegate_) {
     delegate_->Focus();
   }
 }
@@ -314,7 +314,7 @@
   // Create the new drag_dest_.
   drag_dest_.reset(new WebDragDestGtk(web_contents_, content_view));
 
-  if (delegate_.get())
+  if (delegate_)
     drag_dest_->set_delegate(delegate_->GetDragDestDelegate());
 }
 
@@ -326,7 +326,7 @@
 gboolean WebContentsViewGtk::OnFocus(GtkWidget* widget,
                                      GtkDirectionType focus) {
   // Give our view wrapper first chance at this event.
-  if (delegate_.get()) {
+  if (delegate_) {
     gboolean return_value = FALSE;
     if (delegate_->OnNativeViewFocusEvent(widget, focus, &return_value))
       return return_value;
@@ -347,7 +347,7 @@
 void WebContentsViewGtk::ShowContextMenu(
     const ContextMenuParams& params,
     ContextMenuSourceType type) {
-  if (delegate_.get())
+  if (delegate_)
     delegate_->ShowContextMenu(params, type);
   else
     DLOG(ERROR) << "Cannot show context menus without a delegate.";
@@ -375,11 +375,11 @@
 
   RenderWidgetHostViewGtk* view_gtk = static_cast<RenderWidgetHostViewGtk*>(
       web_contents_->GetRenderWidgetHostView());
-  if (!view_gtk || !view_gtk->GetLastMouseDown())
-    return;
-
-  drag_source_->StartDragging(drop_data, ops, view_gtk->GetLastMouseDown(),
-                              *image.bitmap(), image_offset);
+  if (!view_gtk || !view_gtk->GetLastMouseDown() ||
+      !drag_source_->StartDragging(drop_data, ops, view_gtk->GetLastMouseDown(),
+                                   *image.bitmap(), image_offset)) {
+    web_contents_->SystemDragEnded();
+  }
 }
 
 // -----------------------------------------------------------------------------
diff --git a/content/browser/web_contents/web_contents_view_guest.cc b/content/browser/web_contents/web_contents_view_guest.cc
index 088ebfd..f6c42a9 100644
--- a/content/browser/web_contents/web_contents_view_guest.cc
+++ b/content/browser/web_contents/web_contents_view_guest.cc
@@ -5,12 +5,14 @@
 #include "content/browser/web_contents/web_contents_view_guest.h"
 
 #include "build/build_config.h"
+#include "content/browser/browser_plugin/browser_plugin_embedder.h"
 #include "content/browser/browser_plugin/browser_plugin_guest.h"
 #include "content/browser/renderer_host/render_view_host_factory.h"
 #include "content/browser/renderer_host/render_view_host_impl.h"
 #include "content/browser/renderer_host/render_widget_host_view_guest.h"
 #include "content/browser/web_contents/interstitial_page_impl.h"
 #include "content/browser/web_contents/web_contents_impl.h"
+#include "content/common/drag_messages.h"
 #include "content/public/browser/web_contents_delegate.h"
 #include "ui/gfx/image/image_skia.h"
 #include "ui/gfx/point.h"
@@ -36,7 +38,7 @@
 }
 
 gfx::NativeView WebContentsViewGuest::GetNativeView() const {
-  return NULL;
+  return platform_view_->GetNativeView();
 }
 
 gfx::NativeView WebContentsViewGuest::GetContentNativeView() const {
@@ -51,11 +53,14 @@
 }
 
 void WebContentsViewGuest::GetContainerBounds(gfx::Rect* out) const {
-  platform_view_->GetContainerBounds(out);
+  out->SetRect(0, 0, size_.width(), size_.height());
 }
 
 void WebContentsViewGuest::SizeContents(const gfx::Size& size) {
-  platform_view_->SizeContents(size);
+  size_ = size;
+  RenderWidgetHostView* rwhv = web_contents_->GetRenderWidgetHostView();
+  if (rwhv)
+    rwhv->SetSize(size);
 }
 
 void WebContentsViewGuest::SetInitialFocus() {
@@ -63,7 +68,7 @@
 }
 
 gfx::Rect WebContentsViewGuest::GetViewBounds() const {
-  return platform_view_->GetViewBounds();
+  return gfx::Rect(size_);
 }
 
 #if defined(OS_MACOSX)
@@ -75,6 +80,7 @@
 void WebContentsViewGuest::CreateView(const gfx::Size& initial_size,
                                       gfx::NativeView context) {
   platform_view_->CreateView(initial_size, context);
+  size_ = initial_size;
 }
 
 RenderWidgetHostView* WebContentsViewGuest::CreateViewForWidget(
@@ -155,7 +161,14 @@
 }
 
 void WebContentsViewGuest::UpdateDragCursor(WebDragOperation operation) {
-  NOTIMPLEMENTED();
+  RenderViewHostImpl* embedder_render_view_host =
+      static_cast<RenderViewHostImpl*>(
+          guest_->embedder_web_contents()->GetRenderViewHost());
+  CHECK(embedder_render_view_host);
+  RenderViewHostDelegateView* view =
+      embedder_render_view_host->GetDelegate()->GetDelegateView();
+  if (view)
+    view->UpdateDragCursor(operation);
 }
 
 void WebContentsViewGuest::GotFocus() {
@@ -187,7 +200,18 @@
     const gfx::ImageSkia& image,
     const gfx::Vector2d& image_offset,
     const DragEventSourceInfo& event_info) {
-  NOTIMPLEMENTED();
+  WebContentsImpl* embedder_web_contents = guest_->embedder_web_contents();
+  embedder_web_contents->GetBrowserPluginEmbedder()->StartDrag(guest_);
+  RenderViewHostImpl* embedder_render_view_host =
+      static_cast<RenderViewHostImpl*>(
+          embedder_web_contents->GetRenderViewHost());
+  CHECK(embedder_render_view_host);
+  RenderViewHostDelegateView* view =
+      embedder_render_view_host->GetDelegate()->GetDelegateView();
+  if (view)
+    view->StartDragging(drop_data, ops, image, image_offset, event_info);
+  else
+    embedder_web_contents->SystemDragEnded();
 }
 
 }  // namespace content
diff --git a/content/browser/web_contents/web_contents_view_guest.h b/content/browser/web_contents/web_contents_view_guest.h
index 93abb1d..e92a200 100644
--- a/content/browser/web_contents/web_contents_view_guest.h
+++ b/content/browser/web_contents/web_contents_view_guest.h
@@ -97,6 +97,7 @@
   // The platform dependent view backing this WebContentsView.
   // Calls to this WebContentsViewGuest are forwarded to |platform_view_|.
   WebContentsViewPort* platform_view_;
+  gfx::Size size_;
 
   DISALLOW_COPY_AND_ASSIGN(WebContentsViewGuest);
 };
diff --git a/content/browser/web_contents/web_contents_view_mac.h b/content/browser/web_contents/web_contents_view_mac.h
index fdba569..53888b0 100644
--- a/content/browser/web_contents/web_contents_view_mac.h
+++ b/content/browser/web_contents/web_contents_view_mac.h
@@ -12,6 +12,7 @@
 
 #include "base/memory/scoped_nsobject.h"
 #include "base/memory/scoped_ptr.h"
+#include "content/common/content_export.h"
 #include "content/common/drag_event_source_info.h"
 #include "content/port/browser/render_view_host_delegate_view.h"
 #include "content/port/browser/web_contents_view_port.h"
@@ -33,6 +34,7 @@
 class Vector2d;
 }
 
+CONTENT_EXPORT
 @interface WebContentsViewCocoa : BaseView {
  @private
   content::WebContentsViewMac* webContentsView_;  // WEAK; owns us
diff --git a/content/browser/web_contents/web_contents_view_mac.mm b/content/browser/web_contents/web_contents_view_mac.mm
index c22a840..cd4120e 100644
--- a/content/browser/web_contents/web_contents_view_mac.mm
+++ b/content/browser/web_contents/web_contents_view_mac.mm
@@ -138,7 +138,8 @@
 
   // The drag invokes a nested event loop, arrange to continue
   // processing events.
-  MessageLoop::ScopedNestableTaskAllower allow(MessageLoop::current());
+  base::MessageLoop::ScopedNestableTaskAllower allow(
+      base::MessageLoop::current());
   NSDragOperation mask = static_cast<NSDragOperation>(allowed_operations);
   NSPoint offset = NSPointFromCGPoint(
       gfx::PointAtOffsetFromOrigin(image_offset).ToCGPoint());
@@ -483,7 +484,7 @@
 // Returns what kind of drag operations are available. This is a required
 // method for NSDraggingSource.
 - (NSDragOperation)draggingSourceOperationMaskForLocal:(BOOL)isLocal {
-  if (dragSource_.get())
+  if (dragSource_)
     return [dragSource_ draggingSourceOperationMaskForLocal:isLocal];
   // No web drag source - this is the case for dragging a file from the
   // downloads manager. Default to copy operation. Note: It is desirable to
diff --git a/content/browser/web_contents/web_contents_view_win.cc b/content/browser/web_contents/web_contents_view_win.cc
index 28f489a..3ceeb0f 100644
--- a/content/browser/web_contents/web_contents_view_win.cc
+++ b/content/browser/web_contents/web_contents_view_win.cc
@@ -155,7 +155,7 @@
   // Remove the root view drop target so we can register our own.
   RevokeDragDrop(GetNativeView());
   drag_dest_ = new WebDragDest(hwnd(), web_contents_);
-  if (delegate_.get()) {
+  if (delegate_) {
     WebDragDestDelegate* delegate = delegate_->GetDragDestDelegate();
     if (delegate)
       drag_dest_->set_delegate(delegate);
@@ -184,12 +184,12 @@
 }
 
 void WebContentsViewWin::StoreFocus() {
-  if (delegate_.get())
+  if (delegate_)
     delegate_->StoreFocus();
 }
 
 void WebContentsViewWin::RestoreFocus() {
-  if (delegate_.get())
+  if (delegate_)
     delegate_->RestoreFocus();
 }
 
@@ -246,7 +246,7 @@
 void WebContentsViewWin::ShowContextMenu(
     const ContextMenuParams& params,
     ContextMenuSourceType type) {
-  if (delegate_.get())
+  if (delegate_)
     delegate_->ShowContextMenu(params, type);
 }
 
@@ -310,11 +310,11 @@
 
 LRESULT WebContentsViewWin::OnDestroy(
     UINT message, WPARAM wparam, LPARAM lparam, BOOL& handled) {
-  if (drag_dest_.get()) {
+  if (drag_dest_) {
     RevokeDragDrop(GetNativeView());
     drag_dest_ = NULL;
   }
-  if (drag_handler_.get()) {
+  if (drag_handler_) {
     drag_handler_->CancelDrag();
     drag_handler_ = NULL;
   }
@@ -357,7 +357,7 @@
   if (rwhv)
     rwhv->SetSize(size);
 
-  if (delegate_.get())
+  if (delegate_)
     delegate_->SizeChanged(size);
 
   return 0;
diff --git a/content/browser/web_contents/web_drag_dest_gtk.cc b/content/browser/web_contents/web_drag_dest_gtk.cc
index fd2763f..6973821 100644
--- a/content/browser/web_contents/web_drag_dest_gtk.cc
+++ b/content/browser/web_contents/web_drag_dest_gtk.cc
@@ -284,7 +284,8 @@
   // preceded by a drag-leave. The renderer doesn't like getting the signals
   // in this order so delay telling it about the drag-leave till we are sure
   // we are not getting a drop as well.
-  MessageLoop::current()->PostTask(FROM_HERE,
+  base::MessageLoop::current()->PostTask(
+      FROM_HERE,
       base::Bind(&WebDragDestGtk::DragLeave, method_factory_.GetWeakPtr()));
 }
 
diff --git a/content/browser/web_contents/web_drag_dest_gtk.h b/content/browser/web_contents/web_drag_dest_gtk.h
index fb9a6b3..96d7aa3 100644
--- a/content/browser/web_contents/web_drag_dest_gtk.h
+++ b/content/browser/web_contents/web_drag_dest_gtk.h
@@ -96,7 +96,7 @@
   // signal handlers when this WebDragDestGtk is deleted so that if, later on,
   // we re-create the drag dest with the same widget, we don't get callbacks to
   // deleted functions.
-  scoped_array<int> handlers_;
+  scoped_ptr<int[]> handlers_;
 
   // A delegate that can receive drag information about drag events.
   WebDragDestDelegate* delegate_;
diff --git a/content/browser/web_contents/web_drag_dest_mac.h b/content/browser/web_contents/web_drag_dest_mac.h
index 4358e2b..a344a4c 100644
--- a/content/browser/web_contents/web_drag_dest_mac.h
+++ b/content/browser/web_contents/web_drag_dest_mac.h
@@ -6,6 +6,7 @@
 
 #include "base/memory/scoped_ptr.h"
 #include "base/string16.h"
+#include "content/common/content_export.h"
 #include "webkit/glue/webdropdata.h"
 
 
@@ -21,7 +22,7 @@
 // A class that handles tracking and event processing for a drag and drop
 // over the content area. Assumes something else initiates the drag, this is
 // only for processing during a drag.
-
+CONTENT_EXPORT
 @interface WebDragDest : NSObject {
  @private
   // Our associated WebContentsImpl. Weak reference.
diff --git a/content/browser/web_contents/web_drag_dest_mac.mm b/content/browser/web_contents/web_drag_dest_mac.mm
index a292e3b..e3f7a0e 100644
--- a/content/browser/web_contents/web_drag_dest_mac.mm
+++ b/content/browser/web_contents/web_drag_dest_mac.mm
@@ -6,7 +6,7 @@
 
 #import <Carbon/Carbon.h>
 
-#include "base/sys_string_conversions.h"
+#include "base/strings/sys_string_conversions.h"
 #include "content/browser/renderer_host/render_view_host_impl.h"
 #include "content/browser/web_contents/web_contents_impl.h"
 #include "content/public/browser/web_drag_dest_delegate.h"
@@ -248,9 +248,11 @@
 
   // Get HTML. If there's no HTML, try RTF.
   if ([types containsObject:NSHTMLPboardType]) {
-    data->html = NullableString16(
-        base::SysNSStringToUTF16([pboard stringForType:NSHTMLPboardType]),
-        false);
+    NSString* html = [pboard stringForType:NSHTMLPboardType];
+    data->html = NullableString16(base::SysNSStringToUTF16(html), false);
+  } else if ([types containsObject:ui::kChromeDragImageHTMLPboardType]) {
+    NSString* html = [pboard stringForType:ui::kChromeDragImageHTMLPboardType];
+    data->html = NullableString16(base::SysNSStringToUTF16(html), false);
   } else if ([types containsObject:NSRTFPboardType]) {
     NSString* html = [pboard htmlFromRtf];
     data->html = NullableString16(base::SysNSStringToUTF16(html), false);
diff --git a/content/browser/web_contents/web_drag_dest_mac_unittest.mm b/content/browser/web_contents/web_drag_dest_mac_unittest.mm
index 43fb8a3..204a2ae 100644
--- a/content/browser/web_contents/web_drag_dest_mac_unittest.mm
+++ b/content/browser/web_contents/web_drag_dest_mac_unittest.mm
@@ -4,7 +4,7 @@
 
 #include "base/mac/scoped_nsautorelease_pool.h"
 #import "base/memory/scoped_nsobject.h"
-#include "base/sys_string_conversions.h"
+#include "base/strings/sys_string_conversions.h"
 #include "base/utf_string_conversions.h"
 #include "content/browser/renderer_host/test_render_view_host.h"
 #import "content/browser/web_contents/web_drag_dest_mac.h"
diff --git a/content/browser/web_contents/web_drag_source_gtk.cc b/content/browser/web_contents/web_drag_source_gtk.cc
index c3a786f..05af3f5 100644
--- a/content/browser/web_contents/web_drag_source_gtk.cc
+++ b/content/browser/web_contents/web_drag_source_gtk.cc
@@ -36,7 +36,7 @@
 namespace content {
 
 WebDragSourceGtk::WebDragSourceGtk(WebContents* web_contents)
-    : web_contents_(web_contents),
+    : web_contents_(static_cast<WebContentsImpl*>(web_contents)),
       drag_pixbuf_(NULL),
       drag_failed_(false),
       drag_widget_(gtk_invisible_new()),
@@ -58,10 +58,10 @@
 
 WebDragSourceGtk::~WebDragSourceGtk() {
   // Break the current drag, if any.
-  if (drop_data_.get()) {
+  if (drop_data_) {
     gtk_grab_add(drag_widget_);
     gtk_grab_remove(drag_widget_);
-    MessageLoopForUI::current()->RemoveObserver(this);
+    base::MessageLoopForUI::current()->RemoveObserver(this);
     drop_data_.reset();
   }
 
@@ -69,7 +69,7 @@
   gtk_widget_destroy(drag_icon_);
 }
 
-void WebDragSourceGtk::StartDragging(const WebDropData& drop_data,
+bool WebDragSourceGtk::StartDragging(const WebDropData& drop_data,
                                      WebDragOperationsMask allowed_ops,
                                      GdkEventButton* last_mouse_down,
                                      const SkBitmap& image,
@@ -77,8 +77,7 @@
   // Guard against re-starting before previous drag completed.
   if (drag_context_) {
     NOTREACHED();
-    web_contents_->SystemDragEnded();
-    return;
+    return false;
   }
 
   int targets_mask = 0;
@@ -146,11 +145,11 @@
   if (!drag_context_) {
     drag_failed_ = true;
     drop_data_.reset();
-    web_contents_->SystemDragEnded();
-    return;
+    return false;
   }
 
-  MessageLoopForUI::current()->AddObserver(this);
+  base::MessageLoopForUI::current()->AddObserver(this);
+  return true;
 }
 
 void WebDragSourceGtk::WillProcessEvent(GdkEvent* event) {
@@ -164,8 +163,8 @@
   GdkEventMotion* event_motion = reinterpret_cast<GdkEventMotion*>(event);
   gfx::Point client = ui::ClientPoint(GetContentNativeView());
 
-  if (GetRenderViewHost()) {
-    GetRenderViewHost()->DragSourceMovedTo(
+  if (web_contents_) {
+    web_contents_->DragSourceMovedTo(
         client.x(), client.y(),
         static_cast<int>(event_motion->x_root),
         static_cast<int>(event_motion->y_root));
@@ -246,7 +245,7 @@
               CreateFileStreamForDrop(
                   &file_path,
                   GetContentClient()->browser()->GetNetLog()));
-          if (file_stream.get()) {
+          if (file_stream) {
             // Start downloading the file to the stream.
             scoped_refptr<DragDownloadFile> drag_file_downloader =
                 new DragDownloadFile(
@@ -300,8 +299,8 @@
   gfx::Point root = ui::ScreenPoint(GetContentNativeView());
   gfx::Point client = ui::ClientPoint(GetContentNativeView());
 
-  if (GetRenderViewHost()) {
-    GetRenderViewHost()->DragSourceEndedAt(
+  if (web_contents_) {
+    web_contents_->DragSourceEndedAt(
         client.x(), client.y(), root.x(), root.y(),
         WebDragOperationNone);
   }
@@ -361,7 +360,7 @@
     drag_pixbuf_ = NULL;
   }
 
-  MessageLoopForUI::current()->RemoveObserver(this);
+  base::MessageLoopForUI::current()->RemoveObserver(this);
 
   if (!download_url_.is_empty()) {
     gdk_property_delete(drag_context->source_window,
@@ -372,8 +371,8 @@
     gfx::Point root = ui::ScreenPoint(GetContentNativeView());
     gfx::Point client = ui::ClientPoint(GetContentNativeView());
 
-    if (GetRenderViewHost()) {
-      GetRenderViewHost()->DragSourceEndedAt(
+    if (web_contents_) {
+      web_contents_->DragSourceEndedAt(
           client.x(), client.y(), root.x(), root.y(),
           GdkDragActionToWebDragOp(drag_context->action));
     }
@@ -385,10 +384,6 @@
   drag_context_ = NULL;
 }
 
-RenderViewHostImpl* WebDragSourceGtk::GetRenderViewHost() const {
-  return static_cast<RenderViewHostImpl*>(web_contents_->GetRenderViewHost());
-}
-
 gfx::NativeView WebDragSourceGtk::GetContentNativeView() const {
   return web_contents_->GetView()->GetContentNativeView();
 }
diff --git a/content/browser/web_contents/web_drag_source_gtk.h b/content/browser/web_contents/web_drag_source_gtk.h
index d95b40e..4c3381f 100644
--- a/content/browser/web_contents/web_drag_source_gtk.h
+++ b/content/browser/web_contents/web_drag_source_gtk.h
@@ -12,6 +12,7 @@
 #include "base/message_loop.h"
 #include "base/string16.h"
 #include "content/common/content_export.h"
+#include "content/public/browser/web_contents.h"
 #include "googleurl/src/gurl.h"
 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDragOperation.h"
 #include "ui/base/gtk/gtk_signal.h"
@@ -25,17 +26,19 @@
 namespace content {
 
 class RenderViewHostImpl;
-class WebContents;
+class WebContentsImpl;
 
 // WebDragSourceGtk takes care of managing the drag from a WebContents
 // with Gtk.
-class CONTENT_EXPORT WebDragSourceGtk : public MessageLoopForUI::Observer {
+class CONTENT_EXPORT WebDragSourceGtk :
+    public base::MessageLoopForUI::Observer {
  public:
   explicit WebDragSourceGtk(WebContents* web_contents);
   virtual ~WebDragSourceGtk();
 
   // Starts a drag for the WebContents this WebDragSourceGtk was created for.
-  void StartDragging(const WebDropData& drop_data,
+  // Returns false if the drag could not be started.
+  bool StartDragging(const WebDropData& drop_data,
                      WebKit::WebDragOperationsMask allowed_ops,
                      GdkEventButton* last_mouse_down,
                      const SkBitmap& image,
@@ -57,11 +60,10 @@
   CHROMEGTK_CALLBACK_1(WebDragSourceGtk, gboolean, OnDragIconExpose,
                        GdkEventExpose*);
 
-  RenderViewHostImpl* GetRenderViewHost() const;
   gfx::NativeView GetContentNativeView() const;
 
   // The tab we're manging the drag for.
-  WebContents* web_contents_;
+  WebContentsImpl* web_contents_;
 
   // The drop data for the current drag (for drags that originate in the render
   // view). Non-NULL iff there is a current drag.
diff --git a/content/browser/web_contents/web_drag_source_mac.h b/content/browser/web_contents/web_drag_source_mac.h
index a8f1f00..8e2f02c 100644
--- a/content/browser/web_contents/web_drag_source_mac.h
+++ b/content/browser/web_contents/web_drag_source_mac.h
@@ -8,6 +8,7 @@
 #include "base/mac/scoped_cftyperef.h"
 #include "base/memory/scoped_nsobject.h"
 #include "base/memory/scoped_ptr.h"
+#include "content/common/content_export.h"
 #include "googleurl/src/gurl.h"
 
 struct WebDropData;
@@ -17,6 +18,7 @@
 
 // A class that handles tracking and event processing for a drag and drop
 // originating from the content area.
+CONTENT_EXPORT
 @interface WebDragSource : NSObject {
  @private
   // Our contents. Weak reference (owns or co-owns us).
diff --git a/content/browser/web_contents/web_drag_source_mac.mm b/content/browser/web_contents/web_drag_source_mac.mm
index 83521f1..86b2f23 100644
--- a/content/browser/web_contents/web_drag_source_mac.mm
+++ b/content/browser/web_contents/web_drag_source_mac.mm
@@ -11,7 +11,7 @@
 #include "base/mac/mac_util.h"
 #include "base/pickle.h"
 #include "base/string_util.h"
-#include "base/sys_string_conversions.h"
+#include "base/strings/sys_string_conversions.h"
 #include "base/threading/thread.h"
 #include "base/threading/thread_restrictions.h"
 #include "base/utf_string_conversions.h"
@@ -150,17 +150,18 @@
       "<meta http-equiv=\"Content-Type\" content=\"text/html;charset=UTF-8\">");
 
   // Be extra paranoid; avoid crashing.
-  if (!dropData_.get()) {
+  if (!dropData_) {
     NOTREACHED();
     return;
   }
 
   // HTML.
-  if ([type isEqualToString:NSHTMLPboardType]) {
+  if ([type isEqualToString:NSHTMLPboardType] ||
+      [type isEqualToString:ui::kChromeDragImageHTMLPboardType]) {
     DCHECK(!dropData_->html.string().empty());
     // See comment on |kHtmlHeader| above.
     [pboard setString:SysUTF16ToNSString(kHtmlHeader + dropData_->html.string())
-              forType:NSHTMLPboardType];
+              forType:type];
 
   // URL.
   } else if ([type isEqualToString:NSURLPboardType]) {
@@ -186,7 +187,7 @@
               forType:kNSURLTitlePboardType];
 
   // File contents.
-  } else if ([type isEqualToString:base::mac::CFToNSCast(fileUTI_.get())]) {
+  } else if ([type isEqualToString:base::mac::CFToNSCast(fileUTI_)]) {
     [pboard setData:[NSData dataWithBytes:dropData_->file_contents.data()
                                    length:dropData_->file_contents.length()]
             forType:base::mac::CFToNSCast(fileUTI_.get())];
@@ -282,9 +283,8 @@
     if (operation == (NSDragOperationMove | NSDragOperationCopy))
       operation &= ~NSDragOperationMove;
 
-    rvh->DragSourceEndedAt(localPoint.x, localPoint.y,
-                           screenPoint.x, screenPoint.y,
-                           static_cast<WebKit::WebDragOperation>(operation));
+    contents_->DragSourceEndedAt(localPoint.x, localPoint.y, screenPoint.x,
+        screenPoint.y, static_cast<WebKit::WebDragOperation>(operation));
   }
 
   // Make sure the pasteboard owner isn't us.
@@ -307,14 +307,14 @@
     NSRect screenFrame = [[[contentsView_ window] screen] frame];
     screenPoint.y = screenFrame.size.height - screenPoint.y;
 
-    rvh->DragSourceMovedTo(localPoint.x, localPoint.y,
-                           screenPoint.x, screenPoint.y);
+    contents_->DragSourceMovedTo(localPoint.x, localPoint.y,
+                                 screenPoint.x, screenPoint.y);
   }
 }
 
 - (NSString*)dragPromisedFileTo:(NSString*)path {
   // Be extra paranoid; avoid crashing.
-  if (!dropData_.get()) {
+  if (!dropData_) {
     NOTREACHED() << "No drag-and-drop data available for promised file.";
     return nil;
   }
@@ -330,7 +330,7 @@
   base::ThreadRestrictions::ScopedAllowIO allowIO;
   scoped_ptr<FileStream> fileStream(content::CreateFileStreamForDrop(
       &filePath, content::GetContentClient()->browser()->GetNetLog()));
-  if (!fileStream.get())
+  if (!fileStream)
     return nil;
 
   if (downloadURL_.is_valid()) {
@@ -365,15 +365,14 @@
 - (void)fillPasteboard {
   DCHECK(pasteboard_.get());
 
-  [pasteboard_
-      declareTypes:[NSArray arrayWithObject:ui::kChromeDragDummyPboardType]
-             owner:contentsView_];
+  [pasteboard_ declareTypes:@[ui::kChromeDragDummyPboardType]
+                      owner:contentsView_];
 
   // URL (and title).
-  if (dropData_->url.is_valid())
-    [pasteboard_ addTypes:[NSArray arrayWithObjects:NSURLPboardType,
-                                                    kNSURLTitlePboardType, nil]
+  if (dropData_->url.is_valid()) {
+    [pasteboard_ addTypes:@[NSURLPboardType, kNSURLTitlePboardType]
                     owner:contentsView_];
+  }
 
   // MIME type.
   std::string mimeType;
@@ -437,25 +436,32 @@
   bool hasHTMLData = !dropData_->html.string().empty();
   // Mail.app and TextEdit accept drags that have both HTML and image flavors on
   // them, but don't process them correctly <http://crbug.com/55879>. Therefore,
-  // omit the HTML flavor if there is an image flavor. (The only time that
-  // WebKit fills in the WebDropData::file_contents is with an image drop, but
-  // the MIME time is tested anyway for paranoia's sake.)
+  // if there is an image flavor, don't put the HTML data on as HTML, but rather
+  // put it on as this Chrome-only flavor.
+  //
+  // (The only time that Blink fills in the WebDropData::file_contents is with
+  // an image drop, but the MIME time is tested anyway for paranoia's sake.)
   bool hasImageData = !dropData_->file_contents.empty() &&
                       fileUTI_ &&
                       UTTypeConformsTo(fileUTI_.get(), kUTTypeImage);
-  if (hasHTMLData && !hasImageData)
-    [pasteboard_ addTypes:[NSArray arrayWithObject:NSHTMLPboardType]
-                    owner:contentsView_];
+  if (hasHTMLData) {
+    if (hasImageData) {
+      [pasteboard_ addTypes:@[ui::kChromeDragImageHTMLPboardType]
+                      owner:contentsView_];
+    } else {
+      [pasteboard_ addTypes:@[NSHTMLPboardType] owner:contentsView_];
+    }
+  }
 
   // Plain text.
-  if (!dropData_->text.string().empty())
-    [pasteboard_ addTypes:[NSArray arrayWithObject:NSStringPboardType]
+  if (!dropData_->text.string().empty()) {
+    [pasteboard_ addTypes:@[NSStringPboardType]
                     owner:contentsView_];
+  }
 
   if (!dropData_->custom_data.empty()) {
-    [pasteboard_
-        addTypes:[NSArray arrayWithObject:ui::kWebCustomDataPboardType]
-           owner:contentsView_];
+    [pasteboard_ addTypes:@[ui::kWebCustomDataPboardType]
+                    owner:contentsView_];
   }
 }
 
diff --git a/content/browser/web_contents/web_drag_source_win.cc b/content/browser/web_contents/web_drag_source_win.cc
index 18c1881..53df4e8 100644
--- a/content/browser/web_contents/web_drag_source_win.cc
+++ b/content/browser/web_contents/web_drag_source_win.cc
@@ -6,11 +6,12 @@
 
 #include "base/bind.h"
 #include "content/browser/renderer_host/render_view_host_impl.h"
+#include "content/browser/web_contents/web_contents_impl.h"
 #include "content/browser/web_contents/web_drag_utils_win.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/notification_source.h"
 #include "content/public/browser/notification_types.h"
-#include "content/public/browser/web_contents.h"
+#include "ui/base/dragdrop/os_exchange_data.h"
 
 using WebKit::WebDragOperationNone;
 
@@ -35,8 +36,9 @@
                              WebContents* web_contents)
     : ui::DragSourceWin(),
       source_wnd_(source_wnd),
-      render_view_host_(web_contents->GetRenderViewHost()),
-      effect_(DROPEFFECT_NONE) {
+      web_contents_(static_cast<WebContentsImpl*>(web_contents)),
+      effect_(DROPEFFECT_NONE),
+      data_(NULL) {
   registrar_.Add(this, NOTIFICATION_WEB_CONTENTS_SWAPPED,
                  Source<WebContents>(web_contents));
   registrar_.Add(this, NOTIFICATION_WEB_CONTENTS_DISCONNECTED,
@@ -55,18 +57,20 @@
     return;
   }
 
-  if (!render_view_host_)
+  if (!web_contents_)
     return;
 
   gfx::Point client;
   gfx::Point screen;
   GetCursorPositions(source_wnd_, &client, &screen);
-  render_view_host_->DragSourceEndedAt(client.x(), client.y(),
-                                       screen.x(), screen.y(),
-                                       WebDragOperationNone);
+  web_contents_->DragSourceEndedAt(client.x(), client.y(),
+                                   screen.x(), screen.y(),
+                                   WebDragOperationNone);
 }
 
 void WebDragSource::OnDragSourceDrop() {
+  DCHECK(data_);
+  data_->SetInDragLoop(false);
   // On Windows, we check for drag end in IDropSource::QueryContinueDrag which
   // happens before IDropTarget::Drop is called. HTML5 requires the "dragend"
   // event to happen after the "drop" event. Since  Windows calls these two
@@ -78,15 +82,14 @@
 }
 
 void WebDragSource::DelayedOnDragSourceDrop() {
-  if (!render_view_host_)
+  if (!web_contents_)
     return;
 
   gfx::Point client;
   gfx::Point screen;
   GetCursorPositions(source_wnd_, &client, &screen);
-  render_view_host_->DragSourceEndedAt(
-      client.x(), client.y(), screen.x(), screen.y(),
-      WinDragOpToWebDragOp(effect_));
+  web_contents_->DragSourceEndedAt(client.x(), client.y(), screen.x(),
+                                   screen.y(), WinDragOpToWebDragOp(effect_));
 }
 
 void WebDragSource::OnDragSourceMove() {
@@ -98,14 +101,14 @@
     return;
   }
 
-  if (!render_view_host_)
+  if (!web_contents_)
     return;
 
   gfx::Point client;
   gfx::Point screen;
   GetCursorPositions(source_wnd_, &client, &screen);
-  render_view_host_->DragSourceMovedTo(client.x(), client.y(),
-                                       screen.x(), screen.y());
+  web_contents_->DragSourceMovedTo(client.x(), client.y(),
+                                   screen.x(), screen.y());
 }
 
 void WebDragSource::Observe(int type,
@@ -115,12 +118,12 @@
     // When the WebContents get swapped, our render view host goes away.
     // That's OK, we can continue the drag, we just can't send messages back to
     // our drag source.
-    render_view_host_ = NULL;
+    web_contents_ = NULL;
   } else if (type == NOTIFICATION_WEB_CONTENTS_DISCONNECTED) {
     // This could be possible when we close the tab and the source is still
     // being used in DoDragDrop at the time that the virtual file is being
     // downloaded.
-    render_view_host_ = NULL;
+    web_contents_ = NULL;
   }
 }
 
diff --git a/content/browser/web_contents/web_drag_source_win.h b/content/browser/web_contents/web_drag_source_win.h
index 898f3c3..72d4a16 100644
--- a/content/browser/web_contents/web_drag_source_win.h
+++ b/content/browser/web_contents/web_drag_source_win.h
@@ -12,9 +12,14 @@
 #include "ui/gfx/native_widget_types.h"
 #include "ui/gfx/point.h"
 
+namespace ui {
+class OSExchangeData;
+}  // namespace ui
+
 namespace content {
 class RenderViewHost;
 class WebContents;
+class WebContentsImpl;
 
 // An IDropSource implementation for a WebContentsImpl. Handles notifications
 // sent by an active drag-drop operation as the user mouses over other drop
@@ -33,6 +38,10 @@
                        const NotificationDetails& details);
 
   void set_effect(DWORD effect) { effect_ = effect; }
+  // Used to set the active data object for the current drag operation. The
+  // caller must ensure that |data| is not destroyed before the nested drag loop
+  // terminates.
+  void set_data(ui::OSExchangeData* data) { data_ = data; }
 
  protected:
   // ui::DragSourceWin
@@ -54,12 +63,14 @@
   // We use this as a channel to the renderer to tell it about various drag
   // drop events that it needs to know about (such as when a drag operation it
   // initiated terminates).
-  RenderViewHost* render_view_host_;
+  WebContentsImpl* web_contents_;
 
   NotificationRegistrar registrar_;
 
   DWORD effect_;
 
+  ui::OSExchangeData* data_;
+
   DISALLOW_COPY_AND_ASSIGN(WebDragSource);
 };
 
diff --git a/content/browser/webui/content_web_ui_controller_factory.cc b/content/browser/webui/content_web_ui_controller_factory.cc
index 7f486d8..45a38ad 100644
--- a/content/browser/webui/content_web_ui_controller_factory.cc
+++ b/content/browser/webui/content_web_ui_controller_factory.cc
@@ -6,6 +6,7 @@
 
 #include "content/browser/accessibility/accessibility_ui.h"
 #include "content/browser/gpu/gpu_internals_ui.h"
+#include "content/browser/indexed_db/indexed_db_internals_ui.h"
 #include "content/browser/media/media_internals_ui.h"
 #include "content/browser/media/webrtc_internals_ui.h"
 #include "content/browser/tracing/tracing_ui.h"
@@ -17,13 +18,14 @@
 
 WebUI::TypeID ContentWebUIControllerFactory::GetWebUIType(
       BrowserContext* browser_context, const GURL& url) const {
-  if (url.host() == chrome::kChromeUIWebRTCInternalsHost ||
+  if (url.host() == kChromeUIWebRTCInternalsHost ||
 #if !defined(OS_ANDROID)
-      url.host() == chrome::kChromeUITracingHost ||
+      url.host() == kChromeUITracingHost ||
 #endif
-      url.host() == chrome::kChromeUIGpuHost ||
-      url.host() == chrome::kChromeUIMediaInternalsHost ||
-      url.host() == chrome::kChromeUIAccessibilityHost) {
+      url.host() == kChromeUIGpuHost ||
+      url.host() == kChromeUIIndexedDBInternalsHost ||
+      url.host() == kChromeUIMediaInternalsHost ||
+      url.host() == kChromeUIAccessibilityHost) {
     return const_cast<ContentWebUIControllerFactory*>(this);
   }
   return WebUI::kNoWebUI;
@@ -41,16 +43,18 @@
 
 WebUIController* ContentWebUIControllerFactory::CreateWebUIControllerForURL(
     WebUI* web_ui, const GURL& url) const {
-  if (url.host() == chrome::kChromeUIWebRTCInternalsHost)
+  if (url.host() == kChromeUIWebRTCInternalsHost)
     return new WebRTCInternalsUI(web_ui);
-  if (url.host() == chrome::kChromeUIGpuHost)
+  if (url.host() == kChromeUIGpuHost)
     return new GpuInternalsUI(web_ui);
-  if (url.host() == chrome::kChromeUIMediaInternalsHost)
+  if (url.host() == kChromeUIIndexedDBInternalsHost)
+    return new IndexedDBInternalsUI(web_ui);
+  if (url.host() == kChromeUIMediaInternalsHost)
     return new MediaInternalsUI(web_ui);
-  if (url.host() == chrome::kChromeUIAccessibilityHost)
+  if (url.host() == kChromeUIAccessibilityHost)
     return new AccessibilityUI(web_ui);
 #if !defined(OS_ANDROID)
-  if (url.host() == chrome::kChromeUITracingHost)
+  if (url.host() == kChromeUITracingHost)
     return new TracingUI(web_ui);
 #endif
 
diff --git a/content/browser/webui/shared_resources_data_source.cc b/content/browser/webui/shared_resources_data_source.cc
index 54c0c4c..fc390b2 100644
--- a/content/browser/webui/shared_resources_data_source.cc
+++ b/content/browser/webui/shared_resources_data_source.cc
@@ -34,13 +34,14 @@
 SharedResourcesDataSource::~SharedResourcesDataSource() {
 }
 
-std::string SharedResourcesDataSource::GetSource() {
-  return chrome::kChromeUIResourcesHost;
+std::string SharedResourcesDataSource::GetSource() const {
+  return content::kChromeUIResourcesHost;
 }
 
 void SharedResourcesDataSource::StartDataRequest(
     const std::string& path,
-    bool is_incognito,
+    int render_process_id,
+    int render_view_id,
     const content::URLDataSource::GotDataCallback& callback) {
   int idr = PathToIDR(path);
   DCHECK_NE(-1, idr) << " path: " << path;
diff --git a/content/browser/webui/shared_resources_data_source.h b/content/browser/webui/shared_resources_data_source.h
index b5c20b7..cf9c24c 100644
--- a/content/browser/webui/shared_resources_data_source.h
+++ b/content/browser/webui/shared_resources_data_source.h
@@ -15,10 +15,11 @@
   SharedResourcesDataSource();
 
   // content::URLDataSource implementation.
-  virtual std::string GetSource() OVERRIDE;
+  virtual std::string GetSource() const OVERRIDE;
   virtual void StartDataRequest(
       const std::string& path,
-      bool is_incognito,
+      int render_process_id,
+      int render_view_id,
       const content::URLDataSource::GotDataCallback& callback) OVERRIDE;
   virtual std::string GetMimeType(const std::string&) const OVERRIDE;
 
diff --git a/content/browser/webui/url_data_manager_backend.cc b/content/browser/webui/url_data_manager_backend.cc
index 2f28b2a..fc1a706 100644
--- a/content/browser/webui/url_data_manager_backend.cc
+++ b/content/browser/webui/url_data_manager_backend.cc
@@ -28,11 +28,14 @@
 #include "content/browser/webui/url_data_source_impl.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/content_browser_client.h"
+#include "content/public/browser/render_process_host.h"
+#include "content/public/browser/resource_request_info.h"
 #include "content/public/common/url_constants.h"
 #include "googleurl/src/url_util.h"
 #include "net/base/io_buffer.h"
 #include "net/base/net_errors.h"
 #include "net/http/http_response_headers.h"
+#include "net/http/http_status_code.h"
 #include "net/url_request/url_request.h"
 #include "net/url_request/url_request_context.h"
 #include "net/url_request/url_request_job.h"
@@ -61,11 +64,12 @@
 // is the hostname and |path| is the remaining portion of the URL.
 void URLToRequest(const GURL& url, std::string* source_name,
                   std::string* path) {
+  std::vector<std::string> additional_schemes;
   DCHECK(url.SchemeIs(chrome::kChromeDevToolsScheme) ||
          url.SchemeIs(chrome::kChromeUIScheme) ||
-         SchemeIsInSchemes(
-             url.scheme(),
-             GetContentClient()->browser()->GetAdditionalWebUISchemes()));
+         (GetContentClient()->browser()->GetAdditionalWebUISchemes(
+             &additional_schemes),
+          SchemeIsInSchemes(url.scheme(), additional_schemes)));
 
   if (!url.is_valid()) {
     NOTREACHED();
@@ -108,6 +112,7 @@
                            int buf_size,
                            int* bytes_read) OVERRIDE;
   virtual bool GetMimeType(std::string* mime_type) const OVERRIDE;
+  virtual int GetResponseCode() const OVERRIDE;
   virtual void GetResponseInfo(net::HttpResponseInfo* info) OVERRIDE;
 
   // Used to notify that the requested data's |mime_type| is ready.
@@ -209,7 +214,7 @@
       deny_xframe_options_(true),
       is_incognito_(is_incognito),
       backend_(backend),
-      ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) {
+      weak_factory_(this) {
   DCHECK(backend);
 }
 
@@ -220,10 +225,9 @@
 void URLRequestChromeJob::Start() {
   // Start reading asynchronously so that all error reporting and data
   // callbacks happen as they would for network requests.
-  MessageLoop::current()->PostTask(
+  base::MessageLoop::current()->PostTask(
       FROM_HERE,
-      base::Bind(&URLRequestChromeJob::StartAsync,
-                 weak_factory_.GetWeakPtr()));
+      base::Bind(&URLRequestChromeJob::StartAsync, weak_factory_.GetWeakPtr()));
 
   TRACE_EVENT_ASYNC_BEGIN1("browser", "DataManager:Request", this, "URL",
       request_->url().possibly_invalid_spec());
@@ -238,6 +242,10 @@
   return !mime_type_.empty();
 }
 
+int URLRequestChromeJob::GetResponseCode() const {
+  return net::HTTP_OK;
+}
+
 void URLRequestChromeJob::GetResponseInfo(net::HttpResponseInfo* info) {
   DCHECK(!info->headers);
   // Set the headers so that requests serviced by ChromeURLDataManager return a
@@ -276,7 +284,7 @@
 
     data_ = bytes;
     int bytes_read;
-    if (pending_buf_.get()) {
+    if (pending_buf_) {
       CHECK(pending_buf_->data());
       CompleteRead(pending_buf_, pending_buf_size_, &bytes_read);
       pending_buf_ = NULL;
@@ -291,7 +299,7 @@
 
 bool URLRequestChromeJob::ReadRawData(net::IOBuffer* buf, int buf_size,
                                       int* bytes_read) {
-  if (!data_.get()) {
+  if (!data_) {
     SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0));
     DCHECK(!pending_buf_.get());
     CHECK(buf->data());
@@ -373,7 +381,7 @@
 
     // Next check for chrome://appcache-internals/, which uses its own job type.
     if (request->url().SchemeIs(chrome::kChromeUIScheme) &&
-        request->url().host() == chrome::kChromeUIAppCacheInternalsHost) {
+        request->url().host() == kChromeUIAppCacheInternalsHost) {
       return appcache::ViewAppCacheInternalsJobFactory::CreateJobForRequest(
           request, network_delegate, appcache_service_);
     }
@@ -387,14 +395,14 @@
 #if defined(USE_TCMALLOC)
     // Next check for chrome://tcmalloc/, which uses its own job type.
     if (request->url().SchemeIs(chrome::kChromeUIScheme) &&
-        request->url().host() == chrome::kChromeUITcmallocHost) {
+        request->url().host() == kChromeUITcmallocHost) {
       return new TcmallocInternalsRequestJob(request, network_delegate);
     }
 #endif
 
     // Next check for chrome://histograms/, which uses its own job type.
     if (request->url().SchemeIs(chrome::kChromeUIScheme) &&
-        request->url().host() == chrome::kChromeUIHistogramHost) {
+        request->url().host() == kChromeUIHistogramHost) {
       return new HistogramInternalsRequestJob(request, network_delegate);
     }
 
@@ -485,6 +493,7 @@
 
   if (!source->source()->ShouldServiceRequest(request))
     return false;
+  source->source()->WillServiceRequest(request, &path);
 
   // Save this request so we know where to send the data.
   RequestID request_id = next_request_id_++;
@@ -500,11 +509,17 @@
   job->set_deny_xframe_options(
       source->source()->ShouldDenyXFrameOptions());
 
+  // Look up additional request info to pass down.
+  int render_process_id = -1;
+  int render_view_id = -1;
+  ResourceRequestInfo::GetRenderViewForRequest(request,
+                                               &render_process_id,
+                                               &render_view_id);
+
   // Forward along the request to the data source.
-  MessageLoop* target_message_loop =
+  base::MessageLoop* target_message_loop =
       source->source()->MessageLoopForRequestPath(path);
   if (!target_message_loop) {
-    bool is_incognito = job->is_incognito();
     job->MimeTypeAvailable(source->source()->GetMimeType(path));
     // Eliminate potentially dangling pointer to avoid future use.
     job = NULL;
@@ -513,7 +528,7 @@
     // on for this path.  Call directly into it from this thread, the IO
     // thread.
     source->source()->StartDataRequest(
-        path, is_incognito,
+        path, render_process_id, render_view_id,
         base::Bind(&URLDataSourceImpl::SendResponse, source, request_id));
   } else {
     // URLRequestChromeJob should receive mime type before data. This
@@ -531,8 +546,8 @@
     target_message_loop->PostTask(
         FROM_HERE,
         base::Bind(&URLDataManagerBackend::CallStartRequest,
-                   make_scoped_refptr(source), path, job->is_incognito(),
-                   request_id));
+                   make_scoped_refptr(source), path, render_process_id,
+                   render_view_id, request_id));
   }
   return true;
 }
@@ -540,11 +555,21 @@
 void URLDataManagerBackend::CallStartRequest(
     scoped_refptr<URLDataSourceImpl> source,
     const std::string& path,
-    bool is_incognito,
+    int render_process_id,
+    int render_view_id,
     int request_id) {
+  if (BrowserThread::CurrentlyOn(BrowserThread::UI) &&
+      !RenderProcessHost::FromID(render_process_id)) {
+    // Make the request fail if its initiating renderer is no longer valid.
+    // This can happen when the IO thread posts this task just before the
+    // renderer shuts down.
+    source->SendResponse(request_id, NULL);
+    return;
+  }
   source->source()->StartDataRequest(
       path,
-      is_incognito,
+      render_process_id,
+      render_view_id,
       base::Bind(&URLDataSourceImpl::SendResponse, source, request_id));
 }
 
diff --git a/content/browser/webui/url_data_manager_backend.h b/content/browser/webui/url_data_manager_backend.h
index 3181369..e38fe1e 100644
--- a/content/browser/webui/url_data_manager_backend.h
+++ b/content/browser/webui/url_data_manager_backend.h
@@ -13,6 +13,7 @@
 #include "base/compiler_specific.h"
 #include "base/supports_user_data.h"
 #include "content/browser/webui/url_data_manager.h"
+#include "content/public/browser/url_data_source.h"
 #include "net/url_request/url_request_job_factory.h"
 
 class GURL;
@@ -75,7 +76,8 @@
   // need to add a refcount on the source.
   static void CallStartRequest(scoped_refptr<URLDataSourceImpl> source,
                                const std::string& path,
-                               bool is_incognito,
+                               int render_process_id,
+                               int render_view_id,
                                int request_id);
 
   // Remove a request from the list of pending requests.
diff --git a/content/browser/webui/web_ui_data_source_impl.cc b/content/browser/webui/web_ui_data_source_impl.cc
index 5f17e53..7ca34d2 100644
--- a/content/browser/webui/web_ui_data_source_impl.cc
+++ b/content/browser/webui/web_ui_data_source_impl.cc
@@ -35,7 +35,7 @@
   }
 
   // URLDataSource implementation.
-  virtual std::string GetSource() OVERRIDE {
+  virtual std::string GetSource() const OVERRIDE {
     return parent_->GetSource();
   }
   virtual std::string GetMimeType(const std::string& path) const OVERRIDE {
@@ -43,9 +43,11 @@
   }
   virtual void StartDataRequest(
       const std::string& path,
-      bool is_incognito,
+      int render_process_id,
+      int render_view_id,
       const URLDataSource::GotDataCallback& callback) OVERRIDE {
-    return parent_->StartDataRequest(path, is_incognito, callback);
+    return parent_->StartDataRequest(path, render_process_id, render_view_id,
+                                     callback);
   }
   virtual bool ShouldAddContentSecurityPolicy() const OVERRIDE {
     return parent_->add_csp_;
@@ -71,7 +73,7 @@
 WebUIDataSourceImpl::WebUIDataSourceImpl(const std::string& source_name)
     : URLDataSourceImpl(
           source_name,
-          new InternalDataSource(ALLOW_THIS_IN_INITIALIZER_LIST(this))),
+          new InternalDataSource(this)),
       source_name_(source_name),
       default_resource_(-1),
       json_js_format_v2_(false),
@@ -152,7 +154,7 @@
   deny_xframe_options_ = false;
 }
 
-std::string WebUIDataSourceImpl::GetSource() {
+std::string WebUIDataSourceImpl::GetSource() const {
   return source_name_;
 }
 
@@ -171,7 +173,8 @@
 
 void WebUIDataSourceImpl::StartDataRequest(
     const std::string& path,
-    bool is_incognito,
+    int render_process_id,
+    int render_view_id,
     const URLDataSource::GotDataCallback& callback) {
   if (!filter_callback_.is_null() &&
       filter_callback_.Run(path, callback)) {
diff --git a/content/browser/webui/web_ui_data_source_impl.h b/content/browser/webui/web_ui_data_source_impl.h
index 9553a03..98f0a89 100644
--- a/content/browser/webui/web_ui_data_source_impl.h
+++ b/content/browser/webui/web_ui_data_source_impl.h
@@ -70,11 +70,12 @@
 
   // Methods that match URLDataSource which are called by
   // InternalDataSource.
-  std::string GetSource();
+  std::string GetSource() const;
   std::string GetMimeType(const std::string& path) const;
   void StartDataRequest(
       const std::string& path,
-      bool is_incognito,
+      int render_process_id,
+      int render_view_id,
       const URLDataSource::GotDataCallback& callback);
 
   void disable_set_font_strings_for_testing() {
diff --git a/content/browser/webui/web_ui_data_source_unittest.cc b/content/browser/webui/web_ui_data_source_unittest.cc
index b58161c..1a5efb7 100644
--- a/content/browser/webui/web_ui_data_source_unittest.cc
+++ b/content/browser/webui/web_ui_data_source_unittest.cc
@@ -52,14 +52,14 @@
 
 class WebUIDataSourceTest : public testing::Test {
  public:
-  WebUIDataSourceTest() : result_data_(NULL), old_client_(NULL) {}
+  WebUIDataSourceTest() : result_data_(NULL) {}
   virtual ~WebUIDataSourceTest() {}
   WebUIDataSourceImpl* source() { return source_.get(); }
 
   void StartDataRequest(const std::string& path) {
      source_->StartDataRequest(
         path,
-        false,
+        0, 0,
         base::Bind(&WebUIDataSourceTest::SendResult,
         base::Unretained(this)));
   }
@@ -72,7 +72,6 @@
 
  private:
   virtual void SetUp() {
-    old_client_ = GetContentClient();
     SetContentClient(&client_);
     WebUIDataSource* source = WebUIDataSourceImpl::Create("host");
     WebUIDataSourceImpl* source_impl = static_cast<WebUIDataSourceImpl*>(
@@ -81,10 +80,6 @@
     source_ = make_scoped_refptr(source_impl);
   }
 
-  virtual void TearDown() {
-    SetContentClient(old_client_);
-  }
-
   // Store response for later comparisons.
   void SendResult(base::RefCountedMemory* data) {
     result_data_ = data;
@@ -92,7 +87,6 @@
 
   scoped_refptr<WebUIDataSourceImpl> source_;
   TestClient client_;
-  ContentClient* old_client_;
 };
 
 TEST_F(WebUIDataSourceTest, EmptyStrings) {
@@ -147,7 +141,7 @@
 TEST_F(WebUIDataSourceTest, MimeType) {
   const char* html = "text/html";
   const char* js = "application/javascript";
-  EXPECT_EQ(GetMimeType(""), html);
+  EXPECT_EQ(GetMimeType(std::string()), html);
   EXPECT_EQ(GetMimeType("foo"), html);
   EXPECT_EQ(GetMimeType("foo.html"), html);
   EXPECT_EQ(GetMimeType(".js"), js);
diff --git a/content/browser/webui/web_ui_impl.cc b/content/browser/webui/web_ui_impl.cc
index 5155702..88b181b 100644
--- a/content/browser/webui/web_ui_impl.cc
+++ b/content/browser/webui/web_ui_impl.cc
@@ -45,10 +45,7 @@
 }
 
 WebUIImpl::WebUIImpl(WebContents* contents)
-    : hide_favicon_(false),
-      focus_location_bar_by_default_(false),
-      should_hide_url_(false),
-      link_transition_type_(PAGE_TRANSITION_LINK),
+    : link_transition_type_(PAGE_TRANSITION_LINK),
       bindings_(BINDINGS_POLICY_WEB_UI),
       web_contents_(contents) {
   DCHECK(contents);
@@ -111,30 +108,6 @@
   return GetScaleFactorForView(web_contents_->GetRenderWidgetHostView());
 }
 
-bool WebUIImpl::ShouldHideFavicon() const {
-  return hide_favicon_;
-}
-
-void WebUIImpl::HideFavicon() {
-  hide_favicon_ = true;
-}
-
-bool WebUIImpl::ShouldFocusLocationBarByDefault() const {
-  return focus_location_bar_by_default_;
-}
-
-void WebUIImpl::FocusLocationBarByDefault() {
-  focus_location_bar_by_default_ = true;
-}
-
-bool WebUIImpl::ShouldHideURL() const {
-  return should_hide_url_;
-}
-
-void WebUIImpl::HideURL() {
-  should_hide_url_ = true;
-}
-
 const string16& WebUIImpl::GetOverriddenTitle() const {
   return overridden_title_;
 }
diff --git a/content/browser/webui/web_ui_impl.h b/content/browser/webui/web_ui_impl.h
index 49d9b4b..1be3674 100644
--- a/content/browser/webui/web_ui_impl.h
+++ b/content/browser/webui/web_ui_impl.h
@@ -32,12 +32,6 @@
   virtual WebUIController* GetController() const OVERRIDE;
   virtual void SetController(WebUIController* controller) OVERRIDE;
   virtual ui::ScaleFactor GetDeviceScaleFactor() const OVERRIDE;
-  virtual bool ShouldHideFavicon() const OVERRIDE;
-  virtual void HideFavicon() OVERRIDE;
-  virtual bool ShouldFocusLocationBarByDefault() const OVERRIDE;
-  virtual void FocusLocationBarByDefault() OVERRIDE;
-  virtual bool ShouldHideURL() const OVERRIDE;
-  virtual void HideURL() OVERRIDE;
   virtual const string16& GetOverriddenTitle() const OVERRIDE;
   virtual void OverrideTitle(const string16& title) OVERRIDE;
   virtual PageTransition GetLinkTransitionType() const OVERRIDE;
@@ -91,9 +85,6 @@
 
   // 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 focus_location_bar_by_default_;
-  bool should_hide_url_;
   string16 overridden_title_;  // Defaults to empty string.
   PageTransition link_transition_type_;  // Defaults to LINK.
   int bindings_;  // The bindings from BindingsPolicy that should be enabled for
diff --git a/content/browser/worker_host/test/worker_browsertest.cc b/content/browser/worker_host/test/worker_browsertest.cc
index 7928718..b6ab62f 100644
--- a/content/browser/worker_host/test/worker_browsertest.cc
+++ b/content/browser/worker_host/test/worker_browsertest.cc
@@ -24,7 +24,7 @@
 #include "content/test/layout_browsertest.h"
 #include "googleurl/src/gurl.h"
 #include "net/base/test_data_directory.h"
-#include "net/test/test_server.h"
+#include "net/test/spawned_test_server.h"
 
 namespace content {
 
@@ -260,7 +260,7 @@
     for (WorkerProcessHostIterator iter; !iter.Done(); ++iter)
       (*cur_process_count)++;
     BrowserThread::PostTask(
-        BrowserThread::UI, FROM_HERE, MessageLoop::QuitClosure());
+        BrowserThread::UI, FROM_HERE, base::MessageLoop::QuitClosure());
   }
 
   bool WaitForWorkerProcessCount(int count) {
@@ -289,7 +289,7 @@
 
   void NavigateAndWaitForAuth(const GURL& url) {
     ShellContentBrowserClient* browser_client =
-        static_cast<ShellContentBrowserClient*>(GetContentClient()->browser());
+        ShellContentBrowserClient::Get();
     scoped_refptr<MessageLoopRunner> runner = new MessageLoopRunner();
     browser_client->resource_dispatcher_host_delegate()->
         set_login_request_callback(
@@ -300,11 +300,11 @@
 };
 
 IN_PROC_BROWSER_TEST_F(WorkerTest, SingleWorker) {
-  RunTest("single_worker.html", "");
+  RunTest("single_worker.html", std::string());
 }
 
 IN_PROC_BROWSER_TEST_F(WorkerTest, MultipleWorkers) {
-  RunTest("multi_worker.html", "");
+  RunTest("multi_worker.html", std::string());
 }
 
 IN_PROC_BROWSER_TEST_F(WorkerTest, SingleSharedWorker) {
@@ -320,10 +320,10 @@
 // http://crbug.com/30021
 IN_PROC_BROWSER_TEST_F(WorkerTest, IncognitoSharedWorkers) {
   // Load a non-incognito tab and have it create a shared worker
-  RunTest("incognito_worker.html", "");
+  RunTest("incognito_worker.html", std::string());
 
   // Incognito worker should not share with non-incognito
-  RunTest(CreateOffTheRecordBrowser(), "incognito_worker.html", "");
+  RunTest(CreateOffTheRecordBrowser(), "incognito_worker.html", std::string());
 }
 
 // Make sure that auth dialog is displayed from worker context.
@@ -399,7 +399,7 @@
 
 // Flaky, http://crbug.com/59786.
 IN_PROC_BROWSER_TEST_F(WorkerTest, WorkerClose) {
-  RunTest("worker_close.html", "");
+  RunTest("worker_close.html", std::string());
   ASSERT_TRUE(WaitForWorkerProcessCount(0));
 }
 
@@ -466,9 +466,9 @@
 
 IN_PROC_BROWSER_TEST_F(WorkerTest, WebSocketSharedWorker) {
   // Launch WebSocket server.
-  net::TestServer ws_server(net::TestServer::TYPE_WS,
-                            net::TestServer::kLocalhost,
-                            net::GetWebSocketTestDataDirectory());
+  net::SpawnedTestServer ws_server(net::SpawnedTestServer::TYPE_WS,
+                                   net::SpawnedTestServer::kLocalhost,
+                                   net::GetWebSocketTestDataDirectory());
   ASSERT_TRUE(ws_server.Start());
 
   // Generate test URL.
diff --git a/content/browser/worker_host/worker_process_host.cc b/content/browser/worker_host/worker_process_host.cc
index faad9e2..f340df7 100644
--- a/content/browser/worker_host/worker_process_host.cc
+++ b/content/browser/worker_host/worker_process_host.cc
@@ -174,7 +174,6 @@
 #endif
     switches::kDisableFileSystem,
     switches::kDisableSeccompFilterSandbox,
-    switches::kDisableWebSockets,
 #if defined(OS_MACOSX)
     switches::kEnableSandboxLogging,
 #endif
diff --git a/content/browser/worker_host/worker_storage_partition.cc b/content/browser/worker_host/worker_storage_partition.cc
index f9d47d1..994f729 100644
--- a/content/browser/worker_host/worker_storage_partition.cc
+++ b/content/browser/worker_host/worker_storage_partition.cc
@@ -7,7 +7,7 @@
 #include <string>
 
 #include "content/browser/appcache/chrome_appcache_service.h"
-#include "content/browser/in_process_webkit/indexed_db_context_impl.h"
+#include "content/browser/indexed_db/indexed_db_context_impl.h"
 #include "net/url_request/url_request_context_getter.h"
 #include "webkit/database/database_tracker.h"
 #include "webkit/fileapi/file_system_context.h"
diff --git a/content/browser/zygote_host/zygote_host_impl_linux.cc b/content/browser/zygote_host/zygote_host_impl_linux.cc
index 2251b12..ba7884f 100644
--- a/content/browser/zygote_host/zygote_host_impl_linux.cc
+++ b/content/browser/zygote_host/zygote_host_impl_linux.cc
@@ -101,9 +101,7 @@
     switches::kV,
     switches::kVModule,
     switches::kRegisterPepperPlugins,
-    switches::kDisableSeccompSandbox,
     switches::kDisableSeccompFilterSandbox,
-    switches::kEnableSeccompSandbox,
 
     // Zygote process needs to know what resources to have loaded when it
     // becomes a renderer process.
@@ -373,9 +371,12 @@
 
   if (!selinux_valid) {
     const base::FilePath kSelinuxPath("/selinux");
+    file_util::FileEnumerator en(kSelinuxPath, false,
+                                 file_util::FileEnumerator::FILES);
+    bool has_selinux_files = !en.Next().empty();
+
     selinux = access(kSelinuxPath.value().c_str(), X_OK) == 0 &&
-        file_util::CountFilesCreatedAfter(kSelinuxPath,
-                                          base::Time::UnixEpoch()) > 0;
+              has_selinux_files;
     selinux_valid = true;
   }
 
diff --git a/content/common/DEPS b/content/common/DEPS
index e09f27a..a03ed69 100644
--- a/content/common/DEPS
+++ b/content/common/DEPS
@@ -3,5 +3,4 @@
   "+components/tracing",
   "+media/audio",
   "+media/base",
-  "+sandbox/linux/seccomp-legacy",
 ]
diff --git a/content/common/OWNERS b/content/common/OWNERS
index af049b9..0d10d79 100644
--- a/content/common/OWNERS
+++ b/content/common/OWNERS
@@ -3,9 +3,9 @@
 jln@chromium.org
 
 # For security review of sandboxes
-per-file sandbox_policy.cc=set noparent
-per-file sandbox_policy.cc=jschuh@chromium.org
-per-file sandbox_policy.cc=cpu@chromium.org
+per-file sandbox_win.cc=set noparent
+per-file sandbox_win.cc=jschuh@chromium.org
+per-file sandbox_win.cc=cpu@chromium.org
 
 # Mac Sandbox.
 per-file sandbox_init_mac.*=jeremy@chromium.org
@@ -20,6 +20,7 @@
 per-file *_messages.h=jschuh@chromium.org
 per-file *_messages.h=palmer@chromium.org
 per-file *_messages.h=tsepez@chromium.org
+per-file *_messages.h=kenrb@chromium.org
 
 # Accessibility
 per-file accessibility_node_data.*=dmazzoni@chromium.org
diff --git a/content/common/accessibility_node_data.cc b/content/common/accessibility_node_data.cc
index a34b376..cf00e06 100644
--- a/content/common/accessibility_node_data.cc
+++ b/content/common/accessibility_node_data.cc
@@ -336,16 +336,31 @@
       case ATTR_TABLE_CELL_ROW_SPAN:
         result += " rowspan=" + value;
         break;
-    case ATTR_TITLE_UI_ELEMENT:
+      case ATTR_TABLE_COLUMN_HEADER_ID:
+        result += " column_header_id=" + value;
+        break;
+      case ATTR_TABLE_COLUMN_INDEX:
+        result += " column_index=" + value;
+        break;
+      case ATTR_TABLE_HEADER_ID:
+        result += " header_id=" + value;
+        break;
+      case ATTR_TABLE_ROW_HEADER_ID:
+        result += " row_header_id=" + value;
+        break;
+      case ATTR_TABLE_ROW_INDEX:
+        result += " row_index=" + value;
+        break;
+      case ATTR_TITLE_UI_ELEMENT:
         result += " title_elem=" + value;
         break;
-    case ATTR_COLOR_VALUE_RED:
+      case ATTR_COLOR_VALUE_RED:
         result += " color_value_red=" + value;
         break;
-    case ATTR_COLOR_VALUE_GREEN:
+      case ATTR_COLOR_VALUE_GREEN:
         result += " color_value_green=" + value;
         break;
-    case ATTR_COLOR_VALUE_BLUE:
+      case ATTR_COLOR_VALUE_BLUE:
         result += " color_value_blue=" + value;
         break;
     }
@@ -459,9 +474,12 @@
       case ATTR_ARIA_READONLY:
         result += " aria_readonly=" + value;
         break;
-    case ATTR_CAN_SET_VALUE:
+      case ATTR_CAN_SET_VALUE:
         result += " can_set_value=" + value;
         break;
+      case ATTR_UPDATE_LOCATION_ONLY:
+        result += " update_location_only=" + value;
+        break;
     }
   }
 
diff --git a/content/common/accessibility_node_data.h b/content/common/accessibility_node_data.h
index 94eeb2e..6b9f8cd 100644
--- a/content/common/accessibility_node_data.h
+++ b/content/common/accessibility_node_data.h
@@ -214,6 +214,15 @@
     // Table attributes.
     ATTR_TABLE_ROW_COUNT,
     ATTR_TABLE_COLUMN_COUNT,
+    ATTR_TABLE_HEADER_ID,
+
+    // Table row attributes.
+    ATTR_TABLE_ROW_INDEX,
+    ATTR_TABLE_ROW_HEADER_ID,
+
+    // Table column attributes.
+    ATTR_TABLE_COLUMN_INDEX,
+    ATTR_TABLE_COLUMN_HEADER_ID,
 
     // Table cell attributes.
     ATTR_TABLE_CELL_COLUMN_INDEX,
@@ -261,6 +270,10 @@
 
     // Writeable attributes
     ATTR_CAN_SET_VALUE,
+
+    // If this is set, all of the other fields in this struct should
+    // be ignored and only the locations should change.
+    ATTR_UPDATE_LOCATION_ONLY,
   };
 
   AccessibilityNodeData();
diff --git a/content/common/android/common_jni_registrar.cc b/content/common/android/common_jni_registrar.cc
index bf774e6..fd7f2a6 100644
--- a/content/common/android/common_jni_registrar.cc
+++ b/content/common/android/common_jni_registrar.cc
@@ -9,7 +9,6 @@
 #include "content/common/android/command_line.h"
 #include "content/common/android/device_telephony_info.h"
 #include "content/common/android/hash_set.h"
-#include "content/common/android/surface_texture_listener.h"
 #include "content/common/android/trace_event_binding.h"
 #include "webkit/glue/fling_animator_impl_android.h"
 
@@ -20,8 +19,6 @@
         content::DeviceTelephonyInfo::RegisterDeviceTelephonyInfo },
   { "FlingAnimator", webkit_glue::FlingAnimatorImpl::RegisterJni },
   { "HashSet", content::RegisterHashSet },
-  { "SurfaceTextureListener",
-        content::SurfaceTextureListener::RegisterSurfaceTextureListener },
   { "TraceEvent", RegisterTraceEvent },
 };
 
diff --git a/content/common/android/scoped_java_surface.cc b/content/common/android/scoped_java_surface.cc
deleted file mode 100644
index ca84f72..0000000
--- a/content/common/android/scoped_java_surface.cc
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/common/android/scoped_java_surface.h"
-
-#include "base/logging.h"
-#include "content/common/android/surface_texture_bridge.h"
-#include "jni/Surface_jni.h"
-
-namespace {
-
-bool g_jni_initialized = false;
-
-void RegisterNativesIfNeeded(JNIEnv* env) {
-  if (!g_jni_initialized) {
-    JNI_Surface::RegisterNativesImpl(env);
-    g_jni_initialized = true;
-  }
-}
-
-}  // anonymous namespace
-
-namespace content {
-
-ScopedJavaSurface::ScopedJavaSurface() {
-}
-
-ScopedJavaSurface::ScopedJavaSurface(
-    const base::android::JavaRef<jobject>& surface) {
-  JNIEnv* env = base::android::AttachCurrentThread();
-  RegisterNativesIfNeeded(env);
-  DCHECK(env->IsInstanceOf(surface.obj(), g_Surface_clazz));
-  j_surface_.Reset(surface);
-}
-
-ScopedJavaSurface::ScopedJavaSurface(
-    const SurfaceTextureBridge* surface_texture) {
-  JNIEnv* env = base::android::AttachCurrentThread();
-  RegisterNativesIfNeeded(env);
-  ScopedJavaLocalRef<jobject> tmp(JNI_Surface::Java_Surface_Constructor(
-      env, surface_texture->j_surface_texture().obj()));
-  DCHECK(!tmp.is_null());
-  j_surface_.Reset(tmp);
-}
-
-ScopedJavaSurface::~ScopedJavaSurface() {
-  if (!j_surface_.is_null()) {
-    JNIEnv* env = base::android::AttachCurrentThread();
-    JNI_Surface::Java_Surface_release(env, j_surface_.obj());
-  }
-}
-
-}  // namespace content
diff --git a/content/common/android/scoped_java_surface.h b/content/common/android/scoped_java_surface.h
deleted file mode 100644
index de0b673..0000000
--- a/content/common/android/scoped_java_surface.h
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_COMMON_ANDROID_SCOPED_JAVA_SURFACE_H_
-#define CONTENT_COMMON_ANDROID_SCOPED_JAVA_SURFACE_H_
-
-#include <jni.h>
-
-#include "base/android/scoped_java_ref.h"
-
-namespace content {
-
-class SurfaceTextureBridge;
-
-// A helper class for holding a scoped reference to a Java Surface instance.
-// When going out of scope, Surface.release() is called on the Java object to
-// make sure server-side references (esp. wrt graphics memory) are released.
-class ScopedJavaSurface {
- public:
-  ScopedJavaSurface();
-
-  // Wraps an existing Java Surface object in a ScopedJavaSurface.
-  explicit ScopedJavaSurface(const base::android::JavaRef<jobject>& surface);
-
-  // Creates a Java Surface from a SurfaceTexture and wraps it in a
-  // ScopedJavaSurface.
-  explicit ScopedJavaSurface(const SurfaceTextureBridge* surface_texture);
-
-  ~ScopedJavaSurface();
-
-  const base::android::JavaRef<jobject>& j_surface() const {
-    return j_surface_;
-  }
-
- private:
-  base::android::ScopedJavaGlobalRef<jobject> j_surface_;
-};
-
-}  // namespace content
-
-#endif  // CONTENT_COMMON_ANDROID_SCOPED_JAVA_SURFACE_H_
diff --git a/content/common/android/surface_texture_bridge.cc b/content/common/android/surface_texture_bridge.cc
deleted file mode 100644
index 7f9d710..0000000
--- a/content/common/android/surface_texture_bridge.cc
+++ /dev/null
@@ -1,147 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/common/android/surface_texture_bridge.h"
-
-#include <android/native_window_jni.h>
-
-// TODO(boliu): Remove this include when we move off ICS.
-#include "base/android/build_info.h"
-#include "base/android/jni_android.h"
-#include "base/logging.h"
-#include "content/common/android/scoped_java_surface.h"
-#include "content/common/android/surface_texture_listener.h"
-#include "jni/SurfaceTexture_jni.h"
-
-using base::android::AttachCurrentThread;
-using base::android::CheckException;
-using base::android::GetClass;
-using base::android::ScopedJavaLocalRef;
-
-namespace {
-bool g_jni_initialized = false;
-
-void RegisterNativesIfNeeded(JNIEnv* env) {
-  if (!g_jni_initialized) {
-    JNI_SurfaceTexture::RegisterNativesImpl(env);
-    g_jni_initialized = true;
-  }
-}
-
-// TODO(boliu): Remove this method when when we move off ICS. See
-// http://crbug.com/161864.
-bool GlContextMethodsAvailable() {
-  bool available = base::android::BuildInfo::GetInstance()->sdk_int() >= 16;
-  if (!available)
-    LOG(WARNING) << "Running on unsupported device: rendering may not work";
-  return available;
-}
-
-}  // namespace
-
-namespace content {
-
-SurfaceTextureBridge::SurfaceTextureBridge(int texture_id)
-    : texture_id_(texture_id) {
-  JNIEnv* env = AttachCurrentThread();
-  CHECK(env);
-  RegisterNativesIfNeeded(env);
-
-  ScopedJavaLocalRef<jobject> tmp(
-      JNI_SurfaceTexture::Java_SurfaceTexture_Constructor(
-          env, texture_id));
-  DCHECK(!tmp.is_null());
-  j_surface_texture_.Reset(tmp);
-}
-
-SurfaceTextureBridge::~SurfaceTextureBridge() {
-  JNIEnv* env = AttachCurrentThread();
-  CHECK(env);
-
-  // Release the listener.
-  JNI_SurfaceTexture::Java_SurfaceTexture_setOnFrameAvailableListener(
-      env, j_surface_texture_.obj(), NULL);
-
-  // Release graphics memory.
-  JNI_SurfaceTexture::Java_SurfaceTexture_release(
-      env, j_surface_texture_.obj());
-}
-
-void SurfaceTextureBridge::SetFrameAvailableCallback(
-    const base::Closure& callback) {
-  JNIEnv* env = AttachCurrentThread();
-  CHECK(env);
-
-  // Since the listener is owned by the Java SurfaceTexture object, setting
-  // a new listener here will release an existing one at the same time.
-  ScopedJavaLocalRef<jobject> j_listener(
-      env,
-      SurfaceTextureListener::CreateSurfaceTextureListener(env, callback));
-  DCHECK(!j_listener.is_null());
-
-  // Set it as the onFrameAvailableListener for our SurfaceTexture instance.
-  JNI_SurfaceTexture::Java_SurfaceTexture_setOnFrameAvailableListener(
-      env, j_surface_texture_.obj(), j_listener.obj());
-}
-
-void SurfaceTextureBridge::UpdateTexImage() {
-  JNIEnv* env = AttachCurrentThread();
-  CHECK(env);
-
-  JNI_SurfaceTexture::Java_SurfaceTexture_updateTexImage(
-      env, j_surface_texture_.obj());
-}
-
-void SurfaceTextureBridge::GetTransformMatrix(float mtx[16]) {
-  JNIEnv* env = AttachCurrentThread();
-  CHECK(env);
-
-  ScopedJavaLocalRef<jfloatArray> jmatrix(env, env->NewFloatArray(16));
-  JNI_SurfaceTexture::Java_SurfaceTexture_getTransformMatrix(
-      env, j_surface_texture_.obj(), jmatrix.obj());
-
-  jboolean is_copy;
-  jfloat* elements = env->GetFloatArrayElements(jmatrix.obj(), &is_copy);
-  for (int i = 0; i < 16; ++i) {
-    mtx[i] = static_cast<float>(elements[i]);
-  }
-  env->ReleaseFloatArrayElements(jmatrix.obj(), elements, JNI_ABORT);
-}
-
-void SurfaceTextureBridge::SetDefaultBufferSize(int width, int height) {
-  JNIEnv* env = AttachCurrentThread();
-  CHECK(env);
-
-  JNI_SurfaceTexture::Java_SurfaceTexture_setDefaultBufferSize(
-      env, j_surface_texture_.obj(), static_cast<jint>(width),
-      static_cast<jint>(height));
-}
-
-void SurfaceTextureBridge::AttachToGLContext(int texture_id) {
-  if (GlContextMethodsAvailable()) {
-    JNIEnv* env = AttachCurrentThread();
-    // Note: This method is only available on JB and greater.
-    JNI_SurfaceTexture::Java_SurfaceTexture_attachToGLContext(
-        env, j_surface_texture_.obj(), texture_id);
-  }
-}
-
-void SurfaceTextureBridge::DetachFromGLContext() {
-  if (GlContextMethodsAvailable()) {
-    JNIEnv* env = AttachCurrentThread();
-    // Note: This method is only available on JB and greater.
-    JNI_SurfaceTexture::Java_SurfaceTexture_detachFromGLContext(
-        env, j_surface_texture_.obj());
-  }
-}
-
-ANativeWindow* SurfaceTextureBridge::CreateSurface() {
-  JNIEnv* env = AttachCurrentThread();
-  ScopedJavaSurface surface(this);
-  ANativeWindow* native_window =
-      ANativeWindow_fromSurface(env, surface.j_surface().obj());
-  return native_window;
-}
-
-}  // namespace content
diff --git a/content/common/android/surface_texture_bridge.h b/content/common/android/surface_texture_bridge.h
deleted file mode 100644
index 0779196..0000000
--- a/content/common/android/surface_texture_bridge.h
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_COMMON_ANDROID_SURFACE_TEXTURE_BRIDGE_H_
-#define CONTENT_COMMON_ANDROID_SURFACE_TEXTURE_BRIDGE_H_
-
-#include <jni.h>
-
-#include "base/android/scoped_java_ref.h"
-#include "base/callback.h"
-#include "base/memory/ref_counted.h"
-
-struct ANativeWindow;
-
-namespace content {
-
-// This class serves as a bridge for native code to call java functions inside
-// android SurfaceTexture class.
-class SurfaceTextureBridge
-    : public base::RefCountedThreadSafe<SurfaceTextureBridge>{
- public:
-  explicit SurfaceTextureBridge(int texture_id);
-
-  // Set the listener callback, which will be invoked on the same thread that
-  // is being called from here for registration.
-  // Note: Since callbacks come in from Java objects that might outlive objects
-  // being referenced from the callback, the only robust way here is to create
-  // the callback from a weak pointer to your object.
-  void SetFrameAvailableCallback(const base::Closure& callback);
-
-  // Update the texture image to the most recent frame from the image stream.
-  void UpdateTexImage();
-
-  // Retrieve the 4x4 texture coordinate transform matrix associated with the
-  // texture image set by the most recent call to updateTexImage.
-  void GetTransformMatrix(float mtx[16]);
-
-  // Set the default size of the image buffers.
-  void SetDefaultBufferSize(int width, int height);
-
-  // Attach the SurfaceTexture to the given texture in the GL context that is
-  // current on the calling thread.
-  void AttachToGLContext(int texture_id);
-
-  // Detaches the SurfaceTexture from the context that owns its current GL
-  // texture. Must be called with that context current on the calling thread.
-  void DetachFromGLContext();
-
-  // Creates a native render surface for this surface texture.
-  // The caller must release the underlying reference when done with the handle
-  // by calling ANativeWindow_release().
-  ANativeWindow* CreateSurface();
-
-  int texture_id() const {
-    return texture_id_;
-  }
-
-  const base::android::JavaRef<jobject>& j_surface_texture() const {
-    return j_surface_texture_;
-  }
-
- private:
-  friend class base::RefCountedThreadSafe<SurfaceTextureBridge>;
-  ~SurfaceTextureBridge();
-
-  const int texture_id_;
-
-  // Java SurfaceTexture instance.
-  base::android::ScopedJavaGlobalRef<jobject> j_surface_texture_;
-
-  DISALLOW_COPY_AND_ASSIGN(SurfaceTextureBridge);
-};
-
-}  // namespace content
-
-#endif  // CONTENT_COMMON_ANDROID_SURFACE_TEXTURE_BRIDGE_H_
diff --git a/content/common/android/surface_texture_listener.cc b/content/common/android/surface_texture_listener.cc
deleted file mode 100644
index 4440c5c..0000000
--- a/content/common/android/surface_texture_listener.cc
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/common/android/surface_texture_listener.h"
-
-#include "base/location.h"
-#include "base/logging.h"
-#include "base/message_loop_proxy.h"
-#include "content/common/android/surface_texture_bridge.h"
-#include "jni/SurfaceTextureListener_jni.h"
-
-namespace content {
-
-// static
-jobject SurfaceTextureListener::CreateSurfaceTextureListener(
-    JNIEnv* env,
-    const base::Closure& callback) {
-  // The java listener object owns and releases the native instance.
-  // This is necessary to avoid races with incoming notifications.
-  ScopedJavaLocalRef<jobject> listener(Java_SurfaceTextureListener_create(env,
-      reinterpret_cast<int>(new SurfaceTextureListener(callback))));
-
-  DCHECK(!listener.is_null());
-  return listener.Release();
-}
-
-SurfaceTextureListener::SurfaceTextureListener(const base::Closure& callback)
-    : callback_(callback),
-      browser_loop_(base::MessageLoopProxy::current()) {
-}
-
-SurfaceTextureListener::~SurfaceTextureListener() {
-}
-
-void SurfaceTextureListener::Destroy(JNIEnv* env, jobject obj) {
-  delete this;
-}
-
-void SurfaceTextureListener::FrameAvailable(JNIEnv* env, jobject obj) {
-  if (!browser_loop_->BelongsToCurrentThread()) {
-    browser_loop_->PostTask(FROM_HERE, callback_);
-  } else {
-    callback_.Run();
-  }
-}
-
-// static
-bool SurfaceTextureListener::RegisterSurfaceTextureListener(JNIEnv* env) {
-  return RegisterNativesImpl(env);
-}
-
-}  // namespace content
diff --git a/content/common/android/surface_texture_listener.h b/content/common/android/surface_texture_listener.h
deleted file mode 100644
index 32cad7f..0000000
--- a/content/common/android/surface_texture_listener.h
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_COMMON_ANDROID_SURFACE_TEXTURE_LISTENER_H_
-#define CONTENT_COMMON_ANDROID_SURFACE_TEXTURE_LISTENER_H_
-
-#include <jni.h>
-#include "base/callback.h"
-#include "base/memory/ref_counted.h"
-
-namespace base {
-class MessageLoopProxy;
-}
-
-namespace content {
-
-// Listener class for all the callbacks from android SurfaceTexture.
-class SurfaceTextureListener {
-public:
-  // Destroy this listener.
-  void Destroy(JNIEnv* env, jobject obj);
-
-  // A new frame is available to consume.
-  void FrameAvailable(JNIEnv* env, jobject obj);
-
-  static bool RegisterSurfaceTextureListener(JNIEnv* env);
-
-private:
-  SurfaceTextureListener(const base::Closure& callback);
-  ~SurfaceTextureListener();
-
-  friend class SurfaceTextureBridge;
-
-  // Static factory method for the creation of a SurfaceTextureListener.
-  // The native code should not hold any reference to the returned object,
-  // but only use it to pass it up to Java for being referenced by a
-  // SurfaceTexture instance.
-  static jobject CreateSurfaceTextureListener(JNIEnv* env,
-                                              const base::Closure& callback);
-
-  base::Closure callback_;
-
-  scoped_refptr<base::MessageLoopProxy> browser_loop_;
-
-  DISALLOW_IMPLICIT_CONSTRUCTORS(SurfaceTextureListener);
-};
-
-}  // namespace content
-
-#endif  // CONTENT_COMMON_ANDROID_SURFACE_TEXTURE_LISTENER_H_
diff --git a/content/common/android/surface_texture_peer.h b/content/common/android/surface_texture_peer.h
index 921ff4c..0e1fbcc 100644
--- a/content/common/android/surface_texture_peer.h
+++ b/content/common/android/surface_texture_peer.h
@@ -6,7 +6,7 @@
 #define CONTENT_COMMON_ANDROID_SURFACE_TEXTURE_PEER_H_
 
 #include "base/process.h"
-#include "content/common/android/surface_texture_bridge.h"
+#include "ui/gl/android/surface_texture_bridge.h"
 
 namespace content {
 
@@ -20,7 +20,7 @@
   // process.
   virtual void EstablishSurfaceTexturePeer(
       base::ProcessHandle pid,
-      scoped_refptr<SurfaceTextureBridge> surface_texture_bridge,
+      scoped_refptr<gfx::SurfaceTextureBridge> surface_texture_bridge,
       int primary_id,
       int secondary_id) = 0;
 
diff --git a/content/common/android/trace_event_binding.cc b/content/common/android/trace_event_binding.cc
index 04607ed..ec70335 100644
--- a/content/common/android/trace_event_binding.cc
+++ b/content/common/android/trace_event_binding.cc
@@ -89,9 +89,11 @@
   TraceEventDataConverter converter(env, jname, jarg);
   if (converter.arg()) {
     TRACE_EVENT_COPY_INSTANT1(kJavaCategory, converter.name(),
+                              TRACE_EVENT_SCOPE_THREAD,
                               converter.arg_name(), converter.arg());
   } else {
-    TRACE_EVENT_COPY_INSTANT0(kJavaCategory, converter.name());
+    TRACE_EVENT_COPY_INSTANT0(kJavaCategory, converter.name(),
+                              TRACE_EVENT_SCOPE_THREAD);
   }
 }
 
diff --git a/content/common/browser_plugin/browser_plugin_constants.cc b/content/common/browser_plugin/browser_plugin_constants.cc
index f486917..4c11cff 100644
--- a/content/common/browser_plugin/browser_plugin_constants.cc
+++ b/content/common/browser_plugin/browser_plugin_constants.cc
@@ -37,6 +37,8 @@
 const char kAttributeSrc[] = "src";
 
 // Events.
+const char kEventClose[] = "close";
+const char kEventConsoleMessage[] = "consolemessage";
 const char kEventExit[] = "exit";
 const char kEventLoadAbort[] = "loadabort";
 const char kEventLoadCommit[] = "loadcommit";
@@ -54,6 +56,9 @@
 const char kInitialWidth[] = "initialWidth";
 const char kIsTopLevel[] = "isTopLevel";
 const char kLastUnlockedBySelf[] = "lastUnlockedBySelf";
+const char kLevel[] = "level";
+const char kLine[] = "line";
+const char kMessage[] = "message";
 const char kName[] = "name";
 const char kNewURL[] = "newUrl";
 const char kNewHeight[] = "newHeight";
@@ -62,6 +67,7 @@
 const char kOldHeight[] = "oldHeight";
 const char kOldWidth[] = "oldWidth";
 const char kPermission[] = "permission";
+const char kPermissionTypeDownload[] = "download";
 const char kPermissionTypeGeolocation[] = "geolocation";
 const char kPermissionTypeMedia[] = "media";
 const char kPermissionTypeNewWindow[] = "newwindow";
@@ -70,6 +76,8 @@
 const char kProcessId[] = "processId";
 const char kReason[] = "reason";
 const char kRequestId[] = "requestId";
+const char kRequestMethod[] = "requestMethod";
+const char kSourceId[] = "sourceId";
 const char kTargetURL[] = "targetUrl";
 const char kURL[] = "url";
 const char kWindowID[] = "windowId";
diff --git a/content/common/browser_plugin/browser_plugin_constants.h b/content/common/browser_plugin/browser_plugin_constants.h
index 3dc489d..98af916 100644
--- a/content/common/browser_plugin/browser_plugin_constants.h
+++ b/content/common/browser_plugin/browser_plugin_constants.h
@@ -38,6 +38,8 @@
 extern const char kAttributeSrc[];
 
 // Events.
+extern const char kEventClose[];
+extern const char kEventConsoleMessage[];
 extern const char kEventExit[];
 extern const char kEventLoadAbort[];
 extern const char kEventLoadCommit[];
@@ -55,6 +57,9 @@
 extern const char kInitialWidth[];
 extern const char kIsTopLevel[];
 extern const char kLastUnlockedBySelf[];
+extern const char kLevel[];
+extern const char kLine[];
+extern const char kMessage[];
 extern const char kName[];
 extern const char kNewURL[];
 extern const char kNewHeight[];
@@ -63,6 +68,7 @@
 extern const char kOldHeight[];
 extern const char kOldWidth[];
 extern const char kPermission[];
+extern const char kPermissionTypeDownload[];
 extern const char kPermissionTypeGeolocation[];
 extern const char kPermissionTypeMedia[];
 extern const char kPermissionTypeNewWindow[];
@@ -71,6 +77,8 @@
 extern const char kProcessId[];
 extern const char kReason[];
 extern const char kRequestId[];
+extern const char kRequestMethod[];
+extern const char kSourceId[];
 extern const char kTargetURL[];
 extern const char kURL[];
 extern const char kUserGesture[];
diff --git a/content/common/browser_plugin/browser_plugin_message_enums.h b/content/common/browser_plugin/browser_plugin_message_enums.h
index c4ea346..9fe045a 100644
--- a/content/common/browser_plugin/browser_plugin_message_enums.h
+++ b/content/common/browser_plugin/browser_plugin_message_enums.h
@@ -9,20 +9,24 @@
   // Unknown type of permission request.
   BrowserPluginPermissionTypeUnknown,
 
+  // Download.
+  BrowserPluginPermissionTypeDownload,
+
+  // Geolocation.
+  BrowserPluginPermissionTypeGeolocation,
+
+  // Media access (audio/video) permission request type.
+  BrowserPluginPermissionTypeMedia,
+
+  // PointerLock
+  BrowserPluginPermissionTypePointerLock,
+
+
   // New window requests.
   // Note: Even though new windows don't use the permission API, the new window
   // API is sufficiently similar that it's convenient to consider it a
   // permission type for code reuse.
   BrowserPluginPermissionTypeNewWindow,
-
-  // Media access (audio/video) permission request type.
-  BrowserPluginPermissionTypeMedia,
-
-  // Geolocation.
-  BrowserPluginPermissionTypeGeolocation,
-
-  // PointerLock
-  BrowserPluginPermissionTypePointerLock,
 };
 
 #endif  // CONTENT_COMMON_BROWSER_PLUGIN_BROWSER_PLUGIN_MESSAGE_ENUMS_H_
diff --git a/content/common/browser_plugin/browser_plugin_messages.h b/content/common/browser_plugin/browser_plugin_messages.h
index 86d04f8..eb668e6 100644
--- a/content/common/browser_plugin/browser_plugin_messages.h
+++ b/content/common/browser_plugin/browser_plugin_messages.h
@@ -10,6 +10,8 @@
 #include "base/process.h"
 #include "base/shared_memory.h"
 #include "base/values.h"
+#include "cc/output/compositor_frame.h"
+#include "cc/output/compositor_frame_ack.h"
 #include "content/common/browser_plugin/browser_plugin_message_enums.h"
 #include "content/common/content_export.h"
 #include "content/common/content_param_traits.h"
@@ -58,7 +60,7 @@
   IPC_STRUCT_MEMBER(bool, repaint)
 IPC_STRUCT_END()
 
-IPC_STRUCT_BEGIN(BrowserPluginHostMsg_CreateGuest_Params)
+IPC_STRUCT_BEGIN(BrowserPluginHostMsg_Attach_Params)
   IPC_STRUCT_MEMBER(std::string, storage_partition_id)
   IPC_STRUCT_MEMBER(bool, persist_storage)
   IPC_STRUCT_MEMBER(bool, focused)
@@ -70,6 +72,12 @@
                     resize_guest_params)
 IPC_STRUCT_END()
 
+IPC_STRUCT_BEGIN(BrowserPluginMsg_Attach_ACK_Params)
+  IPC_STRUCT_MEMBER(std::string, storage_partition_id)
+  IPC_STRUCT_MEMBER(bool, persist_storage)
+  IPC_STRUCT_MEMBER(std::string, name)
+IPC_STRUCT_END()
+
 IPC_STRUCT_BEGIN(BrowserPluginMsg_LoadCommit_Params)
   // The current URL of the guest.
   IPC_STRUCT_MEMBER(GURL, url)
@@ -138,6 +146,12 @@
 IPC_MESSAGE_ROUTED1(BrowserPluginHostMsg_AllocateInstanceID,
                     int /* request_id */)
 
+// This message is sent from BrowserPlugin to BrowserPluginGuest to issue an
+// edit command.
+IPC_MESSAGE_ROUTED2(BrowserPluginHostMsg_ExecuteEditCommand,
+                     int /* instance_id */,
+                     std::string /* command */)
+
 // This message is sent to the browser process to enable or disable autosize
 // mode.
 IPC_MESSAGE_ROUTED3(
@@ -146,21 +160,14 @@
     BrowserPluginHostMsg_AutoSize_Params /* auto_size_params */,
     BrowserPluginHostMsg_ResizeGuest_Params /* resize_guest_params */)
 
-
-// This message is sent to the browser process to create the browser plugin
-// embedder and helper. It is sent once prior to sending the first
-// BrowserPluginHostMsg_NavigateGuest message.
-IPC_MESSAGE_ROUTED2(BrowserPluginHostMsg_CreateGuest,
-                    int /* instance_id */,
-                    BrowserPluginHostMsg_CreateGuest_Params /* params */)
-
 // This message is sent to the browser process to indicate that a BrowserPlugin
 // has taken ownership of the lifetime of the guest of the given |instance_id|.
-// |params| is the size information of the BrowserPlugin taking ownership of
-// the guest.
+// |params| is the state of the BrowserPlugin taking ownership of
+// the guest. If a guest doesn't already exist with the given |instance_id|,
+// a new one will be created.
 IPC_MESSAGE_ROUTED2(BrowserPluginHostMsg_Attach,
                     int /* instance_id */,
-                    BrowserPluginHostMsg_CreateGuest_Params /* params */)
+                    BrowserPluginHostMsg_Attach_Params /* params */)
 
 // Tells the browser process to terminate the guest associated with the
 // browser plugin associated with the provided |instance_id|.
@@ -220,6 +227,13 @@
                     std::string /* mailbox_name */,
                     uint32 /* sync_point */)
 
+// Acknowledge that we presented an ubercomp frame.
+IPC_MESSAGE_ROUTED4(BrowserPluginHostMsg_CompositorFrameACK,
+                    int /* instance_id */,
+                    int /* route_id */,
+                    int /* renderer_host_id */,
+                    cc::CompositorFrameAck /* ack */)
+
 // When a BrowserPlugin has been removed from the embedder's DOM, it informs
 // the browser process to cleanup the guest.
 IPC_MESSAGE_ROUTED1(BrowserPluginHostMsg_PluginDestroyed,
@@ -290,6 +304,22 @@
                     int /* request_id */,
                     int /* instance_id */)
 
+IPC_MESSAGE_CONTROL2(BrowserPluginMsg_AddMessageToConsole,
+                     int /* instance_id */,
+                     DictionaryValue /* message_info */)
+
+// This message is sent in response to a completed attachment of a guest
+// to a BrowserPlugin. This message carries information about the guest
+// that is used to update the attributes of the browser plugin.
+IPC_MESSAGE_CONTROL2(BrowserPluginMsg_Attach_ACK,
+                     int /* instance_id */,
+                     BrowserPluginMsg_Attach_ACK_Params /* params */)
+
+// When the guest's window requests to close, the embedder is informed through
+// the BrowserPluginMsg_Close message.
+IPC_MESSAGE_CONTROL1(BrowserPluginMsg_Close,
+                     int /* instance_id */)
+
 // Once the swapped out guest RenderView has been created in the embedder render
 // process, the browser process informs the embedder of its routing ID.
 IPC_MESSAGE_CONTROL2(BrowserPluginMsg_GuestContentWindowReady,
@@ -398,6 +428,12 @@
                      int /* route_id */,
                      int /* gpu_host_id */)
 
+IPC_MESSAGE_CONTROL4(BrowserPluginMsg_CompositorFrameSwapped,
+                     int /* instance_id */,
+                     cc::CompositorFrame /* frame */,
+                     int /* route_id */,
+                     int /* renderer_host_id */)
+
 // When the guest requests permission, the browser process forwards this
 // request to the embeddder through this message.
 IPC_MESSAGE_CONTROL4(BrowserPluginMsg_RequestPermission,
diff --git a/content/common/cc_messages.cc b/content/common/cc_messages.cc
index 5ec8ae8..f8e0d74 100644
--- a/content/common/cc_messages.cc
+++ b/content/common/cc_messages.cc
@@ -320,6 +320,9 @@
       case cc::DrawQuad::IO_SURFACE_CONTENT:
         WriteParam(m, *cc::IOSurfaceDrawQuad::MaterialCast(quad));
         break;
+      case cc::DrawQuad::PICTURE_CONTENT:
+        NOTREACHED();
+        break;
       case cc::DrawQuad::TEXTURE_CONTENT:
         WriteParam(m, *cc::TextureDrawQuad::MaterialCast(quad));
         break;
@@ -434,6 +437,9 @@
       case cc::DrawQuad::IO_SURFACE_CONTENT:
         draw_quad = ReadDrawQuad<cc::IOSurfaceDrawQuad>(m, iter);
         break;
+      case cc::DrawQuad::PICTURE_CONTENT:
+        NOTREACHED();
+        return false;
       case cc::DrawQuad::TEXTURE_CONTENT:
         draw_quad = ReadDrawQuad<cc::TextureDrawQuad>(m, iter);
         break;
@@ -513,6 +519,9 @@
       case cc::DrawQuad::IO_SURFACE_CONTENT:
         LogParam(*cc::IOSurfaceDrawQuad::MaterialCast(quad), l);
         break;
+      case cc::DrawQuad::PICTURE_CONTENT:
+        NOTREACHED();
+        break;
       case cc::DrawQuad::TEXTURE_CONTENT:
         LogParam(*cc::TextureDrawQuad::MaterialCast(quad), l);
         break;
@@ -618,7 +627,7 @@
 void ParamTraits<cc::CompositorFrameAck>::Write(Message* m,
                                                 const param_type& p) {
   WriteParam(m, p.resources);
-  WriteParam(m, p.last_content_dib);
+  WriteParam(m, p.last_dib_id);
   if (p.gl_frame_data) {
     WriteParam(m, static_cast<int>(GL_FRAME));
     WriteParam(m, *p.gl_frame_data);
@@ -633,7 +642,7 @@
   if (!ReadParam(m, iter, &p->resources))
     return false;
 
-  if (!ReadParam(m, iter, &p->last_content_dib))
+  if (!ReadParam(m, iter, &p->last_dib_id))
     return false;
 
   int compositor_frame_type;
@@ -659,7 +668,7 @@
   l->append("CompositorFrameAck(");
   LogParam(p.resources, l);
   l->append(", ");
-  LogParam(p.last_content_dib, l);
+  LogParam(p.last_dib_id, l);
   l->append(", ");
   if (p.gl_frame_data)
     LogParam(*p.gl_frame_data, l);
diff --git a/content/common/cc_messages.h b/content/common/cc_messages.h
index 5cb76f7..08b831f 100644
--- a/content/common/cc_messages.h
+++ b/content/common/cc_messages.h
@@ -4,13 +4,14 @@
 //
 // IPC Messages sent between compositor instances.
 
-#include "cc/layers/video_layer_impl.h"
+#include "cc/debug/latency_info.h"
 #include "cc/output/compositor_frame.h"
 #include "cc/output/compositor_frame_ack.h"
 #include "cc/quads/checkerboard_draw_quad.h"
 #include "cc/quads/debug_border_draw_quad.h"
 #include "cc/quads/draw_quad.h"
 #include "cc/quads/io_surface_draw_quad.h"
+#include "cc/quads/picture_draw_quad.h"
 #include "cc/quads/render_pass.h"
 #include "cc/quads/render_pass_draw_quad.h"
 #include "cc/quads/shared_quad_state.h"
@@ -107,6 +108,7 @@
 
 IPC_ENUM_TRAITS(cc::DrawQuad::Material)
 IPC_ENUM_TRAITS(cc::IOSurfaceDrawQuad::Orientation)
+IPC_ENUM_TRAITS(cc::LatencyComponentType)
 IPC_ENUM_TRAITS(WebKit::WebFilterOperation::FilterType)
 
 IPC_STRUCT_TRAITS_BEGIN(cc::RenderPass::Id)
@@ -114,12 +116,6 @@
   IPC_STRUCT_TRAITS_MEMBER(index)
 IPC_STRUCT_TRAITS_END()
 
-IPC_STRUCT_TRAITS_BEGIN(cc::VideoLayerImpl::FramePlane)
-  IPC_STRUCT_TRAITS_MEMBER(resource_id)
-  IPC_STRUCT_TRAITS_MEMBER(size)
-  IPC_STRUCT_TRAITS_MEMBER(format)
-IPC_STRUCT_TRAITS_END()
-
 IPC_STRUCT_TRAITS_BEGIN(cc::DrawQuad)
   IPC_STRUCT_TRAITS_MEMBER(material)
   IPC_STRUCT_TRAITS_MEMBER(rect)
@@ -142,12 +138,13 @@
 IPC_STRUCT_TRAITS_BEGIN(cc::IOSurfaceDrawQuad)
   IPC_STRUCT_TRAITS_PARENT(cc::DrawQuad)
   IPC_STRUCT_TRAITS_MEMBER(io_surface_size)
-  IPC_STRUCT_TRAITS_MEMBER(io_surface_texture_id)
+  IPC_STRUCT_TRAITS_MEMBER(io_surface_resource_id)
   IPC_STRUCT_TRAITS_MEMBER(orientation)
 IPC_STRUCT_TRAITS_END()
 
 IPC_STRUCT_TRAITS_BEGIN(cc::RenderPassDrawQuad)
   IPC_STRUCT_TRAITS_PARENT(cc::DrawQuad)
+  IPC_STRUCT_TRAITS_MEMBER(render_pass_id)
   IPC_STRUCT_TRAITS_MEMBER(is_replica)
   IPC_STRUCT_TRAITS_MEMBER(mask_resource_id)
   IPC_STRUCT_TRAITS_MEMBER(contents_changed_since_last_frame)
@@ -161,11 +158,12 @@
 IPC_STRUCT_TRAITS_BEGIN(cc::SolidColorDrawQuad)
   IPC_STRUCT_TRAITS_PARENT(cc::DrawQuad)
   IPC_STRUCT_TRAITS_MEMBER(color)
+  IPC_STRUCT_TRAITS_MEMBER(force_anti_aliasing_off)
 IPC_STRUCT_TRAITS_END()
 
 IPC_STRUCT_TRAITS_BEGIN(cc::StreamVideoDrawQuad)
   IPC_STRUCT_TRAITS_PARENT(cc::DrawQuad)
-  IPC_STRUCT_TRAITS_MEMBER(texture_id)
+  IPC_STRUCT_TRAITS_MEMBER(resource_id)
   IPC_STRUCT_TRAITS_MEMBER(matrix)
 IPC_STRUCT_TRAITS_END()
 
@@ -193,9 +191,9 @@
 IPC_STRUCT_TRAITS_BEGIN(cc::YUVVideoDrawQuad)
   IPC_STRUCT_TRAITS_PARENT(cc::DrawQuad)
   IPC_STRUCT_TRAITS_MEMBER(tex_scale)
-  IPC_STRUCT_TRAITS_MEMBER(y_plane)
-  IPC_STRUCT_TRAITS_MEMBER(u_plane)
-  IPC_STRUCT_TRAITS_MEMBER(v_plane)
+  IPC_STRUCT_TRAITS_MEMBER(y_plane_resource_id)
+  IPC_STRUCT_TRAITS_MEMBER(u_plane_resource_id)
+  IPC_STRUCT_TRAITS_MEMBER(v_plane_resource_id)
 IPC_STRUCT_TRAITS_END()
 
 IPC_STRUCT_TRAITS_BEGIN(cc::SharedQuadState)
@@ -216,6 +214,17 @@
   IPC_STRUCT_TRAITS_MEMBER(mailbox)
 IPC_STRUCT_TRAITS_END()
 
+IPC_STRUCT_TRAITS_BEGIN(cc::LatencyInfo::LatencyComponent)
+  IPC_STRUCT_TRAITS_MEMBER(sequence_number)
+  IPC_STRUCT_TRAITS_MEMBER(event_time)
+  IPC_STRUCT_TRAITS_MEMBER(event_count)
+IPC_STRUCT_TRAITS_END()
+
+IPC_STRUCT_TRAITS_BEGIN(cc::LatencyInfo)
+  IPC_STRUCT_TRAITS_MEMBER(latency_components)
+  IPC_STRUCT_TRAITS_MEMBER(swap_timestamp)
+IPC_STRUCT_TRAITS_END()
+
 IPC_STRUCT_TRAITS_BEGIN(cc::CompositorFrameMetadata)
   IPC_STRUCT_TRAITS_MEMBER(device_scale_factor)
   IPC_STRUCT_TRAITS_MEMBER(root_scroll_offset)
@@ -226,6 +235,7 @@
   IPC_STRUCT_TRAITS_MEMBER(max_page_scale_factor)
   IPC_STRUCT_TRAITS_MEMBER(location_bar_offset)
   IPC_STRUCT_TRAITS_MEMBER(location_bar_content_translation)
+  IPC_STRUCT_TRAITS_MEMBER(overdraw_bottom_height)
 IPC_STRUCT_TRAITS_END()
 
 IPC_STRUCT_TRAITS_BEGIN(cc::GLFrameData)
@@ -237,5 +247,5 @@
 IPC_STRUCT_TRAITS_BEGIN(cc::SoftwareFrameData)
   IPC_STRUCT_TRAITS_MEMBER(size)
   IPC_STRUCT_TRAITS_MEMBER(damage_rect)
-  IPC_STRUCT_TRAITS_MEMBER(content_dib)
+  IPC_STRUCT_TRAITS_MEMBER(dib_id)
 IPC_STRUCT_TRAITS_END()
diff --git a/content/common/cc_messages_unittest.cc b/content/common/cc_messages_unittest.cc
index d843e4b..7d20b8c 100644
--- a/content/common/cc_messages_unittest.cc
+++ b/content/common/cc_messages_unittest.cc
@@ -15,6 +15,7 @@
 using cc::DebugBorderDrawQuad;
 using cc::DrawQuad;
 using cc::IOSurfaceDrawQuad;
+using cc::PictureDrawQuad;
 using cc::RenderPass;
 using cc::RenderPassDrawQuad;
 using cc::ResourceProvider;
@@ -77,6 +78,10 @@
         Compare(IOSurfaceDrawQuad::MaterialCast(a),
                 IOSurfaceDrawQuad::MaterialCast(b));
         break;
+      case DrawQuad::PICTURE_CONTENT:
+        Compare(PictureDrawQuad::MaterialCast(a),
+                PictureDrawQuad::MaterialCast(b));
+        break;
       case DrawQuad::RENDER_PASS:
         Compare(RenderPassDrawQuad::MaterialCast(a),
                 RenderPassDrawQuad::MaterialCast(b));
@@ -117,11 +122,12 @@
 
   void Compare(const IOSurfaceDrawQuad* a, const IOSurfaceDrawQuad* b) {
     EXPECT_EQ(a->io_surface_size.ToString(), b->io_surface_size.ToString());
-    EXPECT_EQ(a->io_surface_texture_id, b->io_surface_texture_id);
+    EXPECT_EQ(a->io_surface_resource_id, b->io_surface_resource_id);
     EXPECT_EQ(a->orientation, b->orientation);
   }
 
   void Compare(const RenderPassDrawQuad* a, const RenderPassDrawQuad* b) {
+    EXPECT_EQ(a->render_pass_id, b->render_pass_id);
     EXPECT_EQ(a->is_replica, b->is_replica);
     EXPECT_EQ(a->mask_resource_id, b->mask_resource_id);
     EXPECT_EQ(a->contents_changed_since_last_frame,
@@ -134,10 +140,11 @@
 
   void Compare(const SolidColorDrawQuad* a, const SolidColorDrawQuad* b) {
     EXPECT_EQ(a->color, b->color);
+    EXPECT_EQ(a->force_anti_aliasing_off, b->force_anti_aliasing_off);
   }
 
   void Compare(const StreamVideoDrawQuad* a, const StreamVideoDrawQuad* b) {
-    EXPECT_EQ(a->texture_id, b->texture_id);
+    EXPECT_EQ(a->resource_id, b->resource_id);
     EXPECT_EQ(a->matrix, b->matrix);
   }
 
@@ -162,15 +169,9 @@
 
   void Compare(const YUVVideoDrawQuad* a, const YUVVideoDrawQuad* b) {
     EXPECT_EQ(a->tex_scale, b->tex_scale);
-    EXPECT_EQ(a->y_plane.resource_id, b->y_plane.resource_id);
-    EXPECT_EQ(a->y_plane.size.ToString(), b->y_plane.size.ToString());
-    EXPECT_EQ(a->y_plane.format, b->y_plane.format);
-    EXPECT_EQ(a->u_plane.resource_id, b->u_plane.resource_id);
-    EXPECT_EQ(a->u_plane.size.ToString(), b->u_plane.size.ToString());
-    EXPECT_EQ(a->u_plane.format, b->u_plane.format);
-    EXPECT_EQ(a->v_plane.resource_id, b->v_plane.resource_id);
-    EXPECT_EQ(a->v_plane.size.ToString(), b->v_plane.size.ToString());
-    EXPECT_EQ(a->v_plane.format, b->v_plane.format);
+    EXPECT_EQ(a->y_plane_resource_id, b->y_plane_resource_id);
+    EXPECT_EQ(a->u_plane_resource_id, b->u_plane_resource_id);
+    EXPECT_EQ(a->v_plane_resource_id, b->v_plane_resource_id);
   }
 
   void Compare(const TransferableResource& a, const TransferableResource& b) {
@@ -213,22 +214,9 @@
   IOSurfaceDrawQuad::Orientation arbitrary_orientation =
       IOSurfaceDrawQuad::UNFLIPPED;
   RenderPass::Id arbitrary_id(10, 14);
-  ResourceProvider::ResourceId arbitrary_resourceid = 55;
-
-  VideoLayerImpl::FramePlane arbitrary_plane1;
-  arbitrary_plane1.resource_id = arbitrary_resourceid;
-  arbitrary_plane1.size = arbitrary_size1;
-  arbitrary_plane1.format = arbitrary_int;
-
-  VideoLayerImpl::FramePlane arbitrary_plane2;
-  arbitrary_plane2.resource_id = arbitrary_resourceid;
-  arbitrary_plane2.size = arbitrary_size2;
-  arbitrary_plane2.format = arbitrary_int;
-
-  VideoLayerImpl::FramePlane arbitrary_plane3;
-  arbitrary_plane3.resource_id = arbitrary_resourceid;
-  arbitrary_plane3.size = arbitrary_size3;
-  arbitrary_plane3.format = arbitrary_int;
+  ResourceProvider::ResourceId arbitrary_resourceid1 = 55;
+  ResourceProvider::ResourceId arbitrary_resourceid2 = 47;
+  ResourceProvider::ResourceId arbitrary_resourceid3 = 23;
 
   WebFilterOperations arbitrary_filters1;
   arbitrary_filters1.append(WebFilterOperation::createGrayscaleFilter(
@@ -281,7 +269,7 @@
                        arbitrary_rect1,
                        arbitrary_bool1,
                        arbitrary_size1,
-                       arbitrary_int,
+                       arbitrary_resourceid3,
                        arbitrary_orientation);
   scoped_ptr<DrawQuad> iosurface_cmp = iosurface_in->Copy(
       iosurface_in->shared_quad_state);
@@ -295,11 +283,11 @@
                         arbitrary_bool1,
                         arbitrary_id,
                         arbitrary_bool2,
-                        arbitrary_resourceid,
+                        arbitrary_resourceid2,
                         arbitrary_rect1,
                         arbitrary_rectf1,
                         arbitrary_filters1,
-                        arbitrary_filter, // TODO(piman): not serialized.
+                        arbitrary_filter,  // TODO(piman): not serialized.
                         arbitrary_filters2);
   scoped_ptr<RenderPassDrawQuad> renderpass_cmp = renderpass_in->Copy(
       renderpass_in->shared_quad_state, renderpass_in->render_pass_id);
@@ -329,7 +317,8 @@
                         arbitrary_rect1,
                         arbitrary_rect2,
                         arbitrary_bool1,
-                        arbitrary_color);
+                        arbitrary_color,
+                        arbitrary_bool2);
   scoped_ptr<DrawQuad> solidcolor_cmp = solidcolor_in->Copy(
       solidcolor_in->shared_quad_state);
 
@@ -340,7 +329,7 @@
                          arbitrary_rect3,
                          arbitrary_rect1,
                          arbitrary_bool1,
-                         arbitrary_int,
+                         arbitrary_resourceid2,
                          arbitrary_matrix);
   scoped_ptr<DrawQuad> streamvideo_cmp = streamvideo_in->Copy(
       streamvideo_in->shared_quad_state);
@@ -351,7 +340,7 @@
                      arbitrary_rect3,
                      arbitrary_rect1,
                      arbitrary_bool1,
-                     arbitrary_resourceid,
+                     arbitrary_resourceid1,
                      arbitrary_bool2,
                      arbitrary_pointf1,
                      arbitrary_pointf2,
@@ -366,7 +355,7 @@
                   arbitrary_rect3,
                   arbitrary_rect1,
                   arbitrary_bool1,
-                  arbitrary_resourceid,
+                  arbitrary_resourceid3,
                   arbitrary_rectf1,
                   arbitrary_size1,
                   arbitrary_bool2);
@@ -381,9 +370,9 @@
                       arbitrary_rect3,
                       arbitrary_bool1,
                       arbitrary_sizef1,
-                      arbitrary_plane1,
-                      arbitrary_plane2,
-                      arbitrary_plane3);
+                      arbitrary_resourceid1,
+                      arbitrary_resourceid2,
+                      arbitrary_resourceid3);
   scoped_ptr<DrawQuad> yuvvideo_cmp = yuvvideo_in->Copy(
       yuvvideo_in->shared_quad_state);
 
diff --git a/content/common/child_histogram_message_filter.cc b/content/common/child_histogram_message_filter.cc
index 25f9180..752d767 100644
--- a/content/common/child_histogram_message_filter.cc
+++ b/content/common/child_histogram_message_filter.cc
@@ -18,7 +18,7 @@
 
 ChildHistogramMessageFilter::ChildHistogramMessageFilter()
     : channel_(NULL),
-      ALLOW_THIS_IN_INITIALIZER_LIST(histogram_snapshot_manager_(this)) {
+      histogram_snapshot_manager_(this) {
 }
 
 ChildHistogramMessageFilter::~ChildHistogramMessageFilter() {
diff --git a/content/common/child_histogram_message_filter.h b/content/common/child_histogram_message_filter.h
index 4955d49..9339d8e 100644
--- a/content/common/child_histogram_message_filter.h
+++ b/content/common/child_histogram_message_filter.h
@@ -14,8 +14,6 @@
 #include "base/metrics/histogram_snapshot_manager.h"
 #include "ipc/ipc_channel_proxy.h"
 
-class MessageLoop;
-
 namespace base {
 class HistogramSamples;
 }  // namespace base
diff --git a/content/common/child_process.cc b/content/common/child_process.cc
index 75c80ec..95bc331 100644
--- a/content/common/child_process.cc
+++ b/content/common/child_process.cc
@@ -51,7 +51,7 @@
 
   // We can't recover from failing to start the IO thread.
   CHECK(io_thread_.StartWithOptions(
-            base::Thread::Options(MessageLoop::TYPE_IO, 0)));
+      base::Thread::Options(base::MessageLoop::TYPE_IO, 0)));
 
 #if defined(OS_ANDROID)
   // TODO(epenner): Move thread priorities to base. (crbug.com/170549)
@@ -71,7 +71,10 @@
 
   // Kill the main thread object before nulling child_process_, since
   // destruction code might depend on it.
-  main_thread_.reset();
+  if (main_thread_) {  // null in unittests.
+    main_thread_->Shutdown();
+    main_thread_.reset();
+  }
 
   child_process_ = NULL;
 }
@@ -86,19 +89,19 @@
 
 void ChildProcess::AddRefProcess() {
   DCHECK(!main_thread_.get() ||  // null in unittests.
-         MessageLoop::current() == main_thread_->message_loop());
+         base::MessageLoop::current() == main_thread_->message_loop());
   ref_count_++;
 }
 
 void ChildProcess::ReleaseProcess() {
   DCHECK(!main_thread_.get() ||  // null in unittests.
-         MessageLoop::current() == main_thread_->message_loop());
+         base::MessageLoop::current() == main_thread_->message_loop());
   DCHECK(ref_count_);
   DCHECK(child_process_);
   if (--ref_count_)
     return;
 
-  if (main_thread_.get())  // null in unittests.
+  if (main_thread_)  // null in unittests.
     main_thread_->OnProcessFinalRelease();
 }
 
diff --git a/content/common/child_process.h b/content/common/child_process.h
index 09e97d9..dc7df53 100644
--- a/content/common/child_process.h
+++ b/content/common/child_process.h
@@ -30,7 +30,7 @@
   // Takes ownership of the pointer.
   void set_main_thread(ChildThread* thread);
 
-  MessageLoop* io_message_loop() { return io_thread_.message_loop(); }
+  base::MessageLoop* io_message_loop() { return io_thread_.message_loop(); }
   base::MessageLoopProxy* io_message_loop_proxy() {
     return io_thread_.message_loop_proxy();
   }
diff --git a/content/common/child_process_host_impl.cc b/content/common/child_process_host_impl.cc
index 606811d..bb0fdfd 100644
--- a/content/common/child_process_host_impl.cc
+++ b/content/common/child_process_host_impl.cc
@@ -149,7 +149,7 @@
 void ChildProcessHostImpl::AddFilter(IPC::ChannelProxy::MessageFilter* filter) {
   filters_.push_back(filter);
 
-  if (channel_.get())
+  if (channel_)
     filter->OnFilterAdded(channel_.get());
 }
 
@@ -189,7 +189,7 @@
 #endif
 
 bool ChildProcessHostImpl::Send(IPC::Message* message) {
-  if (!channel_.get()) {
+  if (!channel_) {
     delete message;
     return false;
   }
@@ -262,7 +262,7 @@
 }
 
 void ChildProcessHostImpl::OnChannelConnected(int32 peer_pid) {
-  if (!base::OpenProcessHandle(peer_pid, &peer_handle_)) {
+  if (!base::OpenPrivilegedProcessHandle(peer_pid, &peer_handle_)) {
     NOTREACHED();
   }
   opening_channel_ = false;
diff --git a/content/common/child_process_sandbox_support_impl_linux.cc b/content/common/child_process_sandbox_support_impl_linux.cc
index 984f796..6eec6fe 100644
--- a/content/common/child_process_sandbox_support_impl_linux.cc
+++ b/content/common/child_process_sandbox_support_impl_linux.cc
@@ -10,6 +10,8 @@
 #include "base/pickle.h"
 #include "base/posix/eintr_wrapper.h"
 #include "base/posix/unix_domain_socket_linux.h"
+#include "base/safe_numerics.h"
+#include "base/sys_byteorder.h"
 #include "content/common/sandbox_linux.h"
 #include "third_party/WebKit/Source/Platform/chromium/public/linux/WebFontFamily.h"
 #include "third_party/WebKit/Source/WebKit/chromium/public/linux/WebFontRenderStyle.h"
@@ -99,79 +101,74 @@
   return fd;
 }
 
-bool GetFontTable(int fd, uint32_t table, uint8_t* output,
-                  size_t* output_length) {
-  if (table == 0) {
+bool GetFontTable(int fd, uint32_t table_tag, off_t offset,
+                  uint8_t* output, size_t* output_length) {
+  if (offset < 0)
+    return false;
+
+  size_t data_length = 0;  // the length of the file data.
+  off_t data_offset = 0;   // the offset of the data in the file.
+  if (table_tag == 0) {
+    // Get the entire font file.
     struct stat st;
     if (fstat(fd, &st) < 0)
       return false;
-    size_t length = st.st_size;
-    if (!output) {
-      *output_length = length;
-      return true;
-    }
-    if (*output_length < length)
+    data_length = base::checked_numeric_cast<size_t>(st.st_size);
+  } else {
+    // Get a font table. Read the header to find its offset in the file.
+    uint16_t num_tables;
+    ssize_t n = HANDLE_EINTR(pread(fd, &num_tables, sizeof(num_tables),
+                             4 /* skip the font type */));
+    if (n != sizeof(num_tables))
       return false;
-    *output_length = length;
-    ssize_t n = HANDLE_EINTR(pread(fd, output, length, 0));
-    if (n != static_cast<ssize_t>(length))
+    // Font data is stored in net (big-endian) order.
+    num_tables = base::NetToHost16(num_tables);
+
+    // Read the table directory.
+    static const size_t kTableEntrySize = 16;
+    const size_t directory_size = num_tables * kTableEntrySize;
+    scoped_ptr<uint8_t[]> table_entries(new uint8_t[directory_size]);
+    n = HANDLE_EINTR(pread(fd, table_entries.get(), directory_size,
+                           12 /* skip the SFNT header */));
+    if (n != base::checked_numeric_cast<ssize_t>(directory_size))
       return false;
-    return true;
-  }
 
-  unsigned num_tables;
-  uint8_t num_tables_buf[2];
-
-  ssize_t n = HANDLE_EINTR(pread(fd, &num_tables_buf, sizeof(num_tables_buf),
-                           4 /* skip the font type */));
-  if (n != sizeof(num_tables_buf))
-    return false;
-
-  num_tables = static_cast<unsigned>(num_tables_buf[0]) << 8 |
-               num_tables_buf[1];
-
-  // The size in bytes of an entry in the table directory.
-  static const unsigned kTableEntrySize = 16;
-  scoped_array<uint8_t> table_entries(
-      new uint8_t[num_tables * kTableEntrySize]);
-  n = HANDLE_EINTR(pread(fd, table_entries.get(), num_tables * kTableEntrySize,
-                         12 /* skip the SFNT header */));
-  if (n != static_cast<ssize_t>(num_tables * kTableEntrySize))
-    return false;
-
-  size_t offset;
-  size_t length = 0;
-  for (unsigned i = 0; i < num_tables; i++) {
-    const uint8_t* entry = table_entries.get() + i * kTableEntrySize;
-    if (memcmp(entry, &table, sizeof(table)) == 0) {
-      offset = static_cast<size_t>(entry[8]) << 24 |
-               static_cast<size_t>(entry[9]) << 16 |
-               static_cast<size_t>(entry[10]) << 8  |
-               static_cast<size_t>(entry[11]);
-      length = static_cast<size_t>(entry[12]) << 24 |
-               static_cast<size_t>(entry[13]) << 16 |
-               static_cast<size_t>(entry[14]) << 8  |
-               static_cast<size_t>(entry[15]);
-
-      break;
+    for (uint16_t i = 0; i < num_tables; ++i) {
+      uint8_t* entry = table_entries.get() + i * kTableEntrySize;
+      uint32_t tag = *reinterpret_cast<uint32_t*>(entry);
+      if (tag == table_tag) {
+        // Font data is stored in net (big-endian) order.
+        data_offset =
+            base::NetToHost32(*reinterpret_cast<uint32_t*>(entry + 8));
+        data_length =
+            base::NetToHost32(*reinterpret_cast<uint32_t*>(entry + 12));
+        break;
+      }
     }
   }
 
-  if (!length)
+  if (!data_length)
     return false;
+  // Clamp |offset| inside the allowable range. This allows the read to succeed
+  // but return 0 bytes.
+  offset = std::min(offset, base::checked_numeric_cast<off_t>(data_length));
+  // Make sure it's safe to add the data offset and the caller's logical offset.
+  // Define the maximum positive offset on 32 bit systems.
+  static const off_t kMaxPositiveOffset32 = 0x7FFFFFFF;  // 2 GB - 1.
+  if ((offset > kMaxPositiveOffset32 / 2) ||
+      (data_offset > kMaxPositiveOffset32 / 2))
+    return false;
+  data_offset += offset;
+  data_length -= offset;
 
-  if (!output) {
-    *output_length = length;
-    return true;
+  if (output) {
+    // 'output_length' holds the maximum amount of data the caller can accept.
+    data_length = std::min(data_length, *output_length);
+    ssize_t n = HANDLE_EINTR(pread(fd, output, data_length, data_offset));
+    if (n != base::checked_numeric_cast<ssize_t>(data_length))
+      return false;
   }
-
-  if (*output_length < length)
-    return false;
-
-  *output_length = length;
-  n = HANDLE_EINTR(pread(fd, output, length, offset));
-  if (n != static_cast<ssize_t>(length))
-    return false;
+  *output_length = data_length;
 
   return true;
 }
diff --git a/content/common/child_thread.cc b/content/common/child_thread.cc
index 4540b15..b301ab7 100644
--- a/content/common/child_thread.cc
+++ b/content/common/child_thread.cc
@@ -82,7 +82,7 @@
 }  // namespace
 
 ChildThread::ChildThread()
-    : ALLOW_THIS_IN_INITIALIZER_LIST(channel_connected_factory_(this)) {
+    : channel_connected_factory_(this) {
   channel_name_ = CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
       switches::kProcessChannelID);
   Init();
@@ -90,17 +90,20 @@
 
 ChildThread::ChildThread(const std::string& channel_name)
     : channel_name_(channel_name),
-      ALLOW_THIS_IN_INITIALIZER_LIST(channel_connected_factory_(this)) {
+      channel_connected_factory_(this) {
   Init();
 }
 
 void ChildThread::Init() {
   on_channel_error_called_ = false;
-  message_loop_ = MessageLoop::current();
-  channel_.reset(new IPC::SyncChannel(channel_name_,
-      IPC::Channel::MODE_CLIENT, this,
-      ChildProcess::current()->io_message_loop_proxy(), true,
-      ChildProcess::current()->GetShutDownEvent()));
+  message_loop_ = base::MessageLoop::current();
+  channel_.reset(
+      new IPC::SyncChannel(channel_name_,
+                           IPC::Channel::MODE_CLIENT,
+                           this,
+                           ChildProcess::current()->io_message_loop_proxy(),
+                           true,
+                           ChildProcess::current()->GetShutDownEvent()));
 #ifdef IPC_MESSAGE_LOG_ENABLED
   IPC::Logging::GetInstance()->SetIPCSender(this);
 #endif
@@ -129,7 +132,7 @@
     channel_->AddFilter(new SuicideOnChannelErrorFilter());
 #endif
 
-  MessageLoop::current()->PostDelayedTask(
+  base::MessageLoop::current()->PostDelayedTask(
       FROM_HERE,
       base::Bind(&ChildThread::EnsureConnected,
                  channel_connected_factory_.GetWeakPtr()),
@@ -161,12 +164,12 @@
 
 void ChildThread::OnChannelError() {
   set_on_channel_error_called(true);
-  MessageLoop::current()->Quit();
+  base::MessageLoop::current()->Quit();
 }
 
 bool ChildThread::Send(IPC::Message* msg) {
-  DCHECK(MessageLoop::current() == message_loop());
-  if (!channel_.get()) {
+  DCHECK(base::MessageLoop::current() == message_loop());
+  if (!channel_) {
     delete msg;
     return false;
   }
@@ -175,23 +178,17 @@
 }
 
 void ChildThread::AddRoute(int32 routing_id, IPC::Listener* listener) {
-  DCHECK(MessageLoop::current() == message_loop());
+  DCHECK(base::MessageLoop::current() == message_loop());
 
   router_.AddRoute(routing_id, listener);
 }
 
 void ChildThread::RemoveRoute(int32 routing_id) {
-  DCHECK(MessageLoop::current() == message_loop());
+  DCHECK(base::MessageLoop::current() == message_loop());
 
   router_.RemoveRoute(routing_id);
 }
 
-IPC::Listener* ChildThread::ResolveRoute(int32 routing_id) {
-  DCHECK(MessageLoop::current() == message_loop());
-
-  return router_.ResolveRoute(routing_id);
-}
-
 webkit_glue::ResourceLoaderBridge* ChildThread::CreateBridge(
     const webkit_glue::ResourceLoaderBridge::RequestInfo& request_info) {
   return resource_dispatcher()->CreateBridge(request_info);
@@ -279,7 +276,7 @@
 }
 
 void ChildThread::OnShutdown() {
-  MessageLoop::current()->Quit();
+  base::MessageLoop::current()->Quit();
 }
 
 #if defined(IPC_MESSAGE_LOG_ENABLED)
@@ -339,7 +336,7 @@
 
 void ChildThread::OnProcessFinalRelease() {
   if (on_channel_error_called_) {
-    MessageLoop::current()->Quit();
+    base::MessageLoop::current()->Quit();
     return;
   }
 
diff --git a/content/common/child_thread.h b/content/common/child_thread.h
index ed9e684..bd23cc9 100644
--- a/content/common/child_thread.h
+++ b/content/common/child_thread.h
@@ -15,7 +15,9 @@
 #include "ipc/ipc_message.h"  // For IPC_MESSAGE_LOG_ENABLED.
 #include "webkit/glue/resource_loader_bridge.h"
 
+namespace base {
 class MessageLoop;
+}
 
 namespace IPC {
 class SyncChannel;
@@ -41,7 +43,13 @@
   ChildThread();
   // Used for single-process mode.
   explicit ChildThread(const std::string& channel_name);
+  // ChildProcess::main_thread() is reset after Shutdown(), and before the
+  // destructor, so any subsystem that relies on ChildProcess::main_thread()
+  // must be terminated before Shutdown returns. In particular, if a subsystem
+  // has a thread that post tasks to ChildProcess::main_thread(), that thread
+  // should be joined in Shutdown().
   virtual ~ChildThread();
+  virtual void Shutdown() = 0;
 
   // IPC::Sender implementation:
   virtual bool Send(IPC::Message* msg) OVERRIDE;
@@ -50,8 +58,6 @@
   void AddRoute(int32 routing_id, IPC::Listener* listener);
   void RemoveRoute(int32 routing_id);
 
-  IPC::Listener* ResolveRoute(int32 routing_id);
-
   IPC::SyncChannel* channel() { return channel_.get(); }
 
   // Creates a ResourceLoaderBridge.
@@ -104,7 +110,7 @@
     return histogram_message_filter_.get();
   }
 
-  MessageLoop* message_loop() const { return message_loop_; }
+  base::MessageLoop* message_loop() const { return message_loop_; }
 
   // Returns the one child thread.
   static ChildThread* current();
@@ -166,7 +172,7 @@
   // attempt to communicate.
   bool on_channel_error_called_;
 
-  MessageLoop* message_loop_;
+  base::MessageLoop* message_loop_;
 
   scoped_ptr<FileSystemDispatcher> file_system_dispatcher_;
 
diff --git a/content/common/common_param_traits_unittest.cc b/content/common/common_param_traits_unittest.cc
index 0540032..432f8f9 100644
--- a/content/common/common_param_traits_unittest.cc
+++ b/content/common/common_param_traits_unittest.cc
@@ -113,7 +113,7 @@
   bad_msg.WriteData(fixed_data, fixed_data_size);
   // Add some bogus pixel data.
   const size_t bogus_pixels_size = bitmap.getSize() * 2;
-  scoped_array<char> bogus_pixels(new char[bogus_pixels_size]);
+  scoped_ptr<char[]> bogus_pixels(new char[bogus_pixels_size]);
   memset(bogus_pixels.get(), 'B', bogus_pixels_size);
   bad_msg.WriteData(bogus_pixels.get(), bogus_pixels_size);
   // Make sure we don't read out the bitmap!
diff --git a/content/common/content_constants_internal.cc b/content/common/content_constants_internal.cc
index 3295a53..45316c3 100644
--- a/content/common/content_constants_internal.cc
+++ b/content/common/content_constants_internal.cc
@@ -6,10 +6,6 @@
 
 namespace content {
 
-const char kFrameTreeNodeNameKey[] = "name";
-const char kFrameTreeNodeIdKey[] = "id";
-const char kFrameTreeNodeSubtreeKey[] = "subtree";
-
 const int kHungRendererDelayMs = 30000;
 
 } // namespace content
diff --git a/content/common/content_constants_internal.h b/content/common/content_constants_internal.h
index 7ee5b0d..b69bb4a 100644
--- a/content/common/content_constants_internal.h
+++ b/content/common/content_constants_internal.h
@@ -5,16 +5,12 @@
 #ifndef CONTENT_COMMON_CONTENT_CONSTANTS_INTERNAL_H_
 #define CONTENT_COMMON_CONTENT_CONSTANTS_INTERNAL_H_
 
+#include "content/common/content_export.h"
+
 namespace content {
 
-// Keys used for serializing the frame tree of a renderer process, used for
-// ViewMsg_UpdateFrameTree and ViewHostMsg_FrameTreeUpdated.
-extern const char kFrameTreeNodeNameKey[];
-extern const char kFrameTreeNodeIdKey[];
-extern const char kFrameTreeNodeSubtreeKey[];
-
 // How long to wait before we consider a renderer hung.
-extern const int kHungRendererDelayMs;
+CONTENT_EXPORT extern const int kHungRendererDelayMs;
 
 } // namespace content
 
diff --git a/content/common/content_message_generator.h b/content/common/content_message_generator.h
index 9b0d4d4..e553480 100644
--- a/content/common/content_message_generator.h
+++ b/content/common/content_message_generator.h
@@ -26,14 +26,16 @@
 #include "content/common/geolocation_messages.h"
 #include "content/common/gpu/gpu_messages.h"
 #include "content/common/hyphenator_messages.h"
-#include "content/common/icon_messages.h"
+#include "content/common/image_messages.h"
 #include "content/common/indexed_db/indexed_db_messages.h"
+#include "content/common/input_messages.h"
 #include "content/common/java_bridge_messages.h"
 #include "content/common/media/audio_messages.h"
 #include "content/common/media/media_player_messages.h"
 #include "content/common/media/media_stream_messages.h"
 #include "content/common/media/peer_connection_tracker_messages.h"
 #include "content/common/media/video_capture_messages.h"
+#include "content/common/media/webrtc_logging_messages.h"
 #include "content/common/mime_registry_messages.h"
 #include "content/common/p2p_messages.h"
 #include "content/common/pepper_messages.h"
diff --git a/content/common/fileapi/OWNERS b/content/common/fileapi/OWNERS
index a59ea28..9e9046e 100644
--- a/content/common/fileapi/OWNERS
+++ b/content/common/fileapi/OWNERS
@@ -11,3 +11,4 @@
 per-file *_messages.h=jschuh@chromium.org
 per-file *_messages.h=palmer@chromium.org
 per-file *_messages.h=tsepez@chromium.org
+per-file *_messages.h=kenrb@chromium.org
diff --git a/content/common/fileapi/file_system_dispatcher.cc b/content/common/fileapi/file_system_dispatcher.cc
index e80bc04..425b00c 100644
--- a/content/common/fileapi/file_system_dispatcher.cc
+++ b/content/common/fileapi/file_system_dispatcher.cc
@@ -247,9 +247,9 @@
   return true;
 }
 
-bool FileSystemDispatcher::NotifyCloseFile(const GURL& file_path) {
+bool FileSystemDispatcher::NotifyCloseFile(int file_open_id) {
   return ChildThread::current()->Send(
-      new FileSystemHostMsg_NotifyCloseFile(file_path));
+      new FileSystemHostMsg_NotifyCloseFile(file_open_id));
 }
 
 bool FileSystemDispatcher::CreateSnapshotFile(
@@ -265,20 +265,6 @@
   return true;
 }
 
-bool FileSystemDispatcher::CreateSnapshotFile_Deprecated(
-    const GURL& blob_url,
-    const GURL& file_path,
-    fileapi::FileSystemCallbackDispatcher* dispatcher) {
-  int request_id = dispatchers_.Add(dispatcher);
-  if (!ChildThread::current()->Send(
-          new FileSystemHostMsg_CreateSnapshotFile_Deprecated(
-              request_id, blob_url, file_path))) {
-    dispatchers_.Remove(request_id); // destroys |dispatcher|
-    return false;
-  }
-  return true;
-}
-
 void FileSystemDispatcher::OnDidOpenFileSystem(int request_id,
                                                const std::string& name,
                                                const GURL& root) {
@@ -351,11 +337,16 @@
 }
 
 void FileSystemDispatcher::OnDidOpenFile(
-    int request_id, IPC::PlatformFileForTransit file) {
+    int request_id,
+    IPC::PlatformFileForTransit file,
+    int file_open_id,
+    quota::QuotaLimitType quota_policy) {
   fileapi::FileSystemCallbackDispatcher* dispatcher =
       dispatchers_.Lookup(request_id);
   DCHECK(dispatcher);
-  dispatcher->DidOpenFile(IPC::PlatformFileForTransitToPlatformFile(file));
+  dispatcher->DidOpenFile(IPC::PlatformFileForTransitToPlatformFile(file),
+                          file_open_id,
+                          quota_policy);
   dispatchers_.Remove(request_id);
 }
 
diff --git a/content/common/fileapi/file_system_dispatcher.h b/content/common/fileapi/file_system_dispatcher.h
index 9732b09..f38cd0d 100644
--- a/content/common/fileapi/file_system_dispatcher.h
+++ b/content/common/fileapi/file_system_dispatcher.h
@@ -16,6 +16,7 @@
 #include "ipc/ipc_platform_file.h"
 #include "webkit/fileapi/file_system_callback_dispatcher.h"
 #include "webkit/fileapi/file_system_types.h"
+#include "webkit/quota/quota_types.h"
 
 namespace base {
 class FilePath;
@@ -89,16 +90,11 @@
                 fileapi::FileSystemCallbackDispatcher* dispatcher);
   // This must be paired with OpenFile, and called after finished using the
   // raw PlatformFile returned from OpenFile.
-  bool NotifyCloseFile(const GURL& file_path);
+  bool NotifyCloseFile(int file_open_id);
 
   bool CreateSnapshotFile(const GURL& file_path,
                           fileapi::FileSystemCallbackDispatcher* dispatcher);
 
-  bool CreateSnapshotFile_Deprecated(
-      const GURL& blod_url,
-      const GURL& file_path,
-      fileapi::FileSystemCallbackDispatcher* dispatcher);
-
  private:
   // Message handlers.
   void OnDidOpenFileSystem(int request_id,
@@ -119,7 +115,9 @@
   void OnDidWrite(int request_id, int64 bytes, bool complete);
   void OnDidOpenFile(
       int request_id,
-      IPC::PlatformFileForTransit file);
+      IPC::PlatformFileForTransit file,
+      int file_open_id,
+      quota::QuotaLimitType quota_policy);
 
   IDMap<fileapi::FileSystemCallbackDispatcher, IDMapOwnPointer> dispatchers_;
 
diff --git a/content/common/fileapi/file_system_messages.h b/content/common/fileapi/file_system_messages.h
index ef2f8bb..ee25545 100644
--- a/content/common/fileapi/file_system_messages.h
+++ b/content/common/fileapi/file_system_messages.h
@@ -10,6 +10,7 @@
 #include "ipc/ipc_message_macros.h"
 #include "ipc/ipc_platform_file.h"
 #include "webkit/fileapi/file_system_types.h"
+#include "webkit/quota/quota_types.h"
 
 #define IPC_MESSAGE_START FileSystemMsgStart
 
@@ -19,6 +20,7 @@
 IPC_STRUCT_TRAITS_END()
 
 IPC_ENUM_TRAITS(fileapi::FileSystemType)
+IPC_ENUM_TRAITS(quota::QuotaLimitType)
 
 // File system messages sent from the browser to the child process.
 
@@ -47,9 +49,11 @@
                      int /* request_id */,
                      int64 /* byte count */,
                      bool /* complete */)
-IPC_MESSAGE_CONTROL2(FileSystemMsg_DidOpenFile,
+IPC_MESSAGE_CONTROL4(FileSystemMsg_DidOpenFile,
                      int /* request_id */,
-                     IPC::PlatformFileForTransit)
+                     IPC::PlatformFileForTransit,
+                     int /* file_open_id */,
+                     quota::QuotaLimitType /* quota_policy */)
 IPC_MESSAGE_CONTROL2(FileSystemMsg_DidFail,
                      int /* request_id */,
                      base::PlatformFileError /* error_code */)
@@ -145,13 +149,7 @@
 
 // Pepper's NotifyCloseFile message.
 IPC_MESSAGE_CONTROL1(FileSystemHostMsg_NotifyCloseFile,
-                     GURL /* file path */)
-
-// DEPRECATED
-IPC_MESSAGE_CONTROL3(FileSystemHostMsg_CreateSnapshotFile_Deprecated,
-                     int /* request_id */,
-                     GURL /* blob_url */,
-                     GURL /* file_path */)
+                     int /* file_open_id */)
 
 // WebFileSystem::createSnapshotFileAndReadMetadata() message.
 IPC_MESSAGE_CONTROL2(FileSystemHostMsg_CreateSnapshotFile,
diff --git a/content/common/fileapi/webblobregistry_impl.cc b/content/common/fileapi/webblobregistry_impl.cc
index c657684..529d7ac 100644
--- a/content/common/fileapi/webblobregistry_impl.cc
+++ b/content/common/fileapi/webblobregistry_impl.cc
@@ -31,7 +31,8 @@
 
 void WebBlobRegistryImpl::registerBlobURL(
     const WebURL& url, WebBlobData& data) {
-  DCHECK(ChildThread::current()->message_loop() == MessageLoop::current());
+  DCHECK(ChildThread::current()->message_loop() ==
+         base::MessageLoop::current());
   const size_t kLargeThresholdBytes = 250 * 1024;
   const size_t kMaxSharedMemoryBytes = 10 * 1024 * 1024;
 
@@ -111,12 +112,14 @@
 
 void WebBlobRegistryImpl::registerBlobURL(
     const WebURL& url, const WebURL& src_url) {
-  DCHECK(ChildThread::current()->message_loop() == MessageLoop::current());
+  DCHECK(ChildThread::current()->message_loop() ==
+         base::MessageLoop::current());
   sender_->Send(new BlobHostMsg_CloneBlob(url, src_url));
 }
 
 void WebBlobRegistryImpl::unregisterBlobURL(const WebURL& url) {
-  DCHECK(ChildThread::current()->message_loop() == MessageLoop::current());
+  DCHECK(ChildThread::current()->message_loop() ==
+         base::MessageLoop::current());
   sender_->Send(new BlobHostMsg_RemoveBlob(url));
 }
 
diff --git a/content/common/fileapi/webfilesystem_impl.cc b/content/common/fileapi/webfilesystem_impl.cc
index e9b27ce..0fcd7a3 100644
--- a/content/common/fileapi/webfilesystem_impl.cc
+++ b/content/common/fileapi/webfilesystem_impl.cc
@@ -128,16 +128,4 @@
       GURL(path), new WebFileSystemCallbackDispatcher(callbacks));
 }
 
-// DEPRECATED
-void WebFileSystemImpl::createSnapshotFileAndReadMetadata(
-    const WebKit::WebURL& blobURL,
-    const WebKit::WebURL& path,
-    WebKit::WebFileSystemCallbacks* callbacks) {
-  FileSystemDispatcher* dispatcher =
-      ChildThread::current()->file_system_dispatcher();
-  dispatcher->CreateSnapshotFile_Deprecated(
-      GURL(blobURL), GURL(path),
-      new WebFileSystemCallbackDispatcher(callbacks));
-}
-
 }  // namespace content
diff --git a/content/common/fileapi/webfilesystem_impl.h b/content/common/fileapi/webfilesystem_impl.h
index a02ad21..fc742b4 100644
--- a/content/common/fileapi/webfilesystem_impl.h
+++ b/content/common/fileapi/webfilesystem_impl.h
@@ -62,12 +62,6 @@
   virtual void createSnapshotFileAndReadMetadata(
       const WebKit::WebURL& path,
       WebKit::WebFileSystemCallbacks*);
-
-  // DEPRECATED variant being replaced by the above.
-  virtual void createSnapshotFileAndReadMetadata(
-      const WebKit::WebURL& blobURL,
-      const WebKit::WebURL& path,
-      WebKit::WebFileSystemCallbacks*);
 };
 
 }  // namespace content
diff --git a/content/common/font_list.cc b/content/common/font_list.cc
new file mode 100644
index 0000000..398ee80
--- /dev/null
+++ b/content/common/font_list.cc
@@ -0,0 +1,9 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/common/font_list.h"
+
+namespace content {
+const char kFontListSequenceToken[] = "_font_list_sequence_token_";
+}
diff --git a/content/common/font_list.h b/content/common/font_list.h
index 4f59e6d..dd14ce7 100644
--- a/content/common/font_list.h
+++ b/content/common/font_list.h
@@ -13,6 +13,11 @@
 
 namespace content {
 
+// Getting the list of fonts on the system is non-threadsafe on Linux for
+// versions of Pango predating 2013. This sequence token can be used to enforce
+// serial execution of get font list tasks.
+extern const char kFontListSequenceToken[];
+
 // Retrieves the fonts available on the current platform and returns them.
 // The caller will own the returned pointer. Each entry will be a list of
 // two strings, the first being the font family, and the second being the
@@ -21,6 +26,9 @@
 // This function is potentially slow (the system may do a bunch of I/O) so be
 // sure not to call this on a time-critical thread like the UI or I/O threads.
 //
+// Since getting the fonts is not threadsafe on Linux, use
+// |kFontListSequenceToken| to prevent race conditions.
+//
 // Most callers will want to use the GetFontListAsync function in
 // content/browser/font_list_async.h which does an asynchronous call.
 scoped_ptr<base::ListValue> GetFontList_SlowBlocking();
diff --git a/content/common/font_list_mac.mm b/content/common/font_list_mac.mm
index c5405e2..4ffb3de 100644
--- a/content/common/font_list_mac.mm
+++ b/content/common/font_list_mac.mm
@@ -7,7 +7,7 @@
 #import <Cocoa/Cocoa.h>
 
 #include "base/mac/scoped_nsautorelease_pool.h"
-#include "base/sys_string_conversions.h"
+#include "base/strings/sys_string_conversions.h"
 #include "base/values.h"
 
 namespace content {
diff --git a/content/common/gpu/OWNERS b/content/common/gpu/OWNERS
index fd5d45c..7a88280 100644
--- a/content/common/gpu/OWNERS
+++ b/content/common/gpu/OWNERS
@@ -12,3 +12,4 @@
 per-file *_messages.h=jschuh@chromium.org

 per-file *_messages.h=palmer@chromium.org

 per-file *_messages.h=tsepez@chromium.org

+per-file *_messages.h=kenrb@chromium.org

diff --git a/content/common/gpu/client/command_buffer_proxy_impl.cc b/content/common/gpu/client/command_buffer_proxy_impl.cc
index 61f8922..156626a 100644
--- a/content/common/gpu/client/command_buffer_proxy_impl.cc
+++ b/content/common/gpu/client/command_buffer_proxy_impl.cc
@@ -13,6 +13,7 @@
 #include "content/common/child_process_messages.h"
 #include "content/common/gpu/gpu_memory_allocation.h"
 #include "content/common/gpu/client/gpu_channel_host.h"
+#include "content/common/gpu/client/gpu_video_decode_accelerator_host.h"
 #include "content/common/gpu/gpu_messages.h"
 #include "content/common/plugin_messages.h"
 #include "content/common/view_messages.h"
@@ -33,6 +34,10 @@
 }
 
 CommandBufferProxyImpl::~CommandBufferProxyImpl() {
+  FOR_EACH_OBSERVER(DeletionObserver,
+                    deletion_observers_,
+                    OnWillDeleteImpl());
+
   // Delete all the locally cached shared memory objects, closing the handle
   // in this process.
   for (TransferBufferMap::iterator it = transfer_buffers_.begin();
@@ -41,11 +46,6 @@
     delete it->second.shared_memory;
     it->second.shared_memory = NULL;
   }
-  for (Decoders::iterator it = video_decoder_hosts_.begin();
-      it != video_decoder_hosts_.end(); ++it) {
-    if (it->second)
-      it->second->OnChannelError();
-  }
 }
 
 bool CommandBufferProxyImpl::OnMessageReceived(const IPC::Message& message) {
@@ -110,6 +110,15 @@
       route_id_, !memory_allocation_changed_callback_.is_null()));
 }
 
+void CommandBufferProxyImpl::AddDeletionObserver(DeletionObserver* observer) {
+  deletion_observers_.AddObserver(observer);
+}
+
+void CommandBufferProxyImpl::RemoveDeletionObserver(
+    DeletionObserver* observer) {
+  deletion_observers_.RemoveObserver(observer);
+}
+
 void CommandBufferProxyImpl::OnSetMemoryAllocation(
     const GpuMemoryAllocationForRenderer& allocation) {
   if (!memory_allocation_changed_callback_.is_null())
@@ -132,7 +141,7 @@
 bool CommandBufferProxyImpl::Initialize() {
   shared_state_shm_.reset(channel_->factory()->AllocateSharedMemory(
       sizeof(*shared_state())).release());
-  if (!shared_state_shm_.get())
+  if (!shared_state_shm_)
     return false;
 
   if (!shared_state_shm_->Map(sizeof(*shared_state())))
@@ -144,7 +153,7 @@
   // will leak. In otherwords, do not early out on error between here and the
   // sending of the Initialize IPC below.
   base::SharedMemoryHandle handle =
-      channel_->ShareToGpuProcess(shared_state_shm_.get());
+      channel_->ShareToGpuProcess(shared_state_shm_->handle());
   if (!base::SharedMemory::IsHandleValid(handle))
     return false;
 
@@ -202,6 +211,13 @@
                                           ++flush_count_));
 }
 
+void CommandBufferProxyImpl::SetLatencyInfo(
+    const cc::LatencyInfo& latency_info) {
+  if (last_state_.error != gpu::error::kNoError)
+    return;
+  Send(new GpuCommandBufferMsg_SetLatencyInfo(route_id_, latency_info));
+}
+
 gpu::CommandBuffer::State CommandBufferProxyImpl::FlushSync(
     int32 put_offset,
     int32 last_known_get) {
@@ -248,7 +264,7 @@
 
   scoped_ptr<base::SharedMemory> shared_memory(
       channel_->factory()->AllocateSharedMemory(size));
-  if (!shared_memory.get())
+  if (!shared_memory)
     return gpu::Buffer();
 
   DCHECK(!shared_memory->memory());
@@ -259,7 +275,7 @@
   // will leak. In otherwords, do not early out on error between here and the
   // sending of the RegisterTransferBuffer IPC below.
   base::SharedMemoryHandle handle =
-      channel_->ShareToGpuProcess(shared_memory.get());
+      channel_->ShareToGpuProcess(shared_memory->handle());
   if (!base::SharedMemory::IsHandleValid(handle))
     return gpu::Buffer();
 
@@ -420,6 +436,9 @@
 bool CommandBufferProxyImpl::GenerateMailboxNames(
     unsigned num,
     std::vector<gpu::Mailbox>* names) {
+  if (last_state_.error != gpu::error::kNoError)
+    return false;
+
   return channel_->GenerateMailboxNames(num, names);
 }
 
@@ -451,31 +470,28 @@
   return result;
 }
 
-GpuVideoDecodeAcceleratorHost*
+scoped_ptr<media::VideoDecodeAccelerator>
 CommandBufferProxyImpl::CreateVideoDecoder(
     media::VideoCodecProfile profile,
     media::VideoDecodeAccelerator::Client* client) {
   int decoder_route_id;
+  scoped_ptr<media::VideoDecodeAccelerator> vda;
   if (!Send(new GpuCommandBufferMsg_CreateVideoDecoder(route_id_, profile,
                                                        &decoder_route_id))) {
     LOG(ERROR) << "Send(GpuCommandBufferMsg_CreateVideoDecoder) failed";
-    return NULL;
+    return vda.Pass();
   }
 
   if (decoder_route_id < 0) {
     DLOG(ERROR) << "Failed to Initialize GPU decoder on profile: " << profile;
-    return NULL;
+    return vda.Pass();
   }
 
   GpuVideoDecodeAcceleratorHost* decoder_host =
-      new GpuVideoDecodeAcceleratorHost(channel_, decoder_route_id, client);
-  bool inserted = video_decoder_hosts_.insert(std::make_pair(
-      decoder_route_id, base::AsWeakPtr(decoder_host))).second;
-  DCHECK(inserted);
-
-  channel_->AddRoute(decoder_route_id, base::AsWeakPtr(decoder_host));
-
-  return decoder_host;
+      new GpuVideoDecodeAcceleratorHost(channel_, decoder_route_id, client,
+                                        this);
+  vda.reset(decoder_host);
+  return vda.Pass();
 }
 
 gpu::error::Error CommandBufferProxyImpl::GetLastError() {
diff --git a/content/common/gpu/client/command_buffer_proxy_impl.h b/content/common/gpu/client/command_buffer_proxy_impl.h
index 95f3c60..1f37af5 100644
--- a/content/common/gpu/client/command_buffer_proxy_impl.h
+++ b/content/common/gpu/client/command_buffer_proxy_impl.h
@@ -16,12 +16,14 @@
 #include "base/hash_tables.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
+#include "base/observer_list.h"
+#include "cc/debug/latency_info.h"
 #include "content/common/gpu/gpu_memory_allocation.h"
-#include "content/common/gpu/client/gpu_video_decode_accelerator_host.h"
 #include "content/common/gpu/gpu_memory_allocation.h"
 #include "gpu/command_buffer/common/command_buffer.h"
 #include "gpu/command_buffer/common/command_buffer_shared.h"
 #include "ipc/ipc_listener.h"
+#include "media/video/video_decode_accelerator.h"
 
 struct GPUCommandBufferConsoleMessage;
 
@@ -43,6 +45,15 @@
       public IPC::Listener,
       public base::SupportsWeakPtr<CommandBufferProxyImpl> {
  public:
+  class DeletionObserver {
+   public:
+    // Called during the destruction of the CommandBufferProxyImpl.
+    virtual void OnWillDeleteImpl() = 0;
+
+   protected:
+    virtual ~DeletionObserver() {}
+  };
+
   typedef base::Callback<void(
       const std::string& msg, int id)> GpuConsoleMessageCallback;
 
@@ -50,12 +61,12 @@
   virtual ~CommandBufferProxyImpl();
 
   // Sends an IPC message to create a GpuVideoDecodeAccelerator. Creates and
-  // returns a pointer to a GpuVideoDecodeAcceleratorHost.
-  // Returns NULL on failure to create the GpuVideoDecodeAcceleratorHost.
+  // returns it as an owned pointer to a media::VideoDecodeAccelerator.  Returns
+  // NULL on failure to create the GpuVideoDecodeAcceleratorHost.
   // Note that the GpuVideoDecodeAccelerator may still fail to be created in
   // the GPU process, even if this returns non-NULL. In this case the client is
   // notified of an error later.
-  GpuVideoDecodeAcceleratorHost* CreateVideoDecoder(
+  scoped_ptr<media::VideoDecodeAccelerator> CreateVideoDecoder(
       media::VideoCodecProfile profile,
       media::VideoDecodeAccelerator::Client* client);
 
@@ -93,6 +104,9 @@
       const base::Callback<void(const GpuMemoryAllocationForRenderer&)>&
           callback);
 
+  void AddDeletionObserver(DeletionObserver* observer);
+  void RemoveDeletionObserver(DeletionObserver* observer);
+
   bool DiscardBackbuffer();
   bool EnsureBackbuffer();
 
@@ -113,6 +127,8 @@
   void SetOnConsoleMessageCallback(
       const GpuConsoleMessageCallback& callback);
 
+  void SetLatencyInfo(const cc::LatencyInfo& latency_info);
+
   // TODO(apatrick): this is a temporary optimization while skia is calling
   // ContentGLContext::MakeCurrent prior to every GL call. It saves returning 6
   // ints redundantly when only the error is needed for the
@@ -125,7 +141,6 @@
 
  private:
   typedef std::map<int32, gpu::Buffer> TransferBufferMap;
-  typedef std::map<int, base::WeakPtr<GpuVideoDecodeAcceleratorHost> > Decoders;
   typedef base::hash_map<uint32, base::Closure> SignalTaskMap;
 
   // Send an IPC message over the GPU channel. This is private to fully
@@ -154,9 +169,8 @@
   // Local cache of id to transfer buffer mapping.
   TransferBufferMap transfer_buffers_;
 
-  // Zero or more (unowned!) video decoder hosts using this proxy, keyed by
-  // their decoder_route_id.
-  Decoders video_decoder_hosts_;
+  // Unowned list of DeletionObservers.
+  ObserverList<DeletionObserver> deletion_observers_;
 
   // The last cached state received from the service.
   State last_state_;
diff --git a/content/common/gpu/client/gl_helper.cc b/content/common/gpu/client/gl_helper.cc
index 0d295f0..09dcd1c 100644
--- a/content/common/gpu/client/gl_helper.cc
+++ b/content/common/gpu/client/gl_helper.cc
@@ -7,14 +7,11 @@
 #include <queue>
 
 #include "base/bind.h"
+#include "base/debug/trace_event.h"
 #include "base/lazy_instance.h"
 #include "base/logging.h"
-#include "base/memory/ref_counted.h"
 #include "base/message_loop.h"
-#include "base/synchronization/lock.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/threading/thread.h"
-#include "base/threading/thread_restrictions.h"
+#include "base/time.h"
 #include "third_party/WebKit/Source/Platform/chromium/public/WebCString.h"
 #include "third_party/WebKit/Source/Platform/chromium/public/WebString.h"
 #include "third_party/skia/include/core/SkRegion.h"
@@ -27,24 +24,6 @@
 
 namespace {
 
-const char kGLHelperThreadName[] = "GLHelperThread";
-
-class GLHelperThread : public base::Thread {
- public:
-  GLHelperThread() : base::Thread(kGLHelperThreadName) {
-    Start();
-  }
-  virtual ~GLHelperThread() {
-    Stop();
-  }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(GLHelperThread);
-};
-
-base::LazyInstance<GLHelperThread> g_gl_helper_thread =
-    LAZY_INSTANCE_INITIALIZER;
-
 class ScopedWebGLId {
  public:
   typedef void (WebGraphicsContext3D::*DeleteFunc)(WebGLId);
@@ -99,15 +78,6 @@
                       &WebGraphicsContext3D::deleteFramebuffer) {}
 };
 
-class ScopedRenderbuffer : public ScopedWebGLId {
- public:
-  ScopedRenderbuffer(WebGraphicsContext3D* context,
-                     WebGLId id)
-      : ScopedWebGLId(context,
-                      id,
-                      &WebGraphicsContext3D::deleteRenderbuffer) {}
-};
-
 class ScopedProgram : public ScopedWebGLId {
  public:
   ScopedProgram(WebGraphicsContext3D* context,
@@ -144,19 +114,16 @@
                WebGLId id,
                BindFunc bind_func)
       : context_(context),
-        id_(id),
         bind_func_(bind_func) {
-    (context_->*bind_func_)(target, id_);
+    (context_->*bind_func_)(target, id);
   }
 
   virtual ~ScopedBinder() {
-    if (id_ != 0)
-      (context_->*bind_func_)(target, 0);
+    (context_->*bind_func_)(target, 0);
   }
 
  private:
   WebGraphicsContext3D* context_;
-  WebGLId id_;
   BindFunc bind_func_;
 
   DISALLOW_COPY_AND_ASSIGN(ScopedBinder);
@@ -185,17 +152,6 @@
 };
 
 template <WebKit::WGC3Denum target>
-class ScopedRenderbufferBinder : ScopedBinder<target> {
- public:
-  ScopedRenderbufferBinder(WebGraphicsContext3D* context,
-                           WebGLId id)
-      : ScopedBinder<target>(
-          context,
-          id,
-          &WebGraphicsContext3D::bindRenderbuffer) {}
-};
-
-template <WebKit::WGC3Denum target>
 class ScopedTextureBinder : ScopedBinder<target> {
  public:
   ScopedTextureBinder(WebGraphicsContext3D* context,
@@ -222,27 +178,18 @@
   DISALLOW_COPY_AND_ASSIGN(ScopedFlush);
 };
 
-void DeleteContext(WebGraphicsContext3D* context) {
-  delete context;
-}
-
-void SignalWaitableEvent(base::WaitableEvent* event) {
-  event->Signal();
-}
-
 }  // namespace
 
 namespace content {
 
 // Implements GLHelper::CropScaleReadbackAndCleanTexture and encapsulates the
 // data needed for it.
-class GLHelper::CopyTextureToImpl {
+class GLHelper::CopyTextureToImpl :
+      public base::SupportsWeakPtr<GLHelper::CopyTextureToImpl> {
  public:
-  CopyTextureToImpl(WebGraphicsContext3D* context,
-                    WebGraphicsContext3D* context_for_thread,
+  CopyTextureToImpl(WebGraphicsContext3DCommandBufferImpl* context,
                     GLHelper* helper)
       : context_(context),
-        context_for_thread_(context_for_thread),
         helper_(helper),
         flush_(context),
         program_(context, context->createProgram()),
@@ -253,7 +200,6 @@
   }
   ~CopyTextureToImpl() {
     CancelRequests();
-    DeleteContextForThread();
   }
 
   void InitBuffer();
@@ -278,40 +224,66 @@
 
  private:
   // A single request to CropScaleReadbackAndCleanTexture.
-  // Thread-safety notes: the main thread creates instances of this class. The
-  // main thread can cancel the request, before it's handled by the helper
+  // The main thread can cancel the request, before it's handled by the helper
   // thread, by resetting the texture and pixels fields. Alternatively, the
   // thread marks that it handles the request by resetting the pixels field
   // (meaning it guarantees that the callback with be called).
   // In either case, the callback must be called exactly once, and the texture
   // must be deleted by the main thread context.
-  struct Request : public base::RefCountedThreadSafe<Request> {
-    Request(CopyTextureToImpl* impl,
-            WebGLId texture_,
+  struct Request {
+    Request(WebGLId texture_,
             const gfx::Size& size_,
             unsigned char* pixels_,
             const base::Callback<void(bool)>& callback_)
-        : copy_texture_impl(impl),
-        size(size_),
-        callback(callback_),
-        lock(),
-        texture(texture_),
-        pixels(pixels_) {
+        : size(size_),
+          callback(callback_),
+          texture(texture_),
+          pixels(pixels_),
+          buffer(0) {
     }
 
-    // These members are only accessed on the main thread.
-    GLHelper::CopyTextureToImpl* copy_texture_impl;
     gfx::Size size;
     base::Callback<void(bool)> callback;
 
-    // Locks access to below members, which can be accessed on any thread.
-    base::Lock lock;
     WebGLId texture;
     unsigned char* pixels;
+    GLuint buffer;
+  };
+
+  class ShaderProgram {
+   public:
+    ShaderProgram(WebGraphicsContext3D* context,
+                  GLHelper* helper) :
+        context_(context),
+        helper_(helper),
+        program_(context, context->createProgram()) {
+    }
+
+    void Setup(const WebKit::WGC3Dchar* vertex_shader_text,
+               const WebKit::WGC3Dchar* fragment_shader_text);
+    void UseProgram(const gfx::Size& src_size,
+                    const gfx::Rect& src_subrect,
+                    const gfx::Size& dst_size);
 
    private:
-    friend class base::RefCountedThreadSafe<Request>;
-    ~Request() {}
+    WebGraphicsContext3D* context_;
+    GLHelper* helper_;
+
+    // A program for copying a source texture into a destination texture.
+    ScopedProgram program_;
+
+    // The location of the position in the program.
+    WebKit::WGC3Dint position_location_;
+    // The location of the texture coordinate in the program.
+    WebKit::WGC3Dint texcoord_location_;
+    // The location of the source texture in the program.
+    WebKit::WGC3Dint texture_location_;
+    // The location of the texture coordinate of
+    // the sub-rectangle in the program.
+    WebKit::WGC3Dint src_subrect_location_;
+
+   private:
+    DISALLOW_COPY_AND_ASSIGN(ShaderProgram);
   };
 
   // Copies the block of pixels specified with |src_subrect| from |src_texture|,
@@ -321,16 +293,11 @@
                        const gfx::Size& src_size,
                        const gfx::Rect& src_subrect,
                        const gfx::Size& dst_size,
-                       bool vertically_flip_texture);
+                       bool vertically_flip_texture,
+                       bool swizzle);
 
-  // Deletes the context for GLHelperThread.
-  void DeleteContextForThread();
-  static void ReadBackFramebuffer(scoped_refptr<Request> request,
-                                  WebGraphicsContext3D* context,
-                                  scoped_refptr<base::TaskRunner> reply_loop);
-  static void ReadBackFramebufferComplete(scoped_refptr<Request> request,
-                                          bool result);
-  void FinishRequest(scoped_refptr<Request> request);
+  void ReadbackDone(Request* request);
+  void FinishRequest(Request* request, bool result);
   void CancelRequests();
 
   // Interleaved array of 2-dimentional vertex positions (x, y) and
@@ -343,9 +310,9 @@
   // GLHelper::ReadbackTextureSync
   static const WebKit::WGC3Dchar kCopyVertexShader[];
   static const WebKit::WGC3Dchar kCopyFragmentShader[];
+  static const WebKit::WGC3Dchar kCopyAndSwizzleShader[];
 
-  WebGraphicsContext3D* context_;
-  WebGraphicsContext3D* context_for_thread_;
+  WebGraphicsContext3DCommandBufferImpl* context_;
   GLHelper* helper_;
 
   // A scoped flush that will ensure all resource deletions are flushed when
@@ -358,15 +325,10 @@
   ScopedBuffer vertex_attributes_buffer_;
   ScopedBuffer flipped_vertex_attributes_buffer_;
 
-  // The location of the position in the program.
-  WebKit::WGC3Dint position_location_;
-  // The location of the texture coordinate in the program.
-  WebKit::WGC3Dint texcoord_location_;
-  // The location of the source texture in the program.
-  WebKit::WGC3Dint texture_location_;
-  // The location of the texture coordinate of the sub-rectangle in the program.
-  WebKit::WGC3Dint src_subrect_location_;
-  std::queue<scoped_refptr<Request> > request_queue_;
+  scoped_ptr<ShaderProgram> no_swizzle_program_;
+  scoped_ptr<ShaderProgram> swizzle_program_;
+
+  std::queue<Request*> request_queue_;
 };
 
 const WebKit::WGC3Dfloat GLHelper::CopyTextureToImpl::kVertexAttributes[] = {
@@ -394,6 +356,7 @@
     "  v_texcoord = src_subrect.xy + a_texcoord * src_subrect.zw;"
     "}";
 
+
 const WebKit::WGC3Dchar GLHelper::CopyTextureToImpl::kCopyFragmentShader[] =
     "precision mediump float;"
     "varying vec2 v_texcoord;"
@@ -402,6 +365,15 @@
     "  gl_FragColor = texture2D(s_texture, v_texcoord);"
     "}";
 
+const WebKit::WGC3Dchar GLHelper::CopyTextureToImpl::kCopyAndSwizzleShader[] =
+    "precision mediump float;"
+    "varying vec2 v_texcoord;"
+    "uniform sampler2D s_texture;"
+    "void main() {"
+    "  gl_FragColor = texture2D(s_texture, v_texcoord).bgra;"
+    "}";
+
+
 void GLHelper::CopyTextureToImpl::InitBuffer() {
   ScopedBufferBinder<GL_ARRAY_BUFFER> buffer_binder(
       context_, vertex_attributes_buffer_);
@@ -418,14 +390,23 @@
 }
 
 void GLHelper::CopyTextureToImpl::InitProgram() {
+  no_swizzle_program_.reset(new ShaderProgram(context_, helper_));
+  no_swizzle_program_->Setup(kCopyVertexShader, kCopyFragmentShader);
+  swizzle_program_.reset(new ShaderProgram(context_, helper_));
+  swizzle_program_->Setup(kCopyVertexShader, kCopyAndSwizzleShader);
+}
+
+void GLHelper::CopyTextureToImpl::ShaderProgram::Setup(
+    const WebKit::WGC3Dchar* vertex_shader_text,
+    const WebKit::WGC3Dchar* fragment_shader_text) {
   // Shaders to map the source texture to |dst_texture_|.
   ScopedShader vertex_shader(context_, helper_->CompileShaderFromSource(
-      kCopyVertexShader, GL_VERTEX_SHADER));
-  DCHECK_NE(0U, vertex_shader.id());
+      vertex_shader_text, GL_VERTEX_SHADER));
+  DCHECK(vertex_shader.id());
   context_->attachShader(program_, vertex_shader);
   ScopedShader fragment_shader(context_, helper_->CompileShaderFromSource(
-      kCopyFragmentShader, GL_FRAGMENT_SHADER));
-  DCHECK_NE(0U, fragment_shader.id());
+      fragment_shader_text, GL_FRAGMENT_SHADER));
+  DCHECK(fragment_shader.id());
   context_->attachShader(program_, fragment_shader);
   context_->linkProgram(program_);
 
@@ -442,20 +423,57 @@
   src_subrect_location_ = context_->getUniformLocation(program_, "src_subrect");
 }
 
+
+void GLHelper::CopyTextureToImpl::ShaderProgram::UseProgram(
+    const gfx::Size& src_size,
+    const gfx::Rect& src_subrect,
+    const gfx::Size& dst_size) {
+  context_->useProgram(program_);
+
+  WebKit::WGC3Dintptr offset = 0;
+  context_->vertexAttribPointer(position_location_,
+                                2,
+                                GL_FLOAT,
+                                GL_FALSE,
+                                4 * sizeof(WebKit::WGC3Dfloat),
+                                offset);
+  context_->enableVertexAttribArray(position_location_);
+
+  offset += 2 * sizeof(WebKit::WGC3Dfloat);
+  context_->vertexAttribPointer(texcoord_location_,
+                                2,
+                                GL_FLOAT,
+                                GL_FALSE,
+                                4 * sizeof(WebKit::WGC3Dfloat),
+                                offset);
+  context_->enableVertexAttribArray(texcoord_location_);
+
+  context_->uniform1i(texture_location_, 0);
+
+  // Convert |src_subrect| to texture coordinates.
+  GLfloat src_subrect_texcoord[] = {
+    static_cast<float>(src_subrect.x()) / src_size.width(),
+    static_cast<float>(src_subrect.y()) / src_size.height(),
+    static_cast<float>(src_subrect.width()) / src_size.width(),
+    static_cast<float>(src_subrect.height()) / src_size.height(),
+  };
+  context_->uniform4fv(src_subrect_location_, 1, src_subrect_texcoord);
+}
+
 WebGLId GLHelper::CopyTextureToImpl::ScaleTexture(
     WebGLId src_texture,
     const gfx::Size& src_size,
     const gfx::Rect& src_subrect,
     const gfx::Size& dst_size,
-    bool vertically_flip_texture) {
+    bool vertically_flip_texture,
+    bool swizzle) {
   WebGLId dst_texture = context_->createTexture();
   {
     ScopedFramebuffer dst_framebuffer(context_, context_->createFramebuffer());
-    ScopedFramebufferBinder<GL_FRAMEBUFFER> framebuffer_binder(
-        context_, dst_framebuffer);
+    ScopedFramebufferBinder<GL_FRAMEBUFFER> framebuffer_binder(context_,
+                                                               dst_framebuffer);
     {
-      ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(
-          context_, dst_texture);
+      ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(context_, dst_texture);
       context_->texImage2D(GL_TEXTURE_2D,
                            0,
                            GL_RGBA,
@@ -475,41 +493,17 @@
     ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(context_, src_texture);
     WebKit::WebGLId vertex_attributes_buffer = vertically_flip_texture ?
         flipped_vertex_attributes_buffer_ : vertex_attributes_buffer_;
-    ScopedBufferBinder<GL_ARRAY_BUFFER> buffer_binder(
-        context_, vertex_attributes_buffer);
+    ScopedBufferBinder<GL_ARRAY_BUFFER> buffer_binder(context_,
+                                                      vertex_attributes_buffer);
 
     context_->viewport(0, 0, dst_size.width(), dst_size.height());
-    context_->useProgram(program_);
-
-    WebKit::WGC3Dintptr offset = 0;
-    context_->vertexAttribPointer(position_location_,
-                                  2,
-                                  GL_FLOAT,
-                                  GL_FALSE,
-                                  4 * sizeof(WebKit::WGC3Dfloat),
-                                  offset);
-    context_->enableVertexAttribArray(position_location_);
-
-    offset += 2 * sizeof(WebKit::WGC3Dfloat);
-    context_->vertexAttribPointer(texcoord_location_,
-                                  2,
-                                  GL_FLOAT,
-                                  GL_FALSE,
-                                  4 * sizeof(WebKit::WGC3Dfloat),
-                                  offset);
-    context_->enableVertexAttribArray(texcoord_location_);
-
-    context_->uniform1i(texture_location_, 0);
-
-    // Convert |src_subrect| to texture coordinates.
-    GLfloat src_subrect_texcoord[] = {
-      static_cast<float>(src_subrect.x()) / src_size.width(),
-      static_cast<float>(src_subrect.y()) / src_size.height(),
-      static_cast<float>(src_subrect.width()) / src_size.width(),
-      static_cast<float>(src_subrect.height()) / src_size.height(),
-    };
-
-    context_->uniform4fv(src_subrect_location_, 1, src_subrect_texcoord);
+    ShaderProgram* program;
+    if (swizzle) {
+      program = swizzle_program_.get();
+    } else {
+      program = no_swizzle_program_.get();
+    }
+    program->UseProgram(src_size, src_subrect, dst_size);
 
     // Conduct texture mapping by drawing a quad composed of two triangles.
     context_->drawArrays(GL_TRIANGLE_STRIP, 0, 4);
@@ -517,17 +511,6 @@
   return dst_texture;
 }
 
-void GLHelper::CopyTextureToImpl::DeleteContextForThread() {
-  if (!context_for_thread_)
-    return;
-
-  g_gl_helper_thread.Pointer()->message_loop_proxy()->PostTask(
-      FROM_HERE,
-      base::Bind(&DeleteContext,
-                 context_for_thread_));
-  context_for_thread_ = NULL;
-}
-
 void GLHelper::CopyTextureToImpl::CropScaleReadbackAndCleanTexture(
     WebGLId src_texture,
     const gfx::Size& src_size,
@@ -535,34 +518,56 @@
     const gfx::Size& dst_size,
     unsigned char* out,
     const base::Callback<void(bool)>& callback) {
-  if (!context_for_thread_) {
-    callback.Run(false);
-    return;
-  }
-
   WebGLId texture = ScaleTexture(src_texture,
                                  src_size,
                                  src_subrect,
                                  dst_size,
-                                 false);
+                                 true,
+#if (SK_R32_SHIFT == 16) && !SK_B32_SHIFT
+                                 true
+#else
+                                 false
+#endif
+                                 );
   context_->flush();
-  scoped_refptr<Request> request =
-      new Request(this, texture, dst_size, out, callback);
+  Request* request = new Request(texture, dst_size, out, callback);
   request_queue_.push(request);
 
-  g_gl_helper_thread.Pointer()->message_loop_proxy()->PostTask(FROM_HERE,
-      base::Bind(&ReadBackFramebuffer,
-                 request,
-                 context_for_thread_,
-                 base::MessageLoopProxy::current()));
+  ScopedFlush flush(context_);
+  ScopedFramebuffer dst_framebuffer(context_, context_->createFramebuffer());
+  gfx::Size size;
+  size = request->size;
+
+  ScopedFramebufferBinder<GL_FRAMEBUFFER> framebuffer_binder(context_,
+                                                             dst_framebuffer);
+  ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(context_, request->texture);
+  context_->framebufferTexture2D(GL_FRAMEBUFFER,
+                                 GL_COLOR_ATTACHMENT0,
+                                 GL_TEXTURE_2D,
+                                 request->texture,
+                                 0);
+  request->buffer = context_->createBuffer();
+  context_->bindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM,
+                       request->buffer);
+  context_->bufferData(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM,
+                       4 * size.GetArea(),
+                       NULL,
+                       GL_STREAM_READ);
+
+  context_->readPixels(0, 0, size.width(), size.height(),
+                       GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+  context_->bindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, 0);
+  context_->GetCommandBufferProxy()->SignalSyncPoint(
+      context_->insertSyncPoint(),
+      base::Bind(&CopyTextureToImpl::ReadbackDone, AsWeakPtr(), request));
 }
 
 void GLHelper::CopyTextureToImpl::ReadbackTextureSync(WebGLId texture,
                                                       const gfx::Rect& src_rect,
                                                       unsigned char* out) {
   ScopedFramebuffer dst_framebuffer(context_, context_->createFramebuffer());
-  ScopedFramebufferBinder<GL_FRAMEBUFFER> framebuffer_binder(
-      context_, dst_framebuffer);
+  ScopedFramebufferBinder<GL_FRAMEBUFFER> framebuffer_binder(context_,
+                                                             dst_framebuffer);
   ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(context_, texture);
   context_->framebufferTexture2D(GL_FRAMEBUFFER,
                                  GL_COLOR_ATTACHMENT0,
@@ -587,139 +592,64 @@
                       src_size,
                       gfx::Rect(src_size),
                       dst_size,
-                      vertically_flip_texture);
+                      vertically_flip_texture,
+                      false);
 }
 
-void GLHelper::CopyTextureToImpl::ReadBackFramebuffer(
-    scoped_refptr<Request> request,
-    WebGraphicsContext3D* context,
-    scoped_refptr<base::TaskRunner> reply_loop) {
-  DCHECK(context);
-  if (!context->makeContextCurrent() || context->isContextLost()) {
-    base::AutoLock auto_lock(request->lock);
-    if (request->pixels) {
-      // Only report failure if the request wasn't canceled (otherwise the
-      // failure has already been reported).
-      request->pixels = NULL;
-      reply_loop->PostTask(
-          FROM_HERE, base::Bind(ReadBackFramebufferComplete, request, false));
+void GLHelper::CopyTextureToImpl::ReadbackDone(Request* request) {
+  TRACE_EVENT0("mirror",
+               "GLHelper::CopyTextureToImpl::CheckReadBackFramebufferComplete");
+  DCHECK(request == request_queue_.front());
+
+  bool result = false;
+  if (request->buffer != 0) {
+    context_->bindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM,
+                         request->buffer);
+    void* data = context_->mapBufferCHROMIUM(
+        GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, GL_READ_ONLY);
+
+    if (data) {
+      result = true;
+      memcpy(request->pixels, data, request->size.GetArea() * 4);
+      context_->unmapBufferCHROMIUM(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM);
     }
-    return;
+    context_->bindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, 0);
   }
-  ScopedFlush flush(context);
-  ScopedFramebuffer dst_framebuffer(context, context->createFramebuffer());
-  unsigned char* pixels = NULL;
-  gfx::Size size;
-  {
-    // Note: We don't want to keep the lock while doing the readBack (since we
-    // don't want to block the UI thread). We rely on the fact that once the
-    // texture is bound to a FBO (that isn't current), deleting the texture is
-    // delayed until the FBO is deleted. We ensure ordering by flushing while
-    // the lock is held. Either the main thread cancelled before we get the
-    // lock, and we'll exit early, or we ensure that the texture is bound to the
-    // framebuffer before the main thread has a chance to delete it.
-    base::AutoLock auto_lock(request->lock);
-    if (!request->texture || !request->pixels)
-      return;
-    pixels = request->pixels;
-    request->pixels = NULL;
-    size = request->size;
-    {
-      ScopedFlush flush(context);
-      ScopedFramebufferBinder<GL_FRAMEBUFFER> framebuffer_binder(
-          context, dst_framebuffer);
-      ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(
-          context, request->texture);
-      context->framebufferTexture2D(GL_FRAMEBUFFER,
-                                    GL_COLOR_ATTACHMENT0,
-                                    GL_TEXTURE_2D,
-                                    request->texture,
-                                    0);
-    }
-  }
-  bool result = context->readBackFramebuffer(
-        pixels,
-        4 * size.GetArea(),
-        dst_framebuffer.id(),
-        size.width(),
-        size.height());
-  reply_loop->PostTask(
-      FROM_HERE, base::Bind(ReadBackFramebufferComplete, request, result));
+
+  FinishRequest(request, result);
 }
 
-void GLHelper::CopyTextureToImpl::ReadBackFramebufferComplete(
-    scoped_refptr<Request> request,
-    bool result) {
-  request->callback.Run(result);
-  if (request->copy_texture_impl)
-    request->copy_texture_impl->FinishRequest(request);
-}
-
-void GLHelper::CopyTextureToImpl::FinishRequest(
-    scoped_refptr<Request> request) {
-  CHECK(request_queue_.front() == request);
+void GLHelper::CopyTextureToImpl::FinishRequest(Request* request, bool result) {
+  DCHECK(request_queue_.front() == request);
   request_queue_.pop();
-  base::AutoLock auto_lock(request->lock);
+  request->callback.Run(result);
+  ScopedFlush flush(context_);
   if (request->texture != 0) {
     context_->deleteTexture(request->texture);
     request->texture = 0;
-    context_->flush();
   }
+  if (request->buffer != 0) {
+    context_->deleteBuffer(request->buffer);
+    request->buffer = 0;
+  }
+  delete request;
 }
 
 void GLHelper::CopyTextureToImpl::CancelRequests() {
   while (!request_queue_.empty()) {
-    scoped_refptr<Request> request = request_queue_.front();
-    request_queue_.pop();
-    request->copy_texture_impl = NULL;
-    bool cancelled = false;
-    {
-      base::AutoLock auto_lock(request->lock);
-      if (request->texture != 0) {
-        context_->deleteTexture(request->texture);
-        request->texture = 0;
-      }
-      if (request->pixels != NULL) {
-        request->pixels = NULL;
-        cancelled = true;
-      }
-    }
-    if (cancelled)
-      request->callback.Run(false);
+    Request* request = request_queue_.front();
+    FinishRequest(request, false);
   }
 }
 
-base::subtle::Atomic32 GLHelper::count_ = 0;
-
-GLHelper::GLHelper(WebGraphicsContext3D* context,
-                   WebGraphicsContext3D* context_for_thread)
-    : context_(context),
-      context_for_thread_(context_for_thread) {
-  base::subtle::NoBarrier_AtomicIncrement(&count_, 1);
+GLHelper::GLHelper(WebGraphicsContext3DCommandBufferImpl* context)
+    : context_(context) {
 }
 
 GLHelper::~GLHelper() {
-  DCHECK_NE(MessageLoop::current(),
-            g_gl_helper_thread.Pointer()->message_loop());
-  base::subtle::Atomic32 decremented_count =
-    base::subtle::NoBarrier_AtomicIncrement(&count_, -1);
-  if (decremented_count == 0) {
-    // When this is the last instance, we synchronize with the pending
-    // operations on GLHelperThread. Otherwise on shutdown we may kill the GPU
-    // process infrastructure (BrowserGpuChannelHostFactory) before they have
-    // a chance to complete, likely leading to a crash.
-    base::WaitableEvent event(false, false);
-    g_gl_helper_thread.Pointer()->message_loop_proxy()->PostTask(
-        FROM_HERE,
-        base::Bind(&SignalWaitableEvent,
-                   &event));
-    // http://crbug.com/125415
-    base::ThreadRestrictions::ScopedAllowWait allow_wait;
-    event.Wait();
-  }
 }
 
-WebGraphicsContext3D* GLHelper::context() const {
+WebGraphicsContext3DCommandBufferImpl* GLHelper::context() const {
   return context_;
 }
 
@@ -785,10 +715,8 @@
 
 void GLHelper::InitCopyTextToImpl() {
   // Lazily initialize |copy_texture_to_impl_|
-  if (!copy_texture_to_impl_.get())
-    copy_texture_to_impl_.reset(new CopyTextureToImpl(context_,
-                                                      context_for_thread_,
-                                                      this));
+  if (!copy_texture_to_impl_)
+    copy_texture_to_impl_.reset(new CopyTextureToImpl(context_, this));
 }
 
 void GLHelper::CopySubBufferDamage(WebKit::WebGLId texture,
@@ -798,8 +726,8 @@
   SkRegion region(old_damage);
   if (region.op(new_damage, SkRegion::kDifference_Op)) {
     ScopedFramebuffer dst_framebuffer(context_, context_->createFramebuffer());
-    ScopedFramebufferBinder<GL_FRAMEBUFFER> framebuffer_binder(
-        context_, dst_framebuffer);
+    ScopedFramebufferBinder<GL_FRAMEBUFFER> framebuffer_binder(context_,
+                                                               dst_framebuffer);
     ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(context_, texture);
     context_->framebufferTexture2D(GL_FRAMEBUFFER,
                                    GL_COLOR_ATTACHMENT0,
diff --git a/content/common/gpu/client/gl_helper.h b/content/common/gpu/client/gl_helper.h
index 40e25eb..2908f6e 100644
--- a/content/common/gpu/client/gl_helper.h
+++ b/content/common/gpu/client/gl_helper.h
@@ -9,7 +9,7 @@
 #include "base/basictypes.h"
 #include "base/callback.h"
 #include "base/memory/scoped_ptr.h"
-#include "third_party/WebKit/Source/Platform/chromium/public/WebGraphicsContext3D.h"
+#include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h"
 
 namespace gfx {
 class Rect;
@@ -24,11 +24,10 @@
 // interfaces.
 class GLHelper {
  public:
-  GLHelper(WebKit::WebGraphicsContext3D* context,
-           WebKit::WebGraphicsContext3D* context_for_thread);
+  explicit GLHelper(WebGraphicsContext3DCommandBufferImpl* context);
   virtual ~GLHelper();
 
-  WebKit::WebGraphicsContext3D* context() const;
+  WebGraphicsContext3DCommandBufferImpl* context() const;
 
   // Copies the block of pixels specified with |src_subrect| from |src_texture|,
   // scales it to |dst_size|, and writes it into |out|.
@@ -81,13 +80,9 @@
   // Creates |copy_texture_to_impl_| if NULL.
   void InitCopyTextToImpl();
 
-  WebKit::WebGraphicsContext3D* context_;
-  WebKit::WebGraphicsContext3D* context_for_thread_;
+  WebGraphicsContext3DCommandBufferImpl* context_;
   scoped_ptr<CopyTextureToImpl> copy_texture_to_impl_;
 
-  // The number of all GLHelper instances.
-  static base::subtle::Atomic32 count_;
-
   DISALLOW_COPY_AND_ASSIGN(GLHelper);
 };
 
diff --git a/content/common/gpu/client/gpu_channel_host.cc b/content/common/gpu/client/gpu_channel_host.cc
index d5bb6b3..91ff7a6 100644
--- a/content/common/gpu/client/gpu_channel_host.cc
+++ b/content/common/gpu/client/gpu_channel_host.cc
@@ -8,6 +8,7 @@
 #include "base/debug/trace_event.h"
 #include "base/message_loop.h"
 #include "base/message_loop_proxy.h"
+#include "base/posix/eintr_wrapper.h"
 #include "base/threading/thread_restrictions.h"
 #include "content/common/gpu/client/command_buffer_proxy_impl.h"
 #include "content/common/gpu/gpu_messages.h"
@@ -111,12 +112,12 @@
   // TODO: Can we just always use sync_filter_ since we setup the channel
   //       without a main listener?
   if (factory_->IsMainThread()) {
-    if (channel_.get()) {
+    if (channel_) {
       // http://crbug.com/125264
       base::ThreadRestrictions::ScopedAllowWait allow_wait;
       return channel_->Send(message);
     }
-  } else if (MessageLoop::current()) {
+  } else if (base::MessageLoop::current()) {
     return sync_filter_->Send(message);
   }
 
@@ -140,7 +141,7 @@
 
   AutoLock lock(context_lock_);
   // An error occurred. Need to get the host again to reinitialize it.
-  if (!channel_.get())
+  if (!channel_)
     return NULL;
 
   GPUCreateCommandBufferConfig init_params;
@@ -172,7 +173,7 @@
 
   AutoLock lock(context_lock_);
   // An error occurred. Need to get the host again to reinitialize it.
-  if (!channel_.get())
+  if (!channel_)
     return NULL;
 
   GPUCreateCommandBufferConfig init_params;
@@ -199,7 +200,7 @@
   return command_buffer;
 }
 
-GpuVideoDecodeAcceleratorHost* GpuChannelHost::CreateVideoDecoder(
+scoped_ptr<media::VideoDecodeAccelerator> GpuChannelHost::CreateVideoDecoder(
     int command_buffer_route_id,
     media::VideoCodecProfile profile,
     media::VideoDecodeAccelerator::Client* client) {
@@ -207,7 +208,7 @@
   ProxyMap::iterator it = proxies_.find(command_buffer_route_id);
   DCHECK(it != proxies_.end());
   CommandBufferProxyImpl* proxy = it->second;
-  return proxy->CreateVideoDecoder(profile, client);
+  return proxy->CreateVideoDecoder(profile, client).Pass();
 }
 
 void GpuChannelHost::DestroyCommandBuffer(
@@ -251,28 +252,31 @@
 }
 
 base::SharedMemoryHandle GpuChannelHost::ShareToGpuProcess(
-    base::SharedMemory* shared_memory) {
+    base::SharedMemoryHandle source_handle) {
   AutoLock lock(context_lock_);
 
-  if (!channel_.get())
+  if (!channel_)
     return base::SharedMemory::NULLHandle();
 
-  base::SharedMemoryHandle handle;
 #if defined(OS_WIN)
   // Windows needs to explicitly duplicate the handle out to another process.
-  if (!BrokerDuplicateHandle(shared_memory->handle(),
+  base::SharedMemoryHandle target_handle;
+  if (!BrokerDuplicateHandle(source_handle,
                              channel_->peer_pid(),
-                             &handle,
-                             FILE_MAP_WRITE,
-                             0)) {
+                             &target_handle,
+                             0,
+                             DUPLICATE_SAME_ACCESS)) {
     return base::SharedMemory::NULLHandle();
   }
-#else
-  if (!shared_memory->ShareToProcess(channel_->peer_pid(), &handle))
-    return base::SharedMemory::NULLHandle();
-#endif
 
-  return handle;
+  return target_handle;
+#else
+  int duped_handle = HANDLE_EINTR(dup(source_handle.fd));
+  if (duped_handle < 0)
+    return base::SharedMemory::NULLHandle();
+
+  return base::FileDescriptor(duped_handle, true);
+#endif
 }
 
 bool GpuChannelHost::GenerateMailboxNames(unsigned num,
@@ -321,7 +325,7 @@
     base::WeakPtr<GpuChannelHost> parent,
     GpuChannelHostFactory* factory)
     : parent_(parent),
-      factory_(factory) {
+      main_thread_loop_(factory->GetMainLoop()->message_loop_proxy()) {
 }
 
 GpuChannelHost::MessageFilter::~MessageFilter() {}
@@ -330,7 +334,6 @@
     int route_id,
     base::WeakPtr<IPC::Listener> listener,
     scoped_refptr<MessageLoopProxy> loop) {
-  DCHECK(factory_->IsIOThread());
   DCHECK(listeners_.find(route_id) == listeners_.end());
   GpuListenerInfo info;
   info.listener = listener;
@@ -339,7 +342,6 @@
 }
 
 void GpuChannelHost::MessageFilter::RemoveRoute(int route_id) {
-  DCHECK(factory_->IsIOThread());
   ListenerMap::iterator it = listeners_.find(route_id);
   if (it != listeners_.end())
     listeners_.erase(it);
@@ -347,18 +349,14 @@
 
 bool GpuChannelHost::MessageFilter::OnMessageReceived(
     const IPC::Message& message) {
-  DCHECK(factory_->IsIOThread());
-
   // Never handle sync message replies or we will deadlock here.
   if (message.is_reply())
     return false;
 
   if (message.routing_id() == MSG_ROUTING_CONTROL) {
-    MessageLoop* main_loop = factory_->GetMainLoop();
-    main_loop->PostTask(FROM_HERE,
-                        base::Bind(&GpuChannelHost::OnMessageReceived,
-                                   parent_,
-                                   message));
+    main_thread_loop_->PostTask(
+        FROM_HERE, base::Bind(
+            &GpuChannelHost::OnMessageReceived, parent_, message));
     return true;
   }
 
@@ -378,14 +376,12 @@
 }
 
 void GpuChannelHost::MessageFilter::OnChannelError() {
-  DCHECK(factory_->IsIOThread());
-
   // Post the task to signal the GpuChannelHost before the proxies. That way, if
   // they themselves post a task to recreate the context, they will not try to
   // re-use this channel host before it has a chance to mark itself lost.
-  MessageLoop* main_loop = factory_->GetMainLoop();
-  main_loop->PostTask(FROM_HERE,
-                      base::Bind(&GpuChannelHost::OnChannelError, parent_));
+  main_thread_loop_->PostTask(
+      FROM_HERE,
+      base::Bind(&GpuChannelHost::OnChannelError, parent_));
   // Inform all the proxies that an error has occurred. This will be reported
   // via OpenGL as a lost context.
   for (ListenerMap::iterator it = listeners_.begin();
diff --git a/content/common/gpu/client/gpu_channel_host.h b/content/common/gpu/client/gpu_channel_host.h
index 9f55d5a..c52505a 100644
--- a/content/common/gpu/client/gpu_channel_host.h
+++ b/content/common/gpu/client/gpu_channel_host.h
@@ -17,23 +17,23 @@
 #include "base/process_util.h"
 #include "base/synchronization/lock.h"
 #include "content/common/content_export.h"
-#include "content/common/gpu/client/gpu_video_decode_accelerator_host.h"
 #include "content/common/gpu/gpu_process_launch_causes.h"
 #include "content/common/message_router.h"
 #include "content/public/common/gpu_info.h"
 #include "ipc/ipc_channel_handle.h"
 #include "ipc/ipc_channel_proxy.h"
 #include "ipc/ipc_sync_channel.h"
+#include "media/video/video_decode_accelerator.h"
 #include "ui/gfx/native_widget_types.h"
 #include "ui/gfx/size.h"
 #include "ui/gl/gpu_preference.h"
 
 class GURL;
-class MessageLoop;
 class TransportTextureService;
 struct GPUCreateCommandBufferConfig;
 
 namespace base {
+class MessageLoop;
 class MessageLoopProxy;
 }
 
@@ -47,6 +47,7 @@
 
 namespace content {
 class CommandBufferProxyImpl;
+class GpuChannelHost;
 struct GpuRenderingStats;
 
 struct GpuListenerInfo {
@@ -65,7 +66,7 @@
 
   virtual bool IsMainThread() = 0;
   virtual bool IsIOThread() = 0;
-  virtual MessageLoop* GetMainLoop() = 0;
+  virtual base::MessageLoop* GetMainLoop() = 0;
   virtual scoped_refptr<base::MessageLoopProxy> GetIOLoopProxy() = 0;
   virtual base::WaitableEvent* GetShutDownEvent() = 0;
   virtual scoped_ptr<base::SharedMemory> AllocateSharedMemory(size_t size) = 0;
@@ -137,8 +138,7 @@
       gfx::GpuPreference gpu_preference);
 
   // Creates a video decoder in the GPU process.
-  // Returned pointer is owned by the CommandBufferProxy for |route_id|.
-  GpuVideoDecodeAcceleratorHost* CreateVideoDecoder(
+  scoped_ptr<media::VideoDecodeAccelerator> CreateVideoDecoder(
       int command_buffer_route_id,
       media::VideoCodecProfile profile,
       media::VideoDecodeAccelerator::Client* client);
@@ -157,18 +157,13 @@
   GpuChannelHostFactory* factory() const { return factory_; }
   int gpu_host_id() const { return gpu_host_id_; }
 
-  // Do not use this function! It does not take the context lock and even
-  // if it did the PID might become invalid immediately after releasing it
-  // TODO(apatrick): Make all callers use ShareToGpuProcess().
-  base::ProcessId gpu_pid() const { return channel_->peer_pid(); }
-
   int client_id() const { return client_id_; }
 
   // Returns a handle to the shared memory that can be sent via IPC to the
   // GPU process. The caller is responsible for ensuring it is closed. Returns
   // an invalid handle on failure.
   base::SharedMemoryHandle ShareToGpuProcess(
-      base::SharedMemory* shared_memory);
+      base::SharedMemoryHandle source_handle);
 
   // Generates n unique mailbox names that can be used with
   // GL_texture_mailbox_CHROMIUM. Unlike genMailboxCHROMIUM, this IPC is
@@ -210,7 +205,7 @@
     // MessageFilter lives.
     base::WeakPtr<GpuChannelHost> parent_;
 
-    GpuChannelHostFactory* factory_;
+    scoped_refptr<base::MessageLoopProxy> main_thread_loop_;
 
     typedef base::hash_map<int, GpuListenerInfo> ListenerMap;
     ListenerMap listeners_;
diff --git a/content/common/gpu/client/gpu_video_decode_accelerator_host.cc b/content/common/gpu/client/gpu_video_decode_accelerator_host.cc
index c5fdb18..7288c69 100644
--- a/content/common/gpu/client/gpu_video_decode_accelerator_host.cc
+++ b/content/common/gpu/client/gpu_video_decode_accelerator_host.cc
@@ -23,18 +23,25 @@
 GpuVideoDecodeAcceleratorHost::GpuVideoDecodeAcceleratorHost(
     GpuChannelHost* channel,
     int32 decoder_route_id,
-    VideoDecodeAccelerator::Client* client)
+    VideoDecodeAccelerator::Client* client,
+    CommandBufferProxyImpl* impl)
     : channel_(channel),
       decoder_route_id_(decoder_route_id),
-      client_(client) {
+      client_(client),
+      impl_(impl) {
   DCHECK(channel_);
   DCHECK(client_);
+  channel_->AddRoute(decoder_route_id, base::AsWeakPtr(this));
+  impl_->AddDeletionObserver(this);
 }
 
 void GpuVideoDecodeAcceleratorHost::OnChannelError() {
   DLOG(ERROR) << "GpuVideoDecodeAcceleratorHost::OnChannelError()";
   OnErrorNotification(PLATFORM_FAILURE);
-  channel_ = NULL;
+  if (channel_) {
+    channel_->RemoveRoute(decoder_route_id_);
+    channel_ = NULL;
+  }
 }
 
 bool GpuVideoDecodeAcceleratorHost::OnMessageReceived(const IPC::Message& msg) {
@@ -71,19 +78,16 @@
   // Can happen if a decode task was posted before an error was delivered.
   if (!channel_)
     return;
-  base::SharedMemoryHandle buffer_handle = bitstream_buffer.handle();
-#if defined(OS_WIN)
-  if (!BrokerDuplicateHandle(bitstream_buffer.handle(),
-                             channel_->gpu_pid(),
-                             &buffer_handle, 0,
-                             DUPLICATE_SAME_ACCESS)) {
+
+  base::SharedMemoryHandle handle = channel_->ShareToGpuProcess(
+      bitstream_buffer.handle());
+  if (!base::SharedMemory::IsHandleValid(handle)) {
     NOTREACHED() << "Failed to duplicate buffer handler";
     return;
   }
-#endif  // OS_WIN
 
   Send(new AcceleratedVideoDecoderMsg_Decode(
-      decoder_route_id_, buffer_handle, bitstream_buffer.id(),
+      decoder_route_id_, handle, bitstream_buffer.id(),
       bitstream_buffer.size()));
 }
 
@@ -123,16 +127,26 @@
 
 void GpuVideoDecodeAcceleratorHost::Destroy() {
   DCHECK(CalledOnValidThread());
-  if (channel_)
-    channel_->RemoveRoute(decoder_route_id_);
   client_ = NULL;
   Send(new AcceleratedVideoDecoderMsg_Destroy(decoder_route_id_));
   delete this;
 }
 
+void GpuVideoDecodeAcceleratorHost::OnWillDeleteImpl() {
+  impl_ = NULL;
+
+  // The CommandBufferProxyImpl is going away; error out this VDA.
+  OnChannelError();
+}
+
 GpuVideoDecodeAcceleratorHost::~GpuVideoDecodeAcceleratorHost() {
   DCHECK(CalledOnValidThread());
   DCHECK(!client_) << "destructor called without Destroy being called!";
+
+  if (channel_)
+    channel_->RemoveRoute(decoder_route_id_);
+  if (impl_)
+    impl_->RemoveDeletionObserver(this);
 }
 
 void GpuVideoDecodeAcceleratorHost::Send(IPC::Message* message) {
diff --git a/content/common/gpu/client/gpu_video_decode_accelerator_host.h b/content/common/gpu/client/gpu_video_decode_accelerator_host.h
index fc1c040..ed67571 100644
--- a/content/common/gpu/client/gpu_video_decode_accelerator_host.h
+++ b/content/common/gpu/client/gpu_video_decode_accelerator_host.h
@@ -9,6 +9,7 @@
 
 #include "base/memory/weak_ptr.h"
 #include "base/threading/non_thread_safe.h"
+#include "content/common/gpu/client/command_buffer_proxy_impl.h"
 #include "ipc/ipc_listener.h"
 #include "media/video/video_decode_accelerator.h"
 
@@ -20,12 +21,14 @@
 class GpuVideoDecodeAcceleratorHost
     : public IPC::Listener,
       public media::VideoDecodeAccelerator,
+      public CommandBufferProxyImpl::DeletionObserver,
       public base::NonThreadSafe {
  public:
   // |channel| is used to send IPC messages to GPU process.
   GpuVideoDecodeAcceleratorHost(GpuChannelHost* channel,
                                 int32 decoder_route_id,
-                                media::VideoDecodeAccelerator::Client* client);
+                                media::VideoDecodeAccelerator::Client* client,
+                                CommandBufferProxyImpl* impl);
 
   // IPC::Listener implementation.
   virtual void OnChannelError() OVERRIDE;
@@ -41,6 +44,9 @@
   virtual void Reset() OVERRIDE;
   virtual void Destroy() OVERRIDE;
 
+  // CommandBufferProxyImpl::DeletionObserver implemetnation.
+  virtual void OnWillDeleteImpl() OVERRIDE;
+
  private:
   // Only Destroy() should be deleting |this|.
   virtual ~GpuVideoDecodeAcceleratorHost();
@@ -66,6 +72,9 @@
   // Reference to the client that will receive callbacks from the decoder.
   media::VideoDecodeAccelerator::Client* client_;
 
+  // Unowned reference to the CommandBufferProxyImpl that created us.
+  CommandBufferProxyImpl* impl_;
+
   DISALLOW_COPY_AND_ASSIGN(GpuVideoDecodeAcceleratorHost);
 };
 
diff --git a/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.cc b/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.cc
index 8484974..e74a7ee 100644
--- a/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.cc
+++ b/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.cc
@@ -146,7 +146,7 @@
       cached_width_(0),
       cached_height_(0),
       bound_fbo_(0),
-      weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)),
+      weak_ptr_factory_(this),
       initialized_(false),
       parent_(NULL),
       parent_texture_id_(0),
@@ -180,16 +180,6 @@
   Destroy();
 }
 
-void WebGraphicsContext3DCommandBufferImpl::InitializeWithCommandBuffer(
-    CommandBufferProxyImpl* command_buffer,
-    const WebGraphicsContext3D::Attributes& attributes,
-    bool bind_generates_resources) {
-  DCHECK(command_buffer);
-  command_buffer_ = command_buffer;
-  attributes_ = attributes;
-  bind_generates_resources_ = bind_generates_resources;
-}
-
 bool WebGraphicsContext3DCommandBufferImpl::Initialize(
     const WebGraphicsContext3D::Attributes& attributes,
     bool bind_generates_resources,
@@ -230,6 +220,7 @@
                      allowed_extensions ?
                          allowed_extensions : preferred_extensions)) {
     Destroy();
+    initialize_failed_ = true;
     return false;
   }
 
@@ -999,8 +990,8 @@
       program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &max_name_length);
   if (max_name_length < 0)
     return false;
-  scoped_array<GLchar> name(new GLchar[max_name_length]);
-  if (!name.get()) {
+  scoped_ptr<GLchar[]> name(new GLchar[max_name_length]);
+  if (!name) {
     synthesizeGLError(GL_OUT_OF_MEMORY);
     return false;
   }
@@ -1025,8 +1016,8 @@
       program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &max_name_length);
   if (max_name_length < 0)
     return false;
-  scoped_array<GLchar> name(new GLchar[max_name_length]);
-  if (!name.get()) {
+  scoped_ptr<GLchar[]> name(new GLchar[max_name_length]);
+  if (!name) {
     synthesizeGLError(GL_OUT_OF_MEMORY);
     return false;
   }
@@ -1093,8 +1084,8 @@
   gl_->GetProgramiv(program, GL_INFO_LOG_LENGTH, &logLength);
   if (!logLength)
     return WebKit::WebString();
-  scoped_array<GLchar> log(new GLchar[logLength]);
-  if (!log.get())
+  scoped_ptr<GLchar[]> log(new GLchar[logLength]);
+  if (!log)
     return WebKit::WebString();
   GLsizei returnedLogLength = 0;
   gl_->GetProgramInfoLog(
@@ -1116,8 +1107,8 @@
   gl_->GetShaderiv(shader, GL_INFO_LOG_LENGTH, &logLength);
   if (!logLength)
     return WebKit::WebString();
-  scoped_array<GLchar> log(new GLchar[logLength]);
-  if (!log.get())
+  scoped_ptr<GLchar[]> log(new GLchar[logLength]);
+  if (!log)
     return WebKit::WebString();
   GLsizei returnedLogLength = 0;
   gl_->GetShaderInfoLog(
@@ -1137,8 +1128,8 @@
   gl_->GetShaderiv(shader, GL_SHADER_SOURCE_LENGTH, &logLength);
   if (!logLength)
     return WebKit::WebString();
-  scoped_array<GLchar> log(new GLchar[logLength]);
-  if (!log.get())
+  scoped_ptr<GLchar[]> log(new GLchar[logLength]);
+  if (!log)
     return WebKit::WebString();
   GLsizei returnedLogLength = 0;
   gl_->GetShaderSource(
@@ -1158,8 +1149,8 @@
       shader, GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE, &logLength);
   if (!logLength)
     return WebKit::WebString();
-  scoped_array<GLchar> log(new GLchar[logLength]);
-  if (!log.get())
+  scoped_ptr<GLchar[]> log(new GLchar[logLength]);
+  if (!log)
     return WebKit::WebString();
   GLsizei returnedLogLength = 0;
   gl_->GetTranslatedShaderSourceANGLE(
@@ -1441,8 +1432,10 @@
   typedef WebGraphicsContext3DSwapBuffersClient WGC3DSwapClient;
   // This may be called after tear-down of the RenderView.
   if (ShouldUseSwapClient()) {
-    MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
-        &WGC3DSwapClient::OnViewContextSwapBuffersComplete, swap_client_));
+    base::MessageLoop::current()->PostTask(
+        FROM_HERE,
+        base::Bind(&WGC3DSwapClient::OnViewContextSwapBuffersComplete,
+                   swap_client_));
   }
 
   if (swapbuffers_complete_callback_)
@@ -1531,30 +1524,6 @@
 
 // static
 WebGraphicsContext3DCommandBufferImpl*
-WebGraphicsContext3DCommandBufferImpl::CreateViewContext(
-      GpuChannelHostFactory* factory,
-      int32 surface_id,
-      const char* allowed_extensions,
-      const WebGraphicsContext3D::Attributes& attributes,
-      bool bind_generates_resources,
-      const GURL& active_url,
-      CauseForGpuLaunch cause) {
-  WebGraphicsContext3DCommandBufferImpl* context =
-      new WebGraphicsContext3DCommandBufferImpl(
-          surface_id,
-          active_url,
-          factory,
-          base::WeakPtr<WebGraphicsContext3DSwapBuffersClient>());
-  if (!context->Initialize(attributes, bind_generates_resources, cause) ||
-      !context->MaybeInitializeGL(allowed_extensions)) {
-    delete context;
-    return NULL;
-  }
-  return context;
-}
-
-// static
-WebGraphicsContext3DCommandBufferImpl*
 WebGraphicsContext3DCommandBufferImpl::CreateOffscreenContext(
     GpuChannelHostFactory* factory,
     const WebGraphicsContext3D::Attributes& attributes,
@@ -1602,8 +1571,21 @@
 DELEGATE_TO_GL_3(getQueryObjectuivEXT, GetQueryObjectuivEXT,
                  WebGLId, WGC3Denum, WGC3Duint*)
 
-DELEGATE_TO_GL_5(copyTextureCHROMIUM, CopyTextureCHROMIUM,  WGC3Denum,
-                 WebGLId, WebGLId, WGC3Dint, WGC3Denum);
+DELEGATE_TO_GL_6(copyTextureCHROMIUM, CopyTextureCHROMIUM,  WGC3Denum,
+                 WebGLId, WebGLId, WGC3Dint, WGC3Denum, WGC3Denum);
+
+// This copyTextureCHROMIUM(...) has five parameters and delegates the call to
+// CopyTextureCHROMIUM(...) with the sixth parameter set to GL_UNSIGNED_BYTE
+// to bridge the parameter differences.
+// TODO(jun.a.jiang@intel.com): once all clients switch to call
+// the newer copyTextureCHROMIUM(...) with six parameters, this
+// function will be removed.
+void WebGraphicsContext3DCommandBufferImpl::copyTextureCHROMIUM(
+    WGC3Denum target, WebGLId source_id, WebGLId dest_id, WGC3Dint level,
+    WGC3Denum internal_format) {
+  gl_->CopyTextureCHROMIUM(target, source_id, dest_id, level, internal_format,
+                           GL_UNSIGNED_BYTE);
+}
 
 DELEGATE_TO_GL_3(bindUniformLocationCHROMIUM, BindUniformLocationCHROMIUM,
                  WebGLId, WGC3Dint, const WGC3Dchar*)
@@ -1612,6 +1594,22 @@
 
 DELEGATE_TO_GL_1(waitSyncPoint, WaitSyncPointCHROMIUM, GLuint)
 
+static void SignalSyncPointCallback(
+    scoped_ptr<
+      WebKit::WebGraphicsContext3D::WebGraphicsSyncPointCallback> callback) {
+  callback->onSyncPointReached();
+}
+
+void WebGraphicsContext3DCommandBufferImpl::signalSyncPoint(
+    unsigned sync_point,
+    WebGraphicsSyncPointCallback* callback) {
+  // Take ownership of the callback.
+  scoped_ptr<WebGraphicsSyncPointCallback> own_callback(callback);
+  command_buffer_->SignalSyncPoint(
+      sync_point,
+      base::Bind(&SignalSyncPointCallback, base::Passed(&own_callback)));
+}
+
 void WebGraphicsContext3DCommandBufferImpl::genMailboxCHROMIUM(
     WGC3Dbyte* name) {
   std::vector<gpu::Mailbox> names(1);
diff --git a/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h b/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h
index 46d311a..c24a238 100644
--- a/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h
+++ b/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h
@@ -79,11 +79,6 @@
 
   virtual ~WebGraphicsContext3DCommandBufferImpl();
 
-  void InitializeWithCommandBuffer(
-      CommandBufferProxyImpl* command_buffer,
-      const Attributes& attributes,
-      bool bind_generates_resources);
-
   bool Initialize(const Attributes& attributes,
                   bool bind_generates_resources,
                   CauseForGpuLaunch cause);
@@ -106,28 +101,6 @@
   // problem communicating with the GPU process.
   bool IsCommandBufferContextLost();
 
-  // Create a WebGraphicsContext3DCommandBufferImpl that renders directly to a
-  // view. The view and the associated window must not be destroyed until
-  // the returned ContentGLContext has been destroyed, otherwise the GPU process
-  // might attempt to render to an invalid window handle.
-  //
-  // NOTE: on Mac OS X, this entry point is only used to set up the
-  // accelerated compositor's output. On this platform, we actually pass
-  // a gfx::PluginWindowHandle in place of the gfx::NativeViewId,
-  // because the facility to allocate a fake PluginWindowHandle is
-  // already in place. We could add more entry points and messages to
-  // allocate both fake PluginWindowHandles and NativeViewIds and map
-  // from fake NativeViewIds to PluginWindowHandles, but this seems like
-  // unnecessary complexity at the moment.
-  static WebGraphicsContext3DCommandBufferImpl* CreateViewContext(
-      GpuChannelHostFactory* factory,
-      int32 surface_id,
-      const char* allowed_extensions,
-      const WebGraphicsContext3D::Attributes& attributes,
-      bool bind_generates_resources,
-      const GURL& active_url,
-      CauseForGpuLaunch cause);
-
   // Create & initialize a WebGraphicsContext3DCommandBufferImpl.  Return NULL
   // on any failure.
   static WebGraphicsContext3DCommandBufferImpl* CreateOffscreenContext(
@@ -151,7 +124,9 @@
   virtual bool setParentContext(WebGraphicsContext3D* parent_context);
 
   virtual unsigned int insertSyncPoint();
-  virtual void waitSyncPoint(unsigned int);
+  virtual void waitSyncPoint(unsigned int sync_point);
+  virtual void signalSyncPoint(unsigned sync_point,
+                               WebGraphicsSyncPointCallback* callback);
 
   virtual void reshape(int width, int height);
 
@@ -574,6 +549,11 @@
                                    WebGLId dest_id, WGC3Dint level,
                                    WGC3Denum internal_format);
 
+  virtual void copyTextureCHROMIUM(WGC3Denum target, WebGLId source_id,
+                                   WebGLId dest_id, WGC3Dint level,
+                                   WGC3Denum internal_format,
+                                   WGC3Denum dest_type);
+
   virtual void bindUniformLocationCHROMIUM(WebGLId program, WGC3Dint location,
                                            const WGC3Dchar* uniform);
 
diff --git a/content/common/gpu/gpu_channel.cc b/content/common/gpu/gpu_channel.cc
index b7231b4..d116d84 100644
--- a/content/common/gpu/gpu_channel.cc
+++ b/content/common/gpu/gpu_channel.cc
@@ -126,7 +126,7 @@
     // All other messages get processed by the GpuChannel.
     if (!handled) {
       messages_forwarded_to_channel_++;
-      if (preempting_flag_.get())
+      if (preempting_flag_)
         pending_messages_.push(PendingMessage(messages_forwarded_to_channel_));
       UpdatePreemptionState();
     }
@@ -448,7 +448,7 @@
       handle_messages_scheduled_(false),
       processed_get_state_fast_(false),
       currently_processing_message_(NULL),
-      weak_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)),
+      weak_factory_(this),
       num_stubs_descheduled_(0) {
   DCHECK(gpu_channel_manager);
   DCHECK(client_id);
@@ -497,7 +497,7 @@
 
 #if defined(OS_POSIX)
 int GpuChannel::TakeRendererFileDescriptor() {
-  if (!channel_.get()) {
+  if (!channel_) {
     NOTREACHED();
     return -1;
   }
@@ -561,7 +561,7 @@
              << " with type " << message->type();
   }
 
-  if (!channel_.get()) {
+  if (!channel_) {
     delete message;
     return false;
   }
@@ -585,7 +585,7 @@
   // defer newly received messages until the ones in the queue have all been
   // handled by HandleMessage. HandleMessage is invoked as a
   // task to prevent reentrancy.
-  MessageLoop::current()->PostTask(
+  base::MessageLoop::current()->PostTask(
       FROM_HERE,
       base::Bind(&GpuChannel::HandleMessage, weak_factory_.GetWeakPtr()));
   handle_messages_scheduled_ = true;
@@ -603,7 +603,7 @@
   bool a_stub_is_descheduled = num_stubs_descheduled_ > 0;
 
   if (a_stub_is_descheduled != a_stub_was_descheduled) {
-    if (preempting_flag_.get()) {
+    if (preempting_flag_) {
       io_message_loop_->PostTask(
           FROM_HERE,
           base::Bind(&GpuChannelMessageFilter::UpdateStubSchedulingState,
@@ -628,6 +628,14 @@
 
   GpuCommandBufferStub* share_group = stubs_.Lookup(init_params.share_group_id);
 
+  // Virtualize compositor contexts on OS X to prevent performance regressions
+  // when enabling FCM.
+  // http://crbug.com/180463
+  bool use_virtualized_gl_context = false;
+#if defined(OS_MACOSX)
+  use_virtualized_gl_context = true;
+#endif
+
   *route_id = GenerateRouteID();
   scoped_ptr<GpuCommandBufferStub> stub(new GpuCommandBufferStub(
       this,
@@ -640,12 +648,13 @@
       init_params.allowed_extensions,
       init_params.attribs,
       init_params.gpu_preference,
+      use_virtualized_gl_context,
       *route_id,
       surface_id,
       watchdog_,
       software_,
       init_params.active_url));
-  if (preempted_flag_.get())
+  if (preempted_flag_)
     stub->SetPreemptByFlag(preempted_flag_);
   router_.AddRoute(*route_id, stub.get());
   stubs_.AddWithID(stub.release(), *route_id);
@@ -694,7 +703,7 @@
 }
 
 void GpuChannel::DestroySoon() {
-  MessageLoop::current()->PostTask(
+  base::MessageLoop::current()->PostTask(
       FROM_HERE, base::Bind(&GpuChannel::OnDestroy, this));
 }
 
@@ -712,7 +721,7 @@
 }
 
 gpu::PreemptionFlag* GpuChannel::GetPreemptionFlag() {
-  if (!preempting_flag_.get()) {
+  if (!preempting_flag_) {
     preempting_flag_ = new gpu::PreemptionFlag;
     io_message_loop_->PostTask(
         FROM_HERE, base::Bind(
@@ -733,7 +742,7 @@
 }
 
 GpuChannel::~GpuChannel() {
-  if (preempting_flag_.get())
+  if (preempting_flag_)
     preempting_flag_->Reset();
 }
 
@@ -857,11 +866,13 @@
       init_params.allowed_extensions,
       init_params.attribs,
       init_params.gpu_preference,
+      false,
       *route_id,
-      0, watchdog_,
+      0,
+      watchdog_,
       software_,
       init_params.active_url));
-  if (preempted_flag_.get())
+  if (preempted_flag_)
     stub->SetPreemptByFlag(preempted_flag_);
   router_.AddRoute(*route_id, stub.get());
   stubs_.AddWithID(stub.release(), *route_id);
@@ -873,18 +884,17 @@
   TRACE_EVENT1("gpu", "GpuChannel::OnDestroyCommandBuffer",
                "route_id", route_id);
 
-  if (router_.ResolveRoute(route_id)) {
-    GpuCommandBufferStub* stub = stubs_.Lookup(route_id);
-    bool need_reschedule = (stub && !stub->IsScheduled());
-    router_.RemoveRoute(route_id);
-    stubs_.Remove(route_id);
-    // In case the renderer is currently blocked waiting for a sync reply from
-    // the stub, we need to make sure to reschedule the GpuChannel here.
-    if (need_reschedule) {
-      // This stub won't get a chance to reschedule, so update the count
-      // now.
-      StubSchedulingChanged(true);
-    }
+  GpuCommandBufferStub* stub = stubs_.Lookup(route_id);
+  if (!stub)
+    return;
+  bool need_reschedule = (stub && !stub->IsScheduled());
+  router_.RemoveRoute(route_id);
+  stubs_.Remove(route_id);
+  // In case the renderer is currently blocked waiting for a sync reply from the
+  // stub, we need to make sure to reschedule the GpuChannel here.
+  if (need_reschedule) {
+    // This stub won't get a chance to reschedule, so update the count now.
+    StubSchedulingChanged(true);
   }
 }
 
@@ -931,7 +941,7 @@
 
 void GpuChannel::MessageProcessed() {
   messages_processed_++;
-  if (preempting_flag_.get()) {
+  if (preempting_flag_) {
     io_message_loop_->PostTask(
         FROM_HERE,
         base::Bind(&GpuChannelMessageFilter::MessageProcessed,
diff --git a/content/common/gpu/gpu_channel_manager.cc b/content/common/gpu/gpu_channel_manager.cc
index fc48010..d695ff5 100644
--- a/content/common/gpu/gpu_channel_manager.cc
+++ b/content/common/gpu/gpu_channel_manager.cc
@@ -33,13 +33,12 @@
                                      GpuWatchdog* watchdog,
                                      base::MessageLoopProxy* io_message_loop,
                                      base::WaitableEvent* shutdown_event)
-    : ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)),
+    : weak_factory_(this),
       io_message_loop_(io_message_loop),
       shutdown_event_(shutdown_event),
       gpu_child_thread_(gpu_child_thread),
-      ALLOW_THIS_IN_INITIALIZER_LIST(gpu_memory_manager_(
-          this,
-          GpuMemoryManager::kDefaultMaxSurfacesWithFrontbufferSoftLimit)),
+      gpu_memory_manager_(
+          this, GpuMemoryManager::kDefaultMaxSurfacesWithFrontbufferSoftLimit),
       watchdog_(watchdog),
       sync_point_manager_(new SyncPointManager),
       program_cache_(NULL) {
@@ -50,7 +49,7 @@
 
 GpuChannelManager::~GpuChannelManager() {
   gpu_channels_.clear();
-  if (default_offscreen_surface_.get()) {
+  if (default_offscreen_surface_) {
     default_offscreen_surface_->Destroy();
     default_offscreen_surface_ = NULL;
   }
@@ -279,7 +278,7 @@
 }
 
 void GpuChannelManager::LoseAllContexts() {
-  MessageLoop::current()->PostTask(
+  base::MessageLoop::current()->PostTask(
       FROM_HERE,
       base::Bind(&GpuChannelManager::OnLoseAllContexts,
                  weak_factory_.GetWeakPtr()));
@@ -290,7 +289,7 @@
 }
 
 gfx::GLSurface* GpuChannelManager::GetDefaultOffscreenSurface() {
-  if (!default_offscreen_surface_.get()) {
+  if (!default_offscreen_surface_) {
     default_offscreen_surface_ = gfx::GLSurface::CreateOffscreenGLSurface(
         false, gfx::Size(1, 1));
   }
diff --git a/content/common/gpu/gpu_command_buffer_stub.cc b/content/common/gpu/gpu_command_buffer_stub.cc
index 04e55bc..4934df5 100644
--- a/content/common/gpu/gpu_command_buffer_stub.cc
+++ b/content/common/gpu/gpu_command_buffer_stub.cc
@@ -25,6 +25,7 @@
 #include "gpu/command_buffer/common/constants.h"
 #include "gpu/command_buffer/common/gles2_cmd_utils.h"
 #include "gpu/command_buffer/service/gl_context_virtual.h"
+#include "gpu/command_buffer/service/logger.h"
 #include "gpu/command_buffer/service/memory_tracking.h"
 #include "ui/gl/gl_bindings.h"
 #include "ui/gl/gl_switches.h"
@@ -107,6 +108,7 @@
     const std::string& allowed_extensions,
     const std::vector<int32>& attribs,
     gfx::GpuPreference gpu_preference,
+    bool use_virtualized_gl_context,
     int32 route_id,
     int32 surface_id,
     GpuWatchdog* watchdog,
@@ -119,6 +121,7 @@
       allowed_extensions_(allowed_extensions),
       requested_attribs_(attribs),
       gpu_preference_(gpu_preference),
+      use_virtualized_gl_context_(use_virtualized_gl_context),
       route_id_(route_id),
       surface_id_(surface_id),
       software_(software),
@@ -165,7 +168,8 @@
   // Echo, RetireSyncPoint, or WaitSyncPoint).
   if (decoder_.get() &&
       message.type() != GpuCommandBufferMsg_Echo::ID &&
-      message.type() != GpuCommandBufferMsg_RetireSyncPoint::ID) {
+      message.type() != GpuCommandBufferMsg_RetireSyncPoint::ID &&
+      message.type() != GpuCommandBufferMsg_SetLatencyInfo::ID) {
     if (!MakeCurrent())
       return false;
   }
@@ -185,6 +189,7 @@
     IPC_MESSAGE_HANDLER_DELAY_REPLY(GpuCommandBufferMsg_GetStateFast,
                                     OnGetStateFast);
     IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_AsyncFlush, OnAsyncFlush);
+    IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_SetLatencyInfo, OnSetLatencyInfo);
     IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_Rescheduled, OnRescheduled);
     IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_RegisterTransferBuffer,
                         OnRegisterTransferBuffer);
@@ -194,8 +199,6 @@
                                     OnGetTransferBuffer);
     IPC_MESSAGE_HANDLER_DELAY_REPLY(GpuCommandBufferMsg_CreateVideoDecoder,
                                     OnCreateVideoDecoder)
-    IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_DestroyVideoDecoder,
-                        OnDestroyVideoDecoder)
     IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_SetSurfaceVisible,
                         OnSetSurfaceVisible)
     IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_DiscardBackbuffer,
@@ -240,7 +243,7 @@
   if (decoder_.get() && !MakeCurrent())
     return;
 
-  if (scheduler_.get()) {
+  if (scheduler_) {
     bool fences_complete = scheduler_->PollUnscheduleFences();
     // Perform idle work if all fences are complete.
     if (fences_complete) {
@@ -271,7 +274,7 @@
 }
 
 bool GpuCommandBufferStub::HasUnprocessedCommands() {
-  if (command_buffer_.get()) {
+  if (command_buffer_) {
     gpu::CommandBuffer::State state = command_buffer_->GetLastState();
     return state.put_offset != state.get_offset &&
         !gpu::error::IsError(state.error);
@@ -308,10 +311,9 @@
     delay = 0;
   }
 
-  MessageLoop::current()->PostDelayedTask(
+  base::MessageLoop::current()->PostDelayedTask(
       FROM_HERE,
-      base::Bind(&GpuCommandBufferStub::PollWork,
-                 AsWeakPtr()),
+      base::Bind(&GpuCommandBufferStub::PollWork, AsWeakPtr()),
       base::TimeDelta::FromMilliseconds(delay));
 }
 
@@ -343,7 +345,7 @@
   while (!sync_points_.empty())
     OnRetireSyncPoint(sync_points_.front());
 
-  if (decoder_.get())
+  if (decoder_)
     decoder_->set_engine(NULL);
 
   // The scheduler has raw references to the decoder and the command buffer so
@@ -351,14 +353,14 @@
   scheduler_.reset();
 
   bool have_context = false;
-  if (decoder_.get())
+  if (decoder_)
     have_context = decoder_->MakeCurrent();
   FOR_EACH_OBSERVER(DestructionObserver,
                     destruction_observers_,
-                    OnWillDestroyStub(this));
+                    OnWillDestroyStub());
 
   scoped_refptr<gfx::GLContext> context;
-  if (decoder_.get()) {
+  if (decoder_) {
     context = decoder_->GetGLContext();
     decoder_->Destroy(have_context);
     decoder_.reset();
@@ -405,7 +407,7 @@
   scheduler_.reset(new gpu::GpuScheduler(command_buffer_.get(),
                                          decoder_.get(),
                                          decoder_.get()));
-  if (preemption_flag_.get())
+  if (preemption_flag_)
     scheduler_->SetPreemptByFlag(preemption_flag_);
 
   decoder_->set_engine(scheduler_.get());
@@ -428,18 +430,16 @@
     surface_ = manager->GetDefaultOffscreenSurface();
   }
 
-  if (!surface_.get()) {
-    // Ensure the decoder is not destroyed if it is not initialized.
-    decoder_.reset();
-
+  if (!surface_) {
     DLOG(ERROR) << "Failed to create surface.\n";
     OnInitializeFailed(reply_message);
     return;
   }
 
   scoped_refptr<gfx::GLContext> context;
-  if (CommandLine::ForCurrentProcess()->HasSwitch(
-      switches::kEnableVirtualGLContexts) && channel_->share_group()) {
+  if ((CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kEnableVirtualGLContexts) || use_virtualized_gl_context_) &&
+      channel_->share_group()) {
     context = channel_->share_group()->GetSharedContext();
     if (!context) {
       context = gfx::GLContext::CreateGLContext(
@@ -460,9 +460,6 @@
       // with a config that is compatible with onscreen and offscreen surfaces.
       context = NULL;
 
-      // Ensure the decoder is not destroyed if it is not initialized.
-      decoder_.reset();
-
       DLOG(ERROR) << "Failed to initialize virtual GL context.";
       OnInitializeFailed(reply_message);
       return;
@@ -477,17 +474,12 @@
         gpu_preference_);
   }
   if (!context) {
-    // Ensure the decoder is not destroyed if it is not initialized.
-    decoder_.reset();
-
     DLOG(ERROR) << "Failed to create context.\n";
     OnInitializeFailed(reply_message);
     return;
   }
 
-  if (!context->MakeCurrent(surface_.get())) {
-    // Ensure the decoder is not destroyed if it is not initialized.
-    decoder_.reset();
+  if (!context->MakeCurrent(surface_)) {
     LOG(ERROR) << "Failed to make context current.";
     OnInitializeFailed(reply_message);
     return;
@@ -519,7 +511,7 @@
     decoder_->set_log_commands(true);
   }
 
-  decoder_->SetMsgCallback(
+  decoder_->GetLogger()->SetMsgCallback(
       base::Bind(&GpuCommandBufferStub::SendConsoleMessage,
                  base::Unretained(this)));
   decoder_->SetShaderCacheCallback(
@@ -573,10 +565,21 @@
   }
 }
 
+void GpuCommandBufferStub::OnSetLatencyInfo(
+    const cc::LatencyInfo& latency_info) {
+  if (!latency_info_callback_.is_null())
+    latency_info_callback_.Run(latency_info);
+}
+
+void GpuCommandBufferStub::SetLatencyInfoCallback(
+    const LatencyInfoCallback& callback) {
+  latency_info_callback_ = callback;
+}
+
 void GpuCommandBufferStub::OnSetGetBuffer(int32 shm_id,
                                           IPC::Message* reply_message) {
   TRACE_EVENT0("gpu", "GpuCommandBufferStub::OnSetGetBuffer");
-  if (command_buffer_.get())
+  if (command_buffer_)
     command_buffer_->SetGetBuffer(shm_id);
   Send(reply_message);
 }
@@ -591,7 +594,7 @@
   }
 
   bool result = true;
-  if (scheduler_.get()) {
+  if (scheduler_) {
     gpu::gles2::GLES2Decoder* parent_decoder =
         parent_stub ? parent_stub->decoder_.get() : NULL;
     result = decoder_->SetParent(parent_decoder, parent_texture_id);
@@ -609,7 +612,7 @@
 
 void GpuCommandBufferStub::OnGetState(IPC::Message* reply_message) {
   TRACE_EVENT0("gpu", "GpuCommandBufferStub::OnGetState");
-  if (command_buffer_.get()) {
+  if (command_buffer_) {
     gpu::CommandBuffer::State state = command_buffer_->GetState();
     if (state.error == gpu::error::kLostContext &&
         gfx::GLContext::LosesAllContextsOnContextLost())
@@ -685,14 +688,14 @@
   TRACE_EVENT0("gpu", "GpuCommandBufferStub::OnRegisterTransferBuffer");
   base::SharedMemory shared_memory(transfer_buffer, false);
 
-  if (command_buffer_.get())
+  if (command_buffer_)
     command_buffer_->RegisterTransferBuffer(id, &shared_memory, size);
 }
 
 void GpuCommandBufferStub::OnDestroyTransferBuffer(int32 id) {
   TRACE_EVENT0("gpu", "GpuCommandBufferStub::OnDestroyTransferBuffer");
 
-  if (command_buffer_.get())
+  if (command_buffer_)
     command_buffer_->DestroyTransferBuffer(id);
 }
 
@@ -700,7 +703,7 @@
     int32 id,
     IPC::Message* reply_message) {
   TRACE_EVENT0("gpu", "GpuCommandBufferStub::OnGetTransferBuffer");
-  if (command_buffer_.get()) {
+  if (command_buffer_) {
     base::SharedMemoryHandle transfer_buffer = base::SharedMemoryHandle();
     uint32 size = 0;
 
@@ -755,18 +758,14 @@
   int decoder_route_id = channel_->GenerateRouteID();
   GpuVideoDecodeAccelerator* decoder =
       new GpuVideoDecodeAccelerator(decoder_route_id, this);
-  video_decoders_.AddWithID(decoder, decoder_route_id);
   decoder->Initialize(profile, reply_message);
-}
-
-void GpuCommandBufferStub::OnDestroyVideoDecoder(int decoder_route_id) {
-  TRACE_EVENT0("gpu", "GpuCommandBufferStub::OnDestroyVideoDecoder");
-  video_decoders_.Remove(decoder_route_id);
+  // decoder is registered as a DestructionObserver of this stub and will
+  // self-delete during destruction of this stub.
 }
 
 void GpuCommandBufferStub::OnSetSurfaceVisible(bool visible) {
   TRACE_EVENT0("gpu", "GpuCommandBufferStub::OnSetSurfaceVisible");
-  if (memory_manager_client_state_.get())
+  if (memory_manager_client_state_)
     memory_manager_client_state_->SetVisible(visible);
 }
 
@@ -849,7 +848,7 @@
   TRACE_EVENT0(
       "gpu",
       "GpuCommandBufferStub::OnReceivedClientManagedMemoryStats");
-  if (memory_manager_client_state_.get())
+  if (memory_manager_client_state_)
     memory_manager_client_state_->SetManagedMemoryStats(stats);
 }
 
@@ -859,7 +858,7 @@
       "gpu",
       "GpuCommandBufferStub::OnSetClientHasMemoryAllocationChangedCallback");
   if (has_callback) {
-    if (!memory_manager_client_state_.get()) {
+    if (!memory_manager_client_state_) {
       memory_manager_client_state_.reset(GetMemoryManager()->CreateClientState(
           this, surface_id_ != 0, true));
     }
@@ -898,7 +897,7 @@
 void GpuCommandBufferStub::SetPreemptByFlag(
     scoped_refptr<gpu::PreemptionFlag> flag) {
   preemption_flag_ = flag;
-  if (scheduler_.get())
+  if (scheduler_)
     scheduler_->SetPreemptByFlag(preemption_flag_);
 }
 
diff --git a/content/common/gpu/gpu_command_buffer_stub.h b/content/common/gpu/gpu_command_buffer_stub.h
index 512012d..c7f8195 100644
--- a/content/common/gpu/gpu_command_buffer_stub.h
+++ b/content/common/gpu/gpu_command_buffer_stub.h
@@ -9,9 +9,10 @@
 #include <string>
 #include <vector>
 
-#include "base/id_map.h"
+#include "base/memory/scoped_vector.h"
 #include "base/memory/weak_ptr.h"
 #include "base/observer_list.h"
+#include "cc/debug/latency_info.h"
 #include "content/common/content_export.h"
 #include "content/common/gpu/gpu_memory_allocation.h"
 #include "content/common/gpu/gpu_memory_manager.h"
@@ -52,12 +53,15 @@
   class DestructionObserver {
    public:
     // Called in Destroy(), before the context/surface are released.
-    virtual void OnWillDestroyStub(GpuCommandBufferStub* stub) = 0;
+    virtual void OnWillDestroyStub() = 0;
 
    protected:
     virtual ~DestructionObserver() {}
   };
 
+  typedef base::Callback<void(const cc::LatencyInfo&)>
+      LatencyInfoCallback;
+
   GpuCommandBufferStub(
       GpuChannel* channel,
       GpuCommandBufferStub* share_group,
@@ -69,6 +73,7 @@
       const std::string& allowed_extensions,
       const std::vector<int32>& attribs,
       gfx::GpuPreference gpu_preference,
+      bool use_virtualized_gl_context,
       int32 route_id,
       int32 surface_id,
       GpuWatchdog* watchdog,
@@ -130,6 +135,8 @@
 
   void SetPreemptByFlag(scoped_refptr<gpu::PreemptionFlag> flag);
 
+  void SetLatencyInfoCallback(const LatencyInfoCallback& callback);
+
  private:
   GpuMemoryManager* GetMemoryManager();
   bool MakeCurrent();
@@ -159,7 +166,6 @@
   void OnCreateVideoDecoder(
       media::VideoCodecProfile profile,
       IPC::Message* reply_message);
-  void OnDestroyVideoDecoder(int32 decoder_route_id);
 
   void OnSetSurfaceVisible(bool visible);
 
@@ -177,6 +183,7 @@
 
   void OnCommandProcessed();
   void OnParseError();
+  void OnSetLatencyInfo(const cc::LatencyInfo& latency_info);
 
   void ReportState();
 
@@ -205,6 +212,7 @@
   std::string allowed_extensions_;
   std::vector<int32> requested_attribs_;
   gfx::GpuPreference gpu_preference_;
+  bool use_virtualized_gl_context_;
   int32 route_id_;
   int32 surface_id_;
   bool software_;
@@ -228,10 +236,6 @@
 
   GpuWatchdog* watchdog_;
 
-  // Zero or more video decoders owned by this stub, keyed by their
-  // decoder_route_id.
-  IDMap<GpuVideoDecodeAccelerator, IDMapOwnPointer> video_decoders_;
-
   ObserverList<DestructionObserver> destruction_observers_;
 
   // A queue of sync points associated with this stub.
@@ -244,6 +248,8 @@
 
   scoped_refptr<gpu::PreemptionFlag> preemption_flag_;
 
+  LatencyInfoCallback latency_info_callback_;
+
   GURL active_url_;
   size_t active_url_hash_;
 
diff --git a/content/common/gpu/gpu_memory_manager.cc b/content/common/gpu/gpu_memory_manager.cc
index 9a1402c..4794b9f 100644
--- a/content/common/gpu/gpu_memory_manager.cc
+++ b/content/common/gpu/gpu_memory_manager.cc
@@ -75,6 +75,14 @@
   bytes_minimum_per_client_ = 64 * 1024 * 1024;
 #endif
 
+  // On Android, always discard everything that is nonvisible.
+  // On Mac, use as little memory as possible to avoid stability issues.
+#if defined(OS_ANDROID) || defined(OS_MACOSX)
+  allow_nonvisible_memory_ = false;
+#else
+  allow_nonvisible_memory_ = true;
+#endif
+
   if (command_line->HasSwitch(switches::kForceGpuMemAvailableMb)) {
     base::StringToUint64(
         command_line->GetSwitchValueASCII(switches::kForceGpuMemAvailableMb),
@@ -207,9 +215,8 @@
   if (manage_immediate_scheduled_)
     return;
   if (schedule_manage_time == kScheduleManageNow) {
-    MessageLoop::current()->PostTask(
-      FROM_HERE,
-      base::Bind(&GpuMemoryManager::Manage, AsWeakPtr()));
+    base::MessageLoop::current()->PostTask(
+        FROM_HERE, base::Bind(&GpuMemoryManager::Manage, AsWeakPtr()));
     manage_immediate_scheduled_ = true;
     if (!delayed_manage_callback_.IsCancelled())
       delayed_manage_callback_.Cancel();
@@ -218,10 +225,10 @@
       return;
     delayed_manage_callback_.Reset(base::Bind(&GpuMemoryManager::Manage,
                                               AsWeakPtr()));
-    MessageLoop::current()->PostDelayedTask(
-      FROM_HERE,
-      delayed_manage_callback_.callback(),
-      base::TimeDelta::FromMilliseconds(kDelayedScheduleManageTimeoutMs));
+    base::MessageLoop::current()->PostDelayedTask(
+        FROM_HERE,
+        delayed_manage_callback_.callback(),
+        base::TimeDelta::FromMilliseconds(kDelayedScheduleManageTimeoutMs));
   }
 }
 
@@ -634,10 +641,9 @@
         bytes_available_total - bytes_allocated_visible);
   }
 
-  // On Android, always discard everything that is nonvisible.
-#if defined(OS_ANDROID)
-  bytes_available_nonvisible = 0;
-#endif
+  // Clamp the amount of memory available to non-visible clients.
+  if (!allow_nonvisible_memory_)
+    bytes_available_nonvisible = 0;
 
   // Determine which now-visible clients should keep their contents when
   // they are made nonvisible.
@@ -765,6 +771,9 @@
 
     allocation.renderer_allocation.bytes_limit_when_visible =
         client_state->bytes_allocation_when_visible_;
+    // Use a more conservative memory allocation policy on Mac because the
+    // platform is unstable when under memory pressure.
+    // http://crbug.com/141377
     allocation.renderer_allocation.priority_cutoff_when_visible =
 #if defined(OS_MACOSX)
         GpuMemoryAllocationForRenderer::kPriorityCutoffAllowNiceToHave;
diff --git a/content/common/gpu/gpu_memory_manager.h b/content/common/gpu/gpu_memory_manager.h
index 2315c84..57c2c16 100644
--- a/content/common/gpu/gpu_memory_manager.h
+++ b/content/common/gpu/gpu_memory_manager.h
@@ -230,6 +230,9 @@
   uint64 bytes_available_gpu_memory_;
   bool bytes_available_gpu_memory_overridden_;
 
+  // Whether or not clients can be allocated memory when nonvisible.
+  bool allow_nonvisible_memory_;
+
   // The minimum and default allocations for a single client.
   uint64 bytes_minimum_per_client_;
   uint64 bytes_default_per_client_;
diff --git a/content/common/gpu/gpu_memory_manager_unittest.cc b/content/common/gpu/gpu_memory_manager_unittest.cc
index 9cbb4b3..d877ef6 100644
--- a/content/common/gpu/gpu_memory_manager_unittest.cc
+++ b/content/common/gpu/gpu_memory_manager_unittest.cc
@@ -716,9 +716,8 @@
   memmgr_.TestingSetMinimumClientAllocation(8);
 
   uint64 bytes_when_not_visible_expected = 6u;
-#if defined (OS_ANDROID)
-  bytes_when_not_visible_expected = 0;
-#endif
+  if (!memmgr_.allow_nonvisible_memory_)
+    bytes_when_not_visible_expected = 0;
 
   FakeClient stub1(&memmgr_, GenerateUniqueSurfaceId(), true);
   FakeClient stub2(&memmgr_, GenerateUniqueSurfaceId(), true);
@@ -772,9 +771,8 @@
   memmgr_.TestingSetMinimumClientAllocation(8);
 
   uint64 bytes_when_not_visible_expected = 10ul;
-#if defined (OS_ANDROID)
-  bytes_when_not_visible_expected = 0;
-#endif
+  if (!memmgr_.allow_nonvisible_memory_)
+    bytes_when_not_visible_expected = 0;
 
   FakeClient stub1(&memmgr_, GenerateUniqueSurfaceId(), true);
   FakeClient stub2(&memmgr_, GenerateUniqueSurfaceId(), true);
diff --git a/content/common/gpu/gpu_messages.h b/content/common/gpu/gpu_messages.h
index de5d1e2..f8b8549 100644
--- a/content/common/gpu/gpu_messages.h
+++ b/content/common/gpu/gpu_messages.h
@@ -9,6 +9,7 @@
 #include <vector>
 
 #include "base/shared_memory.h"
+#include "cc/debug/latency_info.h"
 #include "content/common/content_export.h"
 #include "content/common/gpu/gpu_memory_allocation.h"
 #include "content/common/gpu/gpu_memory_uma_stats.h"
@@ -50,6 +51,7 @@
   IPC_STRUCT_MEMBER(int32, route_id)
   IPC_STRUCT_MEMBER(std::string, mailbox_name)
   IPC_STRUCT_MEMBER(gfx::Size, size)
+  IPC_STRUCT_MEMBER(cc::LatencyInfo, latency_info)
 IPC_STRUCT_END()
 #undef IPC_MESSAGE_EXPORT
 #define IPC_MESSAGE_EXPORT
@@ -64,6 +66,7 @@
   IPC_STRUCT_MEMBER(int, height)
   IPC_STRUCT_MEMBER(std::string, mailbox_name)
   IPC_STRUCT_MEMBER(gfx::Size, surface_size)
+  IPC_STRUCT_MEMBER(cc::LatencyInfo, latency_info)
 IPC_STRUCT_END()
 
 IPC_STRUCT_BEGIN(GpuHostMsg_AcceleratedSurfaceRelease_Params)
@@ -361,6 +364,11 @@
                      int32 /* route_id */,
                      gfx::Size /* size */)
 
+// Tells the browser that a frame with the specific latency info was drawn to
+// the screen
+IPC_MESSAGE_CONTROL1(GpuHostMsg_FrameDrawn,
+                     cc::LatencyInfo /* latency_info */)
+
 // Same as above with a rect of the part of the surface that changed.
 IPC_MESSAGE_CONTROL1(GpuHostMsg_AcceleratedSurfaceBuffersSwapped,
                      GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params)
@@ -502,6 +510,11 @@
                     int32 /* put_offset */,
                     uint32 /* flush_count */)
 
+// Sends information about the latency of the current frame to the GPU
+// process.
+IPC_MESSAGE_ROUTED1(GpuCommandBufferMsg_SetLatencyInfo,
+                    cc::LatencyInfo /* latency_info */)
+
 // Asynchronously process any commands known to the GPU process. This is only
 // used in the event that a channel is unscheduled and needs to be flushed
 // again to process any commands issued subsequent to unscheduling. The GPU
@@ -531,14 +544,12 @@
                            uint32 /* size */)
 
 // Create and initialize a hardware video decoder, returning its new route_id.
+// Created decoders should be freed with AcceleratedVideoDecoderMsg_Destroy when
+// no longer needed.
 IPC_SYNC_MESSAGE_ROUTED1_1(GpuCommandBufferMsg_CreateVideoDecoder,
                            media::VideoCodecProfile /* profile */,
                            int /* route_id */)
 
-// Release all resources held by the named hardware video decoder.
-IPC_SYNC_MESSAGE_ROUTED1_0(GpuCommandBufferMsg_DestroyVideoDecoder,
-                           int /* route_id */)
-
 // Tells the proxy that there was an error and the command buffer had to be
 // destroyed for some reason.
 IPC_MESSAGE_ROUTED1(GpuCommandBufferMsg_Destroyed,
@@ -625,7 +636,7 @@
 IPC_MESSAGE_ROUTED0(AcceleratedVideoDecoderMsg_Reset)
 
 // Send destroy request to the decoder.
-IPC_SYNC_MESSAGE_ROUTED0_0(AcceleratedVideoDecoderMsg_Destroy)
+IPC_MESSAGE_ROUTED0(AcceleratedVideoDecoderMsg_Destroy)
 
 //------------------------------------------------------------------------------
 // Accelerated Video Decoder Host Messages
diff --git a/content/common/gpu/image_transport_surface.cc b/content/common/gpu/image_transport_surface.cc
index 445f184..f8f0742 100644
--- a/content/common/gpu/image_transport_surface.cc
+++ b/content/common/gpu/image_transport_surface.cc
@@ -12,6 +12,7 @@
 #include "content/common/gpu/gpu_channel_manager.h"
 #include "content/common/gpu/gpu_command_buffer_stub.h"
 #include "content/common/gpu/gpu_messages.h"
+#include "content/common/gpu/texture_image_transport_surface.h"
 #include "gpu/command_buffer/service/gpu_scheduler.h"
 #include "ui/gl/gl_implementation.h"
 #include "ui/gl/gl_switches.h"
@@ -23,6 +24,21 @@
 
 ImageTransportSurface::~ImageTransportSurface() {}
 
+scoped_refptr<gfx::GLSurface> ImageTransportSurface::CreateSurface(
+    GpuChannelManager* manager,
+    GpuCommandBufferStub* stub,
+    const gfx::GLSurfaceHandle& handle) {
+  scoped_refptr<gfx::GLSurface> surface;
+  if (handle.transport_type == gfx::TEXTURE_TRANSPORT)
+    surface = new TextureImageTransportSurface(manager, stub, handle);
+  else
+    surface = CreateNativeSurface(manager, stub, handle);
+
+  if (!surface || !surface->Initialize())
+    return NULL;
+  return surface;
+}
+
 ImageTransportHelper::ImageTransportHelper(ImageTransportSurface* surface,
                                            GpuChannelManager* manager,
                                            GpuCommandBufferStub* stub,
@@ -36,6 +52,10 @@
 }
 
 ImageTransportHelper::~ImageTransportHelper() {
+  if (stub_) {
+    stub_->SetLatencyInfoCallback(
+        base::Callback<void(const cc::LatencyInfo&)>());
+  }
   manager_->RemoveRoute(route_id_);
 }
 
@@ -48,6 +68,10 @@
   decoder->SetResizeCallback(
        base::Bind(&ImageTransportHelper::Resize, base::Unretained(this)));
 
+  stub_->SetLatencyInfoCallback(
+      base::Bind(&ImageTransportHelper::SetLatencyInfo,
+                 base::Unretained(this)));
+
   return true;
 }
 
@@ -68,6 +92,7 @@
     GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params) {
   // TRACE_EVENT for gpu tests:
   TRACE_EVENT_INSTANT2("test_gpu", "SwapBuffers",
+                       TRACE_EVENT_SCOPE_THREAD,
                        "GLImpl", static_cast<int>(gfx::GetGLImplementation()),
                        "width", params.size.width());
   params.surface_id = stub_->surface_id();
@@ -102,6 +127,11 @@
                                                       interval));
 }
 
+void ImageTransportHelper::SendLatencyInfo(
+    const cc::LatencyInfo& latency_info) {
+  manager_->Send(new GpuHostMsg_FrameDrawn(latency_info));
+}
+
 void ImageTransportHelper::SetScheduled(bool is_scheduled) {
   gpu::GpuScheduler* scheduler = Scheduler();
   if (!scheduler)
@@ -141,13 +171,13 @@
 }
 
 gpu::GpuScheduler* ImageTransportHelper::Scheduler() {
-  if (!stub_.get())
+  if (!stub_)
     return NULL;
   return stub_->scheduler();
 }
 
 gpu::gles2::GLES2Decoder* ImageTransportHelper::Decoder() {
-  if (!stub_.get())
+  if (!stub_)
     return NULL;
   return stub_->decoder();
 }
@@ -170,6 +200,11 @@
 #endif
 }
 
+void ImageTransportHelper::SetLatencyInfo(
+    const cc::LatencyInfo& latency_info) {
+  surface_->SetLatencyInfo(latency_info);
+}
+
 PassThroughImageTransportSurface::PassThroughImageTransportSurface(
     GpuChannelManager* manager,
     GpuCommandBufferStub* stub,
@@ -206,9 +241,17 @@
   return false;
 }
 
+void PassThroughImageTransportSurface::SetLatencyInfo(
+    const cc::LatencyInfo& latency_info) {
+  latency_info_ = latency_info;
+}
+
 bool PassThroughImageTransportSurface::SwapBuffers() {
-  bool result = gfx::GLSurfaceAdapter::SwapBuffers();
+  // GetVsyncValues before SwapBuffers to work around Mali driver bug:
+  // crbug.com/223558.
   SendVSyncUpdateIfAvailable();
+  bool result = gfx::GLSurfaceAdapter::SwapBuffers();
+  latency_info_.swap_timestamp = base::TimeTicks::HighResNow();
 
   if (transport_) {
     DCHECK(!is_swap_buffers_pending_);
@@ -218,16 +261,20 @@
     // SwapBuffers message.
     GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params;
     params.surface_handle = 0;
+    params.latency_info = latency_info_;
     params.size = surface()->GetSize();
     helper_->SendAcceleratedSurfaceBuffersSwapped(params);
+  } else {
+    helper_->SendLatencyInfo(latency_info_);
   }
   return result;
 }
 
 bool PassThroughImageTransportSurface::PostSubBuffer(
     int x, int y, int width, int height) {
-  bool result = gfx::GLSurfaceAdapter::PostSubBuffer(x, y, width, height);
   SendVSyncUpdateIfAvailable();
+  bool result = gfx::GLSurfaceAdapter::PostSubBuffer(x, y, width, height);
+  latency_info_.swap_timestamp = base::TimeTicks::HighResNow();
 
   if (transport_) {
     DCHECK(!is_swap_buffers_pending_);
@@ -237,6 +284,7 @@
     // PostSubBuffer message.
     GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params params;
     params.surface_handle = 0;
+    params.latency_info = latency_info_;
     params.surface_size = surface()->GetSize();
     params.x = x;
     params.y = y;
@@ -245,6 +293,8 @@
     helper_->SendAcceleratedSurfacePostSubBuffer(params);
 
     helper_->SetScheduled(false);
+  } else {
+    helper_->SendLatencyInfo(latency_info_);
   }
   return result;
 }
@@ -272,6 +322,7 @@
   DCHECK(transport_);
   Resize(new_size_);
 
+  TRACE_EVENT_ASYNC_END0("gpu", "OnResize", this);
   helper_->SetScheduled(true);
 }
 
@@ -281,6 +332,8 @@
   if (transport_) {
     helper_->SendResizeView(size);
     helper_->SetScheduled(false);
+    TRACE_EVENT_ASYNC_BEGIN2("gpu", "OnResize", this,
+                             "width", size.width(), "height", size.height());
   } else {
     Resize(new_size_);
   }
diff --git a/content/common/gpu/image_transport_surface.h b/content/common/gpu/image_transport_surface.h
index b4b7a49..503a411 100644
--- a/content/common/gpu/image_transport_surface.h
+++ b/content/common/gpu/image_transport_surface.h
@@ -12,6 +12,7 @@
 #include "base/memory/ref_counted.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/weak_ptr.h"
+#include "cc/debug/latency_info.h"
 #include "content/common/content_export.h"
 #include "ipc/ipc_listener.h"
 #include "ipc/ipc_message.h"
@@ -63,12 +64,15 @@
       const AcceleratedSurfaceMsg_BufferPresented_Params& params) = 0;
   virtual void OnResizeViewACK() = 0;
   virtual void OnResize(gfx::Size size) = 0;
+  virtual void SetLatencyInfo(
+      const cc::LatencyInfo& latency_info) = 0;
 
-  // Creates the appropriate surface depending on the GL implementation.
-  static scoped_refptr<gfx::GLSurface>
-      CreateSurface(GpuChannelManager* manager,
-                    GpuCommandBufferStub* stub,
-                    const gfx::GLSurfaceHandle& handle);
+  // Creates a surface with the given attributes.
+  static scoped_refptr<gfx::GLSurface> CreateSurface(
+      GpuChannelManager* manager,
+      GpuCommandBufferStub* stub,
+      const gfx::GLSurfaceHandle& handle);
+
 #if defined(OS_MACOSX)
   CONTENT_EXPORT static void SetAllowOSMesaForTesting(bool allow);
 #endif
@@ -79,6 +83,18 @@
   virtual ~ImageTransportSurface();
 
  private:
+  // Creates the appropriate native surface depending on the GL implementation.
+  // This will be implemented separately by each platform.
+  //
+  // This will not be called for texture transport surfaces which are
+  // cross-platform. The platform implementation should only create the
+  // surface and should not initialize it. On failure, a null scoped_refptr
+  // should be returned.
+  static scoped_refptr<gfx::GLSurface> CreateNativeSurface(
+      GpuChannelManager* manager,
+      GpuCommandBufferStub* stub,
+      const gfx::GLSurfaceHandle& handle);
+
   DISALLOW_COPY_AND_ASSIGN(ImageTransportSurface);
 };
 
@@ -111,6 +127,8 @@
   void SendUpdateVSyncParameters(
       base::TimeTicks timebase, base::TimeDelta interval);
 
+  void SendLatencyInfo(const cc::LatencyInfo& latency_info);
+
   // Whether or not we should execute more commands.
   void SetScheduled(bool is_scheduled);
 
@@ -142,6 +160,8 @@
   // Backbuffer resize callback.
   void Resize(gfx::Size size);
 
+  void SetLatencyInfo(const cc::LatencyInfo& latency_info);
+
   // Weak pointers that point to objects that outlive this helper.
   ImageTransportSurface* surface_;
   GpuChannelManager* manager_;
@@ -178,6 +198,8 @@
   virtual void OnResizeViewACK() OVERRIDE;
   virtual void OnResize(gfx::Size size) OVERRIDE;
   virtual gfx::Size GetSize() OVERRIDE;
+  virtual void SetLatencyInfo(
+      const cc::LatencyInfo& latency_info) OVERRIDE;
 
  protected:
   virtual ~PassThroughImageTransportSurface();
@@ -193,6 +215,7 @@
   bool did_set_swap_interval_;
   bool did_unschedule_;
   bool is_swap_buffers_pending_;
+  cc::LatencyInfo latency_info_;
 
   DISALLOW_COPY_AND_ASSIGN(PassThroughImageTransportSurface);
 };
diff --git a/content/common/gpu/image_transport_surface_android.cc b/content/common/gpu/image_transport_surface_android.cc
index a497559..2d8ee43 100644
--- a/content/common/gpu/image_transport_surface_android.cc
+++ b/content/common/gpu/image_transport_surface_android.cc
@@ -5,45 +5,32 @@
 #include "content/common/gpu/image_transport_surface.h"
 
 #include "base/logging.h"
+#include "content/common/gpu/gpu_command_buffer_stub.h"
 #include "content/common/gpu/gpu_surface_lookup.h"
-#include "content/common/gpu/texture_image_transport_surface.h"
 #include "ui/gl/gl_surface_egl.h"
 
 namespace content {
 
 // static
-scoped_refptr<gfx::GLSurface> ImageTransportSurface::CreateSurface(
+scoped_refptr<gfx::GLSurface> ImageTransportSurface::CreateNativeSurface(
     GpuChannelManager* manager,
     GpuCommandBufferStub* stub,
     const gfx::GLSurfaceHandle& handle) {
-  scoped_refptr<gfx::GLSurface> surface;
-  if (handle.transport_type == gfx::TEXTURE_TRANSPORT) {
-    surface = new TextureImageTransportSurface(manager, stub, handle);
-  } else if (handle.transport_type == gfx::NATIVE_DIRECT) {
-    DCHECK(GpuSurfaceLookup::GetInstance());
-    ANativeWindow* window =
-        GpuSurfaceLookup::GetInstance()->AcquireNativeWidget(
-            stub->surface_id());
-    surface = new gfx::NativeViewGLSurfaceEGL(false, window);
-    bool initialize_success = surface->Initialize();
-    if (window)
-      ANativeWindow_release(window);
-    if (!initialize_success)
-      return NULL;
+  DCHECK(GpuSurfaceLookup::GetInstance());
+  DCHECK_EQ(handle.transport_type, gfx::NATIVE_DIRECT);
+  ANativeWindow* window =
+      GpuSurfaceLookup::GetInstance()->AcquireNativeWidget(
+          stub->surface_id());
+  scoped_refptr<gfx::GLSurface> surface =
+      new gfx::NativeViewGLSurfaceEGL(false, window);
+  bool initialize_success = surface->Initialize();
+  if (window)
+    ANativeWindow_release(window);
+  if (!initialize_success)
+    return scoped_refptr<gfx::GLSurface>();
 
-    surface = new PassThroughImageTransportSurface(
-        manager, stub, surface.get(), false);
-  } else {
-    NOTIMPLEMENTED();
-    return NULL;
-  }
-
-  if (surface->Initialize()) {
-    return surface;
-  } else {
-    LOG(ERROR) << "Failed to initialize ImageTransportSurface";
-    return NULL;
-  }
+  return scoped_refptr<gfx::GLSurface>(new PassThroughImageTransportSurface(
+      manager, stub, surface.get(), false));
 }
 
 }  // namespace content
diff --git a/content/common/gpu/image_transport_surface_linux.cc b/content/common/gpu/image_transport_surface_linux.cc
deleted file mode 100644
index b9a97db..0000000
--- a/content/common/gpu/image_transport_surface_linux.cc
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/common/gpu/image_transport_surface.h"
-
-#include "content/common/gpu/texture_image_transport_surface.h"
-
-namespace content {
-
-// static
-scoped_refptr<gfx::GLSurface> ImageTransportSurface::CreateSurface(
-    GpuChannelManager* manager,
-    GpuCommandBufferStub* stub,
-    const gfx::GLSurfaceHandle& handle) {
-  scoped_refptr<gfx::GLSurface> surface;
-  if (handle.transport_type == gfx::TEXTURE_TRANSPORT) {
-    DCHECK(!handle.handle);
-    surface = new TextureImageTransportSurface(manager, stub, handle);
-  } else {
-    DCHECK(handle.handle);
-    DCHECK(handle.transport_type == gfx::NATIVE_DIRECT ||
-           handle.transport_type == gfx::NATIVE_TRANSPORT);
-    surface = gfx::GLSurface::CreateViewGLSurface(false, handle.handle);
-    if (!surface.get())
-      return NULL;
-    surface = new PassThroughImageTransportSurface(manager,
-                                                   stub,
-                                                   surface.get(),
-                                                   handle.is_transport());
-  }
-
-  if (surface->Initialize())
-    return surface;
-  else
-    return NULL;
-}
-
-}  // namespace content
diff --git a/content/common/gpu/image_transport_surface_mac.cc b/content/common/gpu/image_transport_surface_mac.cc
index 22a7460..62c3265 100644
--- a/content/common/gpu/image_transport_surface_mac.cc
+++ b/content/common/gpu/image_transport_surface_mac.cc
@@ -7,7 +7,6 @@
 #include "base/mac/scoped_cftyperef.h"
 #include "base/memory/scoped_ptr.h"
 #include "content/common/gpu/gpu_messages.h"
-#include "content/common/gpu/texture_image_transport_surface.h"
 #include "ui/gfx/native_widget_types.h"
 #include "ui/gl/gl_bindings.h"
 #include "ui/gl/gl_context.h"
@@ -61,6 +60,7 @@
       const AcceleratedSurfaceMsg_BufferPresented_Params& params) OVERRIDE;
   virtual void OnResizeViewACK() OVERRIDE;
   virtual void OnResize(gfx::Size size) OVERRIDE;
+  virtual void SetLatencyInfo(const cc::LatencyInfo&) OVERRIDE;
 
  private:
   virtual ~IOSurfaceImageTransportSurface() OVERRIDE;
@@ -96,6 +96,8 @@
   // Whether we unscheduled command buffer because of pending SwapBuffers.
   bool did_unschedule_;
 
+  cc::LatencyInfo latency_info_;
+
   scoped_ptr<ImageTransportHelper> helper_;
 
   DISALLOW_COPY_AND_ASSIGN(IOSurfaceImageTransportSurface);
@@ -215,7 +217,7 @@
       io_surface_.get()) {
     UnrefIOSurface();
     helper_->Suspend();
-  } else if (backbuffer_suggested_allocation_ && !io_surface_.get()) {
+  } else if (backbuffer_suggested_allocation_ && !io_surface_) {
     CreateIOSurface();
   }
 }
@@ -229,6 +231,7 @@
   GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params;
   params.surface_handle = io_surface_handle_;
   params.size = GetSize();
+  params.latency_info = latency_info_;
   helper_->SendAcceleratedSurfaceBuffersSwapped(params);
 
   DCHECK(!is_swap_buffers_pending_);
@@ -250,6 +253,7 @@
   params.width = width;
   params.height = height;
   params.surface_size = GetSize();
+  params.latency_info = latency_info_;
   helper_->SendAcceleratedSurfacePostSubBuffer(params);
 
   DCHECK(!is_swap_buffers_pending_);
@@ -298,6 +302,11 @@
   CreateIOSurface();
 }
 
+void IOSurfaceImageTransportSurface::SetLatencyInfo(
+    const cc::LatencyInfo& latency_info) {
+  latency_info_ = latency_info;
+}
+
 void IOSurfaceImageTransportSurface::UnrefIOSurface() {
   // If we have resources to destroy, then make sure that we have a current
   // context which we can use to delete the resources.
@@ -437,49 +446,37 @@
 }  // namespace
 
 // static
-scoped_refptr<gfx::GLSurface> ImageTransportSurface::CreateSurface(
+scoped_refptr<gfx::GLSurface> ImageTransportSurface::CreateNativeSurface(
     GpuChannelManager* manager,
     GpuCommandBufferStub* stub,
     const gfx::GLSurfaceHandle& surface_handle) {
-  scoped_refptr<gfx::GLSurface> surface;
-  if (surface_handle.transport_type == gfx::TEXTURE_TRANSPORT) {
-     surface = new TextureImageTransportSurface(manager, stub, surface_handle);
-  } else {
-    DCHECK(surface_handle.transport_type == gfx::NATIVE_TRANSPORT);
-    IOSurfaceSupport* io_surface_support = IOSurfaceSupport::Initialize();
+  DCHECK(surface_handle.transport_type == gfx::NATIVE_TRANSPORT);
+  IOSurfaceSupport* io_surface_support = IOSurfaceSupport::Initialize();
 
-    switch (gfx::GetGLImplementation()) {
-      case gfx::kGLImplementationDesktopGL:
-      case gfx::kGLImplementationAppleGL:
-        if (!io_surface_support) {
-          DLOG(WARNING) << "No IOSurface support";
-          return NULL;
-        } else {
-          surface = new IOSurfaceImageTransportSurface(
-              manager, stub, surface_handle.handle);
-        }
-        break;
-      default:
-        // Content shell in DRT mode spins up a gpu process which needs an
-        // image transport surface, but that surface isn't used to read pixel
-        // baselines. So this is mostly a dummy surface.
-        if (g_allow_os_mesa) {
-          surface = new DRTSurfaceOSMesa();
-          if (!surface || !surface->Initialize())
-            return NULL;
+  switch (gfx::GetGLImplementation()) {
+    case gfx::kGLImplementationDesktopGL:
+    case gfx::kGLImplementationAppleGL:
+      if (!io_surface_support) {
+        DLOG(WARNING) << "No IOSurface support";
+        return scoped_refptr<gfx::GLSurface>();
+      }
+      return scoped_refptr<gfx::GLSurface>(new IOSurfaceImageTransportSurface(
+          manager, stub, surface_handle.handle));
 
-          surface = new PassThroughImageTransportSurface(
-              manager, stub, surface.get(), /*is_transport=*/false);
-        } else {
-          NOTREACHED();
-          return NULL;
-        }
-    }
+    default:
+      // Content shell in DRT mode spins up a gpu process which needs an
+      // image transport surface, but that surface isn't used to read pixel
+      // baselines. So this is mostly a dummy surface.
+      if (!g_allow_os_mesa) {
+        NOTREACHED();
+        return scoped_refptr<gfx::GLSurface>();
+      }
+      scoped_refptr<gfx::GLSurface> surface(new DRTSurfaceOSMesa());
+      if (!surface || !surface->Initialize())
+        return surface;
+      return scoped_refptr<gfx::GLSurface>(new PassThroughImageTransportSurface(
+          manager, stub, surface.get(), false));
   }
-  if (surface->Initialize())
-    return surface;
-  else
-    return NULL;
 }
 
 // static
diff --git a/content/common/gpu/image_transport_surface_win.cc b/content/common/gpu/image_transport_surface_win.cc
index 479eeb4..5e27ba0 100644
--- a/content/common/gpu/image_transport_surface_win.cc
+++ b/content/common/gpu/image_transport_surface_win.cc
@@ -12,7 +12,6 @@
 #include "base/win/windows_version.h"
 #include "content/common/gpu/gpu_messages.h"
 #include "content/public/common/content_switches.h"
-#include "content/common/gpu/texture_image_transport_surface.h"
 #include "ui/gfx/native_widget_types.h"
 #include "ui/gl/gl_bindings.h"
 #include "ui/gl/gl_context.h"
@@ -49,6 +48,7 @@
       const AcceleratedSurfaceMsg_BufferPresented_Params& params) OVERRIDE;
   virtual void OnResizeViewACK() OVERRIDE;
   virtual void OnResize(gfx::Size size) OVERRIDE;
+  virtual void SetLatencyInfo(const cc::LatencyInfo&) OVERRIDE;
   virtual gfx::Size GetSize() OVERRIDE;
 
  private:
@@ -69,6 +69,8 @@
   // Size to resize to when the surface becomes visible.
   gfx::Size visible_size_;
 
+  cc::LatencyInfo latency_info_;
+
   scoped_ptr<ImageTransportHelper> helper_;
 
   DISALLOW_COPY_AND_ASSIGN(PbufferImageTransportSurface);
@@ -196,6 +198,7 @@
   params.surface_handle = reinterpret_cast<int64>(GetShareHandle());
   CHECK(params.surface_handle);
   params.size = GetSize();
+  params.latency_info = latency_info_;
 
   helper_->SendAcceleratedSurfaceBuffersSwapped(params);
 
@@ -226,6 +229,11 @@
   visible_size_ = size;
 }
 
+void PbufferImageTransportSurface::SetLatencyInfo(
+    const cc::LatencyInfo& latency_info) {
+  latency_info_ = latency_info;
+}
+
 gfx::Size PbufferImageTransportSurface::GetSize() {
   return GLSurfaceAdapter::GetSize();
 }
@@ -233,57 +241,39 @@
 }  // namespace anonymous
 
 // static
-scoped_refptr<gfx::GLSurface> ImageTransportSurface::CreateSurface(
+scoped_refptr<gfx::GLSurface> ImageTransportSurface::CreateNativeSurface(
     GpuChannelManager* manager,
     GpuCommandBufferStub* stub,
     const gfx::GLSurfaceHandle& handle) {
-  scoped_refptr<gfx::GLSurface> surface;
-
-  if (handle.transport_type == gfx::TEXTURE_TRANSPORT) {
-    // If we don't have a valid handle with the transport flag set, then we're
-    // coming from a renderer and we want to render the webpage contents to a
-    // texture.
-    DCHECK(!handle.handle);
-    surface = new TextureImageTransportSurface(manager, stub, handle);
-  } else {
-    DCHECK(handle.handle);
-    DCHECK(handle.transport_type == gfx::NATIVE_DIRECT ||
-           handle.transport_type == gfx::NATIVE_TRANSPORT);
-    if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 &&
-        !CommandLine::ForCurrentProcess()->HasSwitch(
-            switches::kDisableImageTransportSurface)) {
-      // This path handles two different cases.
-      //
-      // For post-Vista regular Windows, this surface will be used for
-      // renderer compositors.
-      //
-      // For Aura Windows, this will be the surface for the browser compositor
-      // (and the renderer compositors surface's will be
-      // TextureImageTransportSurface above).
-      const char* extensions = eglQueryString(
-          eglGetDisplay(EGL_DEFAULT_DISPLAY), EGL_EXTENSIONS);
-      if (strstr(extensions, "EGL_ANGLE_query_surface_pointer") &&
-          strstr(extensions, "EGL_ANGLE_surface_d3d_texture_2d_share_handle")) {
-        surface = new PbufferImageTransportSurface(manager, stub);
-      }
-    }
-
-    if (!surface.get()) {
-      surface = gfx::GLSurface::CreateViewGLSurface(false, handle.handle);
-      if (!surface.get())
-        return NULL;
-
-      surface = new PassThroughImageTransportSurface(manager,
-                                                    stub,
-                                                    surface.get(),
-                                                    handle.is_transport());
+  DCHECK(handle.handle);
+  DCHECK(handle.transport_type == gfx::NATIVE_DIRECT ||
+         handle.transport_type == gfx::NATIVE_TRANSPORT);
+  if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 &&
+      !CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kDisableImageTransportSurface)) {
+    // This path handles two different cases.
+    //
+    // For post-Vista regular Windows, this surface will be used for
+    // renderer compositors.
+    //
+    // For Aura Windows, this will be the surface for the browser compositor
+    // (and the renderer compositors surface's will be
+    // TextureImageTransportSurface above).
+    const char* extensions = eglQueryString(
+        eglGetDisplay(EGL_DEFAULT_DISPLAY), EGL_EXTENSIONS);
+    if (strstr(extensions, "EGL_ANGLE_query_surface_pointer") &&
+        strstr(extensions, "EGL_ANGLE_surface_d3d_texture_2d_share_handle")) {
+      return scoped_refptr<gfx::GLSurface>(
+          new PbufferImageTransportSurface(manager, stub));
     }
   }
 
-  if (surface->Initialize())
+  scoped_refptr<gfx::GLSurface> surface =
+      gfx::GLSurface::CreateViewGLSurface(false, handle.handle);
+  if (!surface)
     return surface;
-  else
-    return NULL;
+  return scoped_refptr<gfx::GLSurface>(new PassThroughImageTransportSurface(
+      manager, stub, surface.get(), handle.is_transport()));
 }
 
 }  // namespace content
diff --git a/content/common/gpu/image_transport_surface_x11.cc b/content/common/gpu/image_transport_surface_x11.cc
new file mode 100644
index 0000000..b6aca42
--- /dev/null
+++ b/content/common/gpu/image_transport_surface_x11.cc
@@ -0,0 +1,25 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/common/gpu/image_transport_surface.h"
+
+namespace content {
+
+// static
+scoped_refptr<gfx::GLSurface> ImageTransportSurface::CreateNativeSurface(
+    GpuChannelManager* manager,
+    GpuCommandBufferStub* stub,
+    const gfx::GLSurfaceHandle& handle) {
+  DCHECK(handle.handle);
+  DCHECK(handle.transport_type == gfx::NATIVE_DIRECT ||
+         handle.transport_type == gfx::NATIVE_TRANSPORT);
+  scoped_refptr<gfx::GLSurface> surface =
+      gfx::GLSurface::CreateViewGLSurface(false, handle.handle);
+  if (!surface)
+    return surface;
+  return scoped_refptr<gfx::GLSurface>(new PassThroughImageTransportSurface(
+      manager, stub, surface.get(), handle.is_transport()));
+}
+
+}  // namespace content
diff --git a/content/common/gpu/media/android_video_decode_accelerator.cc b/content/common/gpu/media/android_video_decode_accelerator.cc
index 3e4dacd..4d65c61 100644
--- a/content/common/gpu/media/android_video_decode_accelerator.cc
+++ b/content/common/gpu/media/android_video_decode_accelerator.cc
@@ -7,28 +7,28 @@
 #include "base/bind.h"
 #include "base/logging.h"
 #include "base/message_loop.h"
-#include "content/common/android/scoped_java_surface.h"
 #include "content/common/gpu/gpu_channel.h"
 #include "gpu/command_buffer/service/gles2_cmd_decoder.h"
 #include "media/base/bitstream_buffer.h"
 #include "media/base/limits.h"
 #include "media/video/picture.h"
+#include "ui/gl/android/scoped_java_surface.h"
 #include "ui/gl/gl_bindings.h"
 
 namespace content {
 
 // Helper macros for dealing with failure.  If |result| evaluates false, emit
 // |log| to ERROR, register |error| with the decoder, and return.
-#define RETURN_ON_FAILURE(result, log, error)                      \
-  do {                                                             \
-    if (!(result)) {                                               \
-      DLOG(ERROR) << log;                                          \
-      MessageLoop::current()->PostTask(FROM_HERE, base::Bind(      \
-          &AndroidVideoDecodeAccelerator::NotifyError,             \
-          base::AsWeakPtr(this), error));                          \
-      state_ = ERROR;                                              \
-      return;                                                      \
-    }                                                              \
+#define RETURN_ON_FAILURE(result, log, error)                       \
+  do {                                                              \
+    if (!(result)) {                                                \
+      DLOG(ERROR) << log;                                           \
+      base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind( \
+          &AndroidVideoDecodeAccelerator::NotifyError,              \
+          base::AsWeakPtr(this), error));                           \
+      state_ = ERROR;                                               \
+      return;                                                       \
+    }                                                               \
   } while (0)
 
 // TODO(dwkang): We only need kMaxVideoFrames to pass media stack's prerolling
@@ -50,7 +50,7 @@
     const base::Callback<bool(void)>& make_context_current)
     : client_(client),
       make_context_current_(make_context_current),
-      codec_(media::MediaCodecBridge::VIDEO_H264),
+      codec_(media::kCodecH264),
       state_(NO_ERROR),
       surface_texture_id_(0),
       picturebuffers_requested_(false),
@@ -73,7 +73,7 @@
     return false;
 
   if (profile == media::VP8PROFILE_MAIN) {
-    codec_ = media::MediaCodecBridge::VIDEO_VP8;
+    codec_ = media::kCodecVP8;
   } else {
     // TODO(dwkang): enable H264 once b/8125974 is fixed.
     LOG(ERROR) << "Unsupported profile: " << profile;
@@ -85,7 +85,7 @@
     return false;
   }
 
-  if (!gl_decoder_.get()) {
+  if (!gl_decoder_) {
     LOG(ERROR) << "Failed to get gles2 decoder instance.";
     return false;
   }
@@ -102,11 +102,11 @@
   gl_decoder_->RestoreTextureUnitBindings(0);
   gl_decoder_->RestoreActiveTexture();
 
-  surface_texture_ = new SurfaceTextureBridge(surface_texture_id_);
+  surface_texture_ = new gfx::SurfaceTextureBridge(surface_texture_id_);
 
   ConfigureMediaCodec();
 
-  MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
+  base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
       &AndroidVideoDecodeAccelerator::NotifyInitializeDone,
       base::AsWeakPtr(this)));
   return true;
@@ -126,7 +126,7 @@
     io_task_is_posted_ = true;
     // TODO(dwkang): PostDelayedTask() does not guarantee the task will awake
     //               at the exact time. Need a better way for polling.
-    MessageLoop::current()->PostDelayedTask(
+    base::MessageLoop::current()->PostDelayedTask(
         FROM_HERE,
         base::Bind(
             &AndroidVideoDecodeAccelerator::DoIOTask, base::AsWeakPtr(this)),
@@ -187,7 +187,7 @@
     // keep getting more bitstreams from the client, and throttle them by using
     // |bitstreams_notified_in_advance_|.
     // TODO(dwkang): check if there is a way to remove this workaround.
-    MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
+    base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
         &AndroidVideoDecodeAccelerator::NotifyEndOfBitstreamBuffer,
         base::AsWeakPtr(this), bitstream_buffer.id()));
     bitstreams_notified_in_advance_.push_back(bitstream_buffer.id());
@@ -223,7 +223,7 @@
         if (!picturebuffers_requested_) {
           picturebuffers_requested_ = true;
           size_ = gfx::Size(width, height);
-          MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
+          base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
               &AndroidVideoDecodeAccelerator::RequestPictureBuffers,
               base::AsWeakPtr(this)));
         } else {
@@ -248,7 +248,7 @@
   media_codec_->ReleaseOutputBuffer(buf_index, true);
 
   if (eos) {
-    MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
+    base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
         &AndroidVideoDecodeAccelerator::NotifyFlushDone,
         base::AsWeakPtr(this)));
     decoder_met_eos_ = true;
@@ -319,7 +319,7 @@
                          picture_buffer_texture_id, 0, size_.width(),
                          size_.height(), false, false, false);
 
-  MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
+  base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
       &AndroidVideoDecodeAccelerator::NotifyPictureReady,
       base::AsWeakPtr(this), media::Picture(picture_buffer_id, bitstream_id)));
 }
@@ -328,7 +328,7 @@
     const media::BitstreamBuffer& bitstream_buffer) {
   DCHECK(thread_checker_.CalledOnValidThread());
   if (bitstream_buffer.id() != -1 && bitstream_buffer.size() == 0) {
-    MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
+    base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
         &AndroidVideoDecodeAccelerator::NotifyEndOfBitstreamBuffer,
         base::AsWeakPtr(this), bitstream_buffer.id()));
     return;
@@ -379,13 +379,13 @@
 void AndroidVideoDecodeAccelerator::ConfigureMediaCodec() {
   DCHECK(surface_texture_.get());
 
-  media_codec_.reset(new media::MediaCodecBridge(codec_));
+  media_codec_.reset(new media::VideoCodecBridge(codec_));
 
-  ScopedJavaSurface surface(surface_texture_.get());
+  gfx::ScopedJavaSurface surface(surface_texture_.get());
   // VDA does not pass the container indicated resolution in the initialization
   // phase. Here, we set 720p by default.
   // TODO(dwkang): find out a way to remove the following hard-coded value.
-  media_codec_->StartVideo(
+  media_codec_->Start(
       codec_, gfx::Size(1280, 720), surface.j_surface().obj());
   media_codec_->GetOutputBuffers();
 }
@@ -399,7 +399,7 @@
     pending_bitstream_buffers_.pop();
 
     if (bitstream_buffer.id() != -1) {
-      MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
+      base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
           &AndroidVideoDecodeAccelerator::NotifyEndOfBitstreamBuffer,
           base::AsWeakPtr(this), bitstream_buffer.id()));
     }
@@ -418,7 +418,7 @@
   num_bytes_used_in_the_pending_buffer_ = 0;
   state_ = NO_ERROR;
 
-  MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
+  base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
       &AndroidVideoDecodeAccelerator::NotifyResetDone, base::AsWeakPtr(this)));
 }
 
diff --git a/content/common/gpu/media/android_video_decode_accelerator.h b/content/common/gpu/media/android_video_decode_accelerator.h
index 6ddd7f0..e892999 100644
--- a/content/common/gpu/media/android_video_decode_accelerator.h
+++ b/content/common/gpu/media/android_video_decode_accelerator.h
@@ -20,9 +20,11 @@
 #include "media/base/android/media_codec_bridge.h"
 #include "media/video/video_decode_accelerator.h"
 
-namespace content {
-
+namespace gfx {
 class SurfaceTextureBridge;
+}
+
+namespace content {
 
 // A VideoDecodeAccelerator implementation for Android.
 // This class decodes the input encoded stream by using Android's MediaCodec
@@ -107,7 +109,7 @@
   base::Callback<bool(void)> make_context_current_;
 
   // Codec type. Used when we configure media codec.
-  media::MediaCodecBridge::Codec codec_;
+  media::VideoCodec codec_;
 
   // The current state of this class. For now, this is used only for setting
   // error state.
@@ -123,10 +125,10 @@
   std::queue<int32> free_picture_ids_;
 
   // The low-level decoder which Android SDK provides.
-  scoped_ptr<media::MediaCodecBridge> media_codec_;
+  scoped_ptr<media::VideoCodecBridge> media_codec_;
 
   // A container of texture. Used to set a texture to |media_codec_|.
-  scoped_refptr<SurfaceTextureBridge> surface_texture_;
+  scoped_refptr<gfx::SurfaceTextureBridge> surface_texture_;
 
   // The texture id which is set to |surface_texture_|.
   uint32 surface_texture_id_;
diff --git a/content/common/gpu/media/avc_config_record_builder.cc b/content/common/gpu/media/avc_config_record_builder.cc
deleted file mode 100644
index df0abe7..0000000
--- a/content/common/gpu/media/avc_config_record_builder.cc
+++ /dev/null
@@ -1,155 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/common/gpu/media/avc_config_record_builder.h"
-
-#include <limits>
-
-#include "base/logging.h"
-#include "content/common/gpu/media/h264_parser.h"
-
-namespace content {
-
-AVCConfigRecordBuilder::AVCConfigRecordBuilder()
-    : sps_profile_idc_(0),
-      sps_constraint_setx_flag_(0),
-      sps_level_idc_(0),
-      coded_width_(0),
-      coded_height_(0) {
-}
-
-AVCConfigRecordBuilder::~AVCConfigRecordBuilder() {
-}
-
-bool AVCConfigRecordBuilder::ProcessNALU(
-    H264Parser* parser,
-    const H264NALU& nalu,
-    std::vector<uint8>* config_record) {
-  if (nalu.nal_unit_type == H264NALU::kSPS) {
-    return ProcessSPS(parser, nalu);
-  } else if (nalu.nal_unit_type == H264NALU::kPPS) {
-    return ProcessPPS(parser, nalu);
-  } else if (nalu.nal_unit_type >= 1 && nalu.nal_unit_type <= 5) {
-    // Ready to build the AVC decoder configuration record once the first slice
-    // type is encountered.
-    return BuildConfigRecord(config_record);
-  }
-  // Effectively skip this NALU by returning success.
-  return true;
-}
-
-bool AVCConfigRecordBuilder::BuildConfigRecord(
-    std::vector<uint8>* config_record) {
-  // 5 bytes for AVC record header. 1 byte for the number of SPS units.
-  // 1 byte for the number of PPS units.
-  size_t record_size = 7;
-  for (NALUVector::const_iterator it = sps_nalus_.begin();
-       it != sps_nalus_.end(); ++it) {
-    // Plus 2 bytes to store the SPS size.
-    size_t size = (*it)->size() + 2;
-    if (std::numeric_limits<size_t>::max() - size <= record_size)
-      return false;
-    record_size += size;
-  }
-  for (NALUVector::const_iterator it = pps_nalus_.begin();
-       it != pps_nalus_.end(); ++it) {
-    // Plus 2 bytes to store the PPS size.
-    size_t size = (*it)->size() + 2;
-    if (std::numeric_limits<size_t>::max() - size <= record_size)
-      return false;
-    record_size += size;
-  }
-  std::vector<uint8> extra_data(record_size);
-
-  // AVC decoder configuration record version.
-  extra_data[0] = 0x01;
-  // Profile.
-  extra_data[1] = sps_profile_idc_ & 0xff;
-  // Profile compatibility, must match the byte between profile IDC
-  // and level IDC in the SPS.
-  extra_data[2] = sps_constraint_setx_flag_;
-  // AVC level.
-  extra_data[3] = sps_level_idc_ & 0xff;
-
-  // TODO(sail): There's no way to get the NALU length field size from the
-  // SPS and PPS data. Just assume 4 for now.
-  const size_t kNALULengthFieldSize = 4;
-
-  // The first 6 bits are reserved and must be 1. Last two bits are the
-  // NALU field size minus 1.
-  extra_data[4] = 0xfc | ((kNALULengthFieldSize - 1) & 0x03);
-
-  // The first 3 bits are reserved and must be 1. Last 5 bits are the
-  // number of SPS units.
-  extra_data[5] = 0xe0 | (sps_nalus_.size() & 0x1f);
-  size_t index = 6;
-  if (!sps_nalus_.empty())
-    index += CopyNALUsToConfigRecord(sps_nalus_, &extra_data[index]);
-
-  // The number of PPS units.
-  extra_data[index++] = pps_nalus_.size() & 0xff;
-  if (!pps_nalus_.empty())
-    CopyNALUsToConfigRecord(pps_nalus_, &extra_data[index]);
-
-  *config_record = extra_data;
-  return true;
-}
-
-size_t AVCConfigRecordBuilder::CopyNALUsToConfigRecord(const NALUVector& nalus,
-                                                       uint8* record_buffer) {
-  size_t index = 0;
-  for (NALUVector::const_iterator it = nalus.begin();
-       it != nalus.end(); ++it) {
-    // High byte of the NALU size.
-    record_buffer[index++] = ((*it)->size() >> 8) & 0xff;
-    // Low byte of the NALU size.
-    record_buffer[index++] = (*it)->size() & 0xff;
-    // The NALU data.
-    memcpy(record_buffer + index, (*it)->front(), (*it)->size());
-    index += (*it)->size();
-  }
-  return index;
-}
-
-bool AVCConfigRecordBuilder::ProcessSPS(H264Parser* parser,
-                                        const H264NALU& nalu) {
-  int sps_id = 0;
-  H264Parser::Result result = parser->ParseSPS(&sps_id);
-  if (result != H264Parser::kOk)
-    return false;
-
-  std::vector<uint8> bytes(nalu.data, nalu.data + nalu.size);
-  sps_nalus_.push_back(base::RefCountedBytes::TakeVector(&bytes));
-
-  const H264SPS* sps = parser->GetSPS(sps_id);
-
-  // Use the last width and height that are encountered.
-  coded_width_ = (sps->pic_width_in_mbs_minus1 + 1) * 16;
-  if (sps->frame_mbs_only_flag)
-    coded_height_ = (sps->pic_height_in_map_units_minus1 + 1) * 16;
-  else
-    coded_height_ = (sps->pic_height_in_map_units_minus1 + 1) * 32;
-
-  // Use the last video profile and flags that are encountered.
-  sps_profile_idc_ = sps->profile_idc;
-  sps_constraint_setx_flag_ = sps->constraint_setx_flag;
-  // Use the largest AVC level that's encountered.
-  sps_level_idc_ = std::max(sps_level_idc_, sps->level_idc);
-
-  return true;
-}
-
-bool AVCConfigRecordBuilder::ProcessPPS(H264Parser* parser,
-                                        const H264NALU& nalu) {
-  int pps_id = 0;
-  H264Parser::Result result = parser->ParsePPS(&pps_id);
-  if (result != H264Parser::kOk)
-    return false;
-
-  std::vector<uint8> bytes(nalu.data, nalu.data + nalu.size);
-  pps_nalus_.push_back(base::RefCountedBytes::TakeVector(&bytes));
-  return true;
-}
-
-}  // namespace content
diff --git a/content/common/gpu/media/avc_config_record_builder.h b/content/common/gpu/media/avc_config_record_builder.h
deleted file mode 100644
index 3214244..0000000
--- a/content/common/gpu/media/avc_config_record_builder.h
+++ /dev/null
@@ -1,66 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_COMMON_GPU_MEDIA_AVC_CONFIG_RECORD_BUILDER_H_
-#define CONTENT_COMMON_GPU_MEDIA_AVC_CONFIG_RECORD_BUILDER_H_
-
-#include <vector>
-
-#include "base/memory/ref_counted.h"
-#include "base/memory/ref_counted_memory.h"
-#include "content/common/content_export.h"
-
-namespace content {
-
-struct H264NALU;
-class H264Parser;
-
-// Utility class to build an AVC configuration record given a stream of NALUs
-// containing SPS and PPS data.
-class CONTENT_EXPORT AVCConfigRecordBuilder {
- public:
-  AVCConfigRecordBuilder();
-  ~AVCConfigRecordBuilder();
-
-  // Processes the given NALU. If the final AVC decoder configuration record
-  // can be built then the NALU is not consumed and the record is returned
-  // in |config_record|. Otherwise the NALU is consumed and |config_record|
-  // is not modified. Returns true on success, false on failure.
-  bool ProcessNALU(H264Parser* parser,
-                   const H264NALU& nalu,
-                   std::vector<uint8>* config_record);
-
-  int coded_width() const { return coded_width_; }
-  int coded_height() const { return coded_height_; }
-
- private:
-  typedef std::vector<scoped_refptr<base::RefCountedBytes> > NALUVector;
-
-  bool ProcessSPS(H264Parser* parser, const H264NALU& nalu);
-  bool ProcessPPS(H264Parser* parser, const H264NALU& nalu);
-  bool BuildConfigRecord(std::vector<uint8>* config_record);
-
-  // Copies data from |nalus| into |record_buffer|. Returns the number of bytes
-  // that were written.
-  size_t CopyNALUsToConfigRecord(const NALUVector& nalus, uint8* record_buffer);
-
-  // Data for each SPS.
-  NALUVector sps_nalus_;
-  // Data for each PPS.
-  NALUVector pps_nalus_;
-  // The video codec profile stored in the SPS.
-  int sps_profile_idc_;
-  // The constraint setx flags stored in the SPS.
-  int sps_constraint_setx_flag_;
-  // The avc level stored in the SPS.
-  int sps_level_idc_;
-  // The width of the video as enocded in the SPS.
-  uint32 coded_width_;
-  // The height of the video as enocded in the SPS.
-  uint32 coded_height_;
-};
-
-}  // namespace content
-
-#endif  // CONTENT_COMMON_GPU_MEDIA_AVC_CONFIG_RECORD_BUILDER_H_
diff --git a/content/common/gpu/media/avc_config_record_builder_unittest.cc b/content/common/gpu/media/avc_config_record_builder_unittest.cc
deleted file mode 100644
index 150adca..0000000
--- a/content/common/gpu/media/avc_config_record_builder_unittest.cc
+++ /dev/null
@@ -1,92 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/common/gpu/media/avc_config_record_builder.h"
-
-#include "content/common/gpu/media/h264_parser.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace {
-
-const uint8 kSPSData[] = {
-  0x67, 0x64, 0x00, 0x1f, 0xac, 0x34, 0xec, 0x05,
-  0x00, 0x5b, 0xa1, 0x00, 0x00, 0x03, 0x00, 0x01,
-  0x00, 0x00, 0x03, 0x00, 0x32, 0x0f, 0x18, 0x31,
-  0x38,
-};
-
-const uint8 kPPSData[] = {
-  0x68, 0xef, 0xb2, 0xc8, 0xb0,
-};
-
-const uint8 kNALUHeader[] = {
-  0x00, 0x00, 0x00, 0x01
-};
-
-}  // namespace
-
-TEST(AVCConfigRecordBuilderTest, BuildConfig) {
-  std::vector<uint8> stream;
-  stream.insert(stream.end(), kNALUHeader,
-                kNALUHeader + arraysize(kNALUHeader));
-  stream.insert(stream.end(), kSPSData, kSPSData + arraysize(kSPSData));
-  stream.insert(stream.end(), kNALUHeader,
-                kNALUHeader + arraysize(kNALUHeader));
-  stream.insert(stream.end(), kPPSData, kPPSData + arraysize(kPPSData));
-
-  content::H264Parser parser;
-  parser.SetStream(&stream[0], stream.size());
-  content::H264NALU nalu;
-  ASSERT_EQ(parser.AdvanceToNextNALU(&nalu), content::H264Parser::kOk);
-
-  content::AVCConfigRecordBuilder config;
-  std::vector<uint8> config_data;
-  EXPECT_TRUE(config.ProcessNALU(&parser, nalu, &config_data));
-  EXPECT_TRUE(config_data.empty());
-
-  ASSERT_EQ(parser.AdvanceToNextNALU(&nalu), content::H264Parser::kOk);
-
-  EXPECT_TRUE(config.ProcessNALU(&parser, nalu, &config_data));
-  EXPECT_TRUE(config_data.empty());
-
-  nalu.nal_unit_type = content::H264NALU::kIDRSlice;
-  EXPECT_TRUE(config.ProcessNALU(&parser, nalu, &config_data));
-  EXPECT_FALSE(config_data.empty());
-  EXPECT_EQ(config.coded_width(), 1280);
-  EXPECT_EQ(config.coded_height(), 720);
-
-  const uint8 kExpectedData[] = {
-    0x01, 0x64, 0x00, 0x1f,    0xff, 0xe1, 0x00, 0x19,
-    0x67, 0x64, 0x00, 0x1f,    0xac, 0x34, 0xec, 0x05,
-    0x00, 0x5b, 0xa1, 0x00,    0x00, 0x03, 0x00, 0x01,
-    0x00, 0x00, 0x03, 0x00,    0x32, 0x0f, 0x18, 0x31,
-    0x38, 0x01, 0x00, 0x05,    0x68, 0xef, 0xb2, 0xc8,
-    0xb0,
-  };
-  std::vector<uint8> expected_config_data(
-        kExpectedData, kExpectedData + arraysize(kExpectedData));
-  EXPECT_EQ(config_data, expected_config_data);
-}
-
-// Test building a config record with zero SPS and PPS data.
-TEST(AVCConfigRecordBuilderTest, EmptyConfig) {
-  content::AVCConfigRecordBuilder config;
-  content::H264Parser parser;
-  std::vector<uint8> config_data;
-
-  // Feed the builder a slice right away.
-  content::H264NALU nalu;
-  nalu.nal_unit_type = content::H264NALU::kIDRSlice;
-  EXPECT_TRUE(config.ProcessNALU(&parser, nalu, &config_data));
-  EXPECT_FALSE(config_data.empty());
-  EXPECT_EQ(config.coded_width(), 0);
-  EXPECT_EQ(config.coded_height(), 0);
-
-  const uint8 kExpectedData[] = {
-    0x01, 0x0, 0x00, 0x0, 0xff, 0xe0, 0x00,
-  };
-  std::vector<uint8> expected_config_data(
-        kExpectedData, kExpectedData + arraysize(kExpectedData));
-  EXPECT_EQ(config_data, expected_config_data);
-}
diff --git a/content/common/gpu/media/dxva_video_decode_accelerator.cc b/content/common/gpu/media/dxva_video_decode_accelerator.cc
index ad79c51..1d14852 100644
--- a/content/common/gpu/media/dxva_video_decode_accelerator.cc
+++ b/content/common/gpu/media/dxva_video_decode_accelerator.cc
@@ -498,7 +498,7 @@
       PLATFORM_FAILURE, false);
 
   state_ = kNormal;
-  MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
+  base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
       &DXVAVideoDecodeAccelerator::NotifyInitializeDone,
       base::AsWeakPtr(this)));
   return true;
@@ -531,6 +531,9 @@
 
   RETURN_AND_NOTIFY_ON_FAILURE((state_ != kUninitialized),
       "Invalid state: " << state_, ILLEGAL_STATE,);
+  RETURN_AND_NOTIFY_ON_FAILURE((kNumPictureBuffers == buffers.size()),
+      "Failed to provide requested picture buffers. (Got " << buffers.size() <<
+      ", requested " << kNumPictureBuffers << ")", INVALID_ARGUMENT,);
 
   // Copy the picture buffers provided by the client to the available list,
   // and mark these buffers as available for use.
@@ -604,7 +607,7 @@
   RETURN_AND_NOTIFY_ON_FAILURE(SendMFTMessage(MFT_MESSAGE_COMMAND_FLUSH, 0),
       "Reset: Failed to send message.", PLATFORM_FAILURE,);
 
-  MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
+  base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
       &DXVAVideoDecodeAccelerator::NotifyResetDone, base::AsWeakPtr(this)));
 
   state_ = DXVAVideoDecodeAccelerator::kNormal;
@@ -875,7 +878,7 @@
   RETURN_ON_HR_FAILURE(hr, "Failed to get surface description", false);
 
   // Go ahead and request picture buffers.
-  MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
+  base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
       &DXVAVideoDecodeAccelerator::RequestPictureBuffers,
       base::AsWeakPtr(this), surface_desc.Width, surface_desc.Height));
 
@@ -916,7 +919,7 @@
 
       media::Picture output_picture(index->second->id(),
                                     sample_info.input_buffer_id);
-      MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
+      base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
           &DXVAVideoDecodeAccelerator::NotifyPictureReady,
           base::AsWeakPtr(this), output_picture));
 
@@ -926,7 +929,7 @@
   }
 
   if (!pending_input_buffers_.empty() && pending_output_samples_.empty()) {
-    MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
+    base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
         &DXVAVideoDecodeAccelerator::DecodePendingInputBuffers,
         base::AsWeakPtr(this)));
   }
@@ -1037,7 +1040,7 @@
       return;
   }
 
-  MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
+  base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
       &DXVAVideoDecodeAccelerator::NotifyFlushDone, base::AsWeakPtr(this)));
 
   state_ = kNormal;
@@ -1109,7 +1112,7 @@
   // decoder to emit an output packet for every input packet.
   // http://code.google.com/p/chromium/issues/detail?id=108121
   // http://code.google.com/p/chromium/issues/detail?id=150925
-  MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
+  base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
       &DXVAVideoDecodeAccelerator::NotifyInputBufferRead,
       base::AsWeakPtr(this), input_buffer_id));
 }
diff --git a/content/common/gpu/media/exynos_video_decode_accelerator.cc b/content/common/gpu/media/exynos_video_decode_accelerator.cc
index 43089b9..697ddd6 100644
--- a/content/common/gpu/media/exynos_video_decode_accelerator.cc
+++ b/content/common/gpu/media/exynos_video_decode_accelerator.cc
@@ -220,6 +220,7 @@
       mfc_output_streamon_(false),
       mfc_output_buffer_queued_count_(0),
       mfc_output_buffer_pixelformat_(0),
+      mfc_output_dpb_size_(0),
       gsc_fd_(-1),
       gsc_input_streamon_(false),
       gsc_input_buffer_queued_count_(0),
@@ -427,7 +428,9 @@
   DCHECK(child_message_loop_proxy_->BelongsToCurrentThread());
 
   if (buffers.size() != gsc_output_buffer_map_.size()) {
-    DLOG(ERROR) << "AssignPictureBuffers(): invalid buffer count";
+    DLOG(ERROR) << "AssignPictureBuffers(): Failed to provide requested picture"
+      " buffers. (Got " << buffers.size() << ", requested " <<
+      gsc_output_buffer_map_.size() << ")";
     NOTIFY_ERROR(INVALID_ARGUMENT);
     return;
   }
@@ -597,7 +600,7 @@
 void ExynosVideoDecodeAccelerator::DecodeTask(
     scoped_ptr<BitstreamBufferRef> bitstream_record) {
   DVLOG(3) << "DecodeTask(): input_id=" << bitstream_record->input_id;
-  DCHECK_EQ(decoder_thread_.message_loop(), MessageLoop::current());
+  DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
   DCHECK_NE(decoder_state_, kUninitialized);
   TRACE_EVENT1("Video Decoder", "EVDA::DecodeTask", "input_id",
                bitstream_record->input_id);
@@ -623,7 +626,7 @@
 
 void ExynosVideoDecodeAccelerator::DecodeBufferTask() {
   DVLOG(3) << "DecodeBufferTask()";
-  DCHECK_EQ(decoder_thread_.message_loop(), MessageLoop::current());
+  DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
   DCHECK_NE(decoder_state_, kUninitialized);
   TRACE_EVENT0("Video Decoder", "EVDA::DecodeBufferTask");
 
@@ -820,7 +823,7 @@
 }
 
 void ExynosVideoDecodeAccelerator::ScheduleDecodeBufferTaskIfNeeded() {
-  DCHECK_EQ(decoder_thread_.message_loop(), MessageLoop::current());
+  DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
 
   // If we're behind on tasks, schedule another one.
   int buffers_to_decode = decoder_input_queue_.size();
@@ -837,7 +840,7 @@
 bool ExynosVideoDecodeAccelerator::DecodeBufferInitial(
     const void* data, size_t size, size_t* endpos) {
   DVLOG(3) << "DecodeBufferInitial(): data=" << data << ", size=" << size;
-  DCHECK_EQ(decoder_thread_.message_loop(), MessageLoop::current());
+  DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
   DCHECK_NE(decoder_state_, kUninitialized);
   DCHECK_NE(decoder_state_, kDecoding);
   DCHECK(!device_poll_thread_.IsRunning());
@@ -912,7 +915,7 @@
 bool ExynosVideoDecodeAccelerator::DecodeBufferContinue(
     const void* data, size_t size) {
   DVLOG(3) << "DecodeBufferContinue(): data=" << data << ", size=" << size;
-  DCHECK_EQ(decoder_thread_.message_loop(), MessageLoop::current());
+  DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
   DCHECK_EQ(decoder_state_, kDecoding);
 
   // Both of these calls will set kError state if they fail.
@@ -924,7 +927,7 @@
 bool ExynosVideoDecodeAccelerator::AppendToInputFrame(
     const void* data, size_t size) {
   DVLOG(3) << "AppendToInputFrame()";
-  DCHECK_EQ(decoder_thread_.message_loop(), MessageLoop::current());
+  DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
   DCHECK_NE(decoder_state_, kUninitialized);
   DCHECK_NE(decoder_state_, kResetting);
   DCHECK_NE(decoder_state_, kError);
@@ -990,7 +993,7 @@
 
 bool ExynosVideoDecodeAccelerator::FlushInputFrame() {
   DVLOG(3) << "FlushInputFrame()";
-  DCHECK_EQ(decoder_thread_.message_loop(), MessageLoop::current());
+  DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
   DCHECK_NE(decoder_state_, kUninitialized);
   DCHECK_NE(decoder_state_, kResetting);
   DCHECK_NE(decoder_state_, kError);
@@ -1029,7 +1032,7 @@
 void ExynosVideoDecodeAccelerator::AssignPictureBuffersTask(
     scoped_ptr<PictureBufferArrayRef> pic_buffers) {
   DVLOG(3) << "AssignPictureBuffersTask()";
-  DCHECK_EQ(decoder_thread_.message_loop(), MessageLoop::current());
+  DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
   DCHECK_NE(decoder_state_, kUninitialized);
   TRACE_EVENT0("Video Decoder", "EVDA::AssignPictureBuffersTask");
 
@@ -1066,7 +1069,7 @@
 
 void ExynosVideoDecodeAccelerator::ServiceDeviceTask() {
   DVLOG(3) << "ServiceDeviceTask()";
-  DCHECK_EQ(decoder_thread_.message_loop(), MessageLoop::current());
+  DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
   DCHECK_NE(decoder_state_, kUninitialized);
   DCHECK_NE(decoder_state_, kInitialized);
   DCHECK_NE(decoder_state_, kAfterReset);
@@ -1135,7 +1138,7 @@
 
 void ExynosVideoDecodeAccelerator::EnqueueMfc() {
   DVLOG(3) << "EnqueueMfc()";
-  DCHECK_EQ(decoder_thread_.message_loop(), MessageLoop::current());
+  DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
   DCHECK_NE(decoder_state_, kUninitialized);
   TRACE_EVENT0("Video Decoder", "EVDA::EnqueueMfc");
 
@@ -1180,7 +1183,7 @@
 
 void ExynosVideoDecodeAccelerator::DequeueMfc() {
   DVLOG(3) << "DequeueMfc()";
-  DCHECK_EQ(decoder_thread_.message_loop(), MessageLoop::current());
+  DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
   DCHECK_NE(decoder_state_, kUninitialized);
   TRACE_EVENT0("Video Decoder", "EVDA::DequeueMfc");
 
@@ -1259,7 +1262,7 @@
 
 void ExynosVideoDecodeAccelerator::EnqueueGsc() {
   DVLOG(3) << "EnqueueGsc()";
-  DCHECK_EQ(decoder_thread_.message_loop(), MessageLoop::current());
+  DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
   DCHECK_NE(decoder_state_, kUninitialized);
   DCHECK_NE(decoder_state_, kInitialized);
   TRACE_EVENT0("Video Decoder", "EVDA::EnqueueGsc");
@@ -1285,9 +1288,13 @@
   }
 
   // Enqueue a GSC output, only if we need one
+  // TODO(ihf): Revert to size > 0 once issue 225563 is fixed.
+  COMPILE_ASSERT(
+      kDpbOutputBufferExtraCount >= kGscOutputBufferExtraForSyncCount,
+      gsc_output_buffer_extra_for_sync_count_too_large);
   if (gsc_input_buffer_queued_count_ != 0 &&
       gsc_output_buffer_queued_count_ == 0 &&
-      !gsc_free_output_buffers_.empty()) {
+      gsc_free_output_buffers_.size() > kGscOutputBufferExtraForSyncCount) {
     const int old_gsc_outputs_queued = gsc_output_buffer_queued_count_;
     if (!EnqueueGscOutputRecord())
       return;
@@ -1311,7 +1318,7 @@
 
 void ExynosVideoDecodeAccelerator::DequeueGsc() {
   DVLOG(3) << "DequeueGsc()";
-  DCHECK_EQ(decoder_thread_.message_loop(), MessageLoop::current());
+  DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
   DCHECK_NE(decoder_state_, kUninitialized);
   DCHECK_NE(decoder_state_, kInitialized);
   DCHECK_NE(decoder_state_, kAfterReset);
@@ -1518,7 +1525,7 @@
     int32 picture_buffer_id, scoped_ptr<EGLSyncKHRRef> egl_sync_ref) {
   DVLOG(3) << "ReusePictureBufferTask(): picture_buffer_id="
            << picture_buffer_id;
-  DCHECK_EQ(decoder_thread_.message_loop(), MessageLoop::current());
+  DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
   TRACE_EVENT0("Video Decoder", "EVDA::ReusePictureBufferTask");
 
   // We run ReusePictureBufferTask even if we're in kResetting.
@@ -1558,7 +1565,7 @@
 
 void ExynosVideoDecodeAccelerator::FlushTask() {
   DVLOG(3) << "FlushTask()";
-  DCHECK_EQ(decoder_thread_.message_loop(), MessageLoop::current());
+  DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
   TRACE_EVENT0("Video Decoder", "EVDA::FlushTask");
 
   // Flush outstanding buffers.
@@ -1620,7 +1627,7 @@
 
 void ExynosVideoDecodeAccelerator::ResetTask() {
   DVLOG(3) << "ResetTask()";
-  DCHECK_EQ(decoder_thread_.message_loop(), MessageLoop::current());
+  DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
   TRACE_EVENT0("Video Decoder", "EVDA::ResetTask");
 
   if (decoder_state_ == kError) {
@@ -1650,7 +1657,7 @@
 
 void ExynosVideoDecodeAccelerator::ResetDoneTask() {
   DVLOG(3) << "ResetDoneTask()";
-  DCHECK_EQ(decoder_thread_.message_loop(), MessageLoop::current());
+  DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
   TRACE_EVENT0("Video Decoder", "EVDA::ResetDoneTask");
 
   if (decoder_state_ == kError) {
@@ -1698,7 +1705,7 @@
 
 bool ExynosVideoDecodeAccelerator::StartDevicePoll() {
   DVLOG(3) << "StartDevicePoll()";
-  DCHECK_EQ(decoder_thread_.message_loop(), MessageLoop::current());
+  DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
   DCHECK(!device_poll_thread_.IsRunning());
 
   // Start up the device poll thread and schedule its first DevicePollTask().
@@ -1717,7 +1724,7 @@
 
 bool ExynosVideoDecodeAccelerator::StopDevicePoll() {
   DVLOG(3) << "StopDevicePoll()";
-  DCHECK_EQ(decoder_thread_.message_loop(), MessageLoop::current());
+  DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
 
   // Signal the DevicePollTask() to stop, and stop the device poll thread.
   if (!SetDevicePollInterrupt())
@@ -1790,7 +1797,7 @@
 
 bool ExynosVideoDecodeAccelerator::SetDevicePollInterrupt() {
   DVLOG(3) << "SetDevicePollInterrupt()";
-  DCHECK_EQ(decoder_thread_.message_loop(), MessageLoop::current());
+  DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
 
   const uint64 buf = 1;
   if (HANDLE_EINTR(write(device_poll_interrupt_fd_, &buf, sizeof(buf))) == -1) {
@@ -1803,7 +1810,7 @@
 
 bool ExynosVideoDecodeAccelerator::ClearDevicePollInterrupt() {
   DVLOG(3) << "ClearDevicePollInterrupt()";
-  DCHECK_EQ(decoder_thread_.message_loop(), MessageLoop::current());
+  DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
 
   uint64 buf;
   if (HANDLE_EINTR(read(device_poll_interrupt_fd_, &buf, sizeof(buf))) == -1) {
@@ -1821,7 +1828,7 @@
 
 void ExynosVideoDecodeAccelerator::DevicePollTask(unsigned int poll_fds) {
   DVLOG(3) << "DevicePollTask()";
-  DCHECK_EQ(device_poll_thread_.message_loop(), MessageLoop::current());
+  DCHECK_EQ(device_poll_thread_.message_loop(), base::MessageLoop::current());
   TRACE_EVENT0("Video Decoder", "EVDA::DevicePollTask");
 
   // This routine just polls the set of device fds, and schedules a
@@ -1886,7 +1893,7 @@
   // We can touch decoder_state_ only if this is the decoder thread or the
   // decoder thread isn't running.
   if (decoder_thread_.message_loop() != NULL &&
-      decoder_thread_.message_loop() != MessageLoop::current()) {
+      decoder_thread_.message_loop() != base::MessageLoop::current()) {
     decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
         &ExynosVideoDecodeAccelerator::SetDecoderState,
         base::Unretained(this), state));
@@ -1967,13 +1974,14 @@
   memset(&ctrl, 0, sizeof(ctrl));
   ctrl.id = V4L2_CID_MIN_BUFFERS_FOR_CAPTURE;
   IOCTL_OR_ERROR_RETURN_FALSE(mfc_fd_, VIDIOC_G_CTRL, &ctrl);
+  mfc_output_dpb_size_ = ctrl.value;
 
   // Output format setup in Initialize().
 
   // Allocate the output buffers.
   struct v4l2_requestbuffers reqbufs;
   memset(&reqbufs, 0, sizeof(reqbufs));
-  reqbufs.count  = ctrl.value + kMfcOutputBufferExtraCount;
+  reqbufs.count  = mfc_output_dpb_size_ + kDpbOutputBufferExtraCount;
   reqbufs.type   = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
   reqbufs.memory = V4L2_MEMORY_MMAP;
   IOCTL_OR_ERROR_RETURN_FALSE(mfc_fd_, VIDIOC_REQBUFS, &reqbufs);
@@ -2092,7 +2100,7 @@
 
   struct v4l2_requestbuffers reqbufs;
   memset(&reqbufs, 0, sizeof(reqbufs));
-  reqbufs.count = kGscOutputBufferCount;
+  reqbufs.count = mfc_output_dpb_size_ + kDpbOutputBufferExtraCount;
   reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
   reqbufs.memory = V4L2_MEMORY_DMABUF;
   IOCTL_OR_ERROR_RETURN_FALSE(gsc_fd_, VIDIOC_REQBUFS, &reqbufs);
diff --git a/content/common/gpu/media/exynos_video_decode_accelerator.h b/content/common/gpu/media/exynos_video_decode_accelerator.h
index 920af68..0eb3299 100644
--- a/content/common/gpu/media/exynos_video_decode_accelerator.h
+++ b/content/common/gpu/media/exynos_video_decode_accelerator.h
@@ -86,10 +86,17 @@
   // These are rather subjectively tuned.
   enum {
     kMfcInputBufferCount = 8,
-    kMfcOutputBufferExtraCount = 5,  // number of buffers above request by V4L2.
     kMfcInputBufferMaxSize = 512 * 1024,
-    kGscInputBufferCount = 6,
-    kGscOutputBufferCount = 6,
+    kGscInputBufferCount = 4,
+    // Number of output buffers to use for each VDA stage above what's required
+    // by the decoder (e.g. DPB size, in H264).
+    kDpbOutputBufferExtraCount = 3,
+    // We're continuing to have issues with synchronization between Mali 3D and
+    // Exynos video decode, so we buffer this many extra GSC output buffers in
+    // the GSC free output buffers queue, to add a safety margin.
+    // Must be lesser than or equal to kDpbOutputBufferExtraCount.
+    // TODO(sheu): remove this hack (http://crbug.com/225563).
+    kGscOutputBufferExtraForSyncCount = 2,
   };
 
   // Internal state of the decoder.
@@ -367,6 +374,8 @@
   // Required size of MFC output buffers.  Two sizes for two planes.
   size_t mfc_output_buffer_size_[2];
   uint32 mfc_output_buffer_pixelformat_;
+  // Required size of DPB for decoding.
+  int mfc_output_dpb_size_;
 
   // Completed MFC outputs, waiting for GSC.
   std::list<int> mfc_output_gsc_input_queue_;
diff --git a/content/common/gpu/media/gpu_video_decode_accelerator.cc b/content/common/gpu/media/gpu_video_decode_accelerator.cc
index 7e51777..251e202 100644
--- a/content/common/gpu/media/gpu_video_decode_accelerator.cc
+++ b/content/common/gpu/media/gpu_video_decode_accelerator.cc
@@ -29,9 +29,6 @@
 #elif defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY) && defined(USE_X11)
 #include "ui/gl/gl_context_glx.h"
 #include "content/common/gpu/media/vaapi_video_decode_accelerator.h"
-#elif defined(OS_MACOSX)
-#include "gpu/command_buffer/service/texture_manager.h"
-#include "content/common/gpu/media/mac_video_decode_accelerator.h"
 #elif defined(OS_ANDROID)
 #include "content/common/gpu/media/android_video_decode_accelerator.h"
 #endif
@@ -63,28 +60,28 @@
     GpuCommandBufferStub* stub)
     : init_done_msg_(NULL),
       host_route_id_(host_route_id),
-      stub_(stub->AsWeakPtr()),
+      stub_(stub),
       video_decode_accelerator_(NULL),
       texture_target_(0) {
-  if (!stub_)
-    return;
+  DCHECK(stub_);
   stub_->AddDestructionObserver(this);
+  stub_->channel()->AddRoute(host_route_id_, this);
   make_context_current_ =
       base::Bind(&MakeDecoderContextCurrent, stub_->AsWeakPtr());
 }
 
 GpuVideoDecodeAccelerator::~GpuVideoDecodeAccelerator() {
-  if (stub_) {
-    stub_->channel()->RemoveRoute(host_route_id_);
-    stub_->RemoveDestructionObserver(this);
-  }
-
-  if (video_decode_accelerator_.get())
+  DCHECK(stub_);
+  if (video_decode_accelerator_)
     video_decode_accelerator_.release()->Destroy();
+
+  stub_->channel()->RemoveRoute(host_route_id_);
+  stub_->RemoveDestructionObserver(this);
 }
 
 bool GpuVideoDecodeAccelerator::OnMessageReceived(const IPC::Message& msg) {
-  if (!stub_ || !video_decode_accelerator_.get())
+  DCHECK(stub_);
+  if (!video_decode_accelerator_)
     return false;
   bool handled = true;
   IPC_BEGIN_MESSAGE_MAP(GpuVideoDecodeAccelerator, msg)
@@ -156,14 +153,11 @@
 void GpuVideoDecodeAccelerator::Initialize(
     const media::VideoCodecProfile profile,
     IPC::Message* init_done_msg) {
+  DCHECK(stub_);
   DCHECK(!video_decode_accelerator_.get());
   DCHECK(!init_done_msg_);
   DCHECK(init_done_msg);
   init_done_msg_ = init_done_msg;
-  if (!stub_)
-    return;
-
-  stub_->channel()->AddRoute(host_route_id_, this);
 
 #if !defined(OS_WIN)
   // Ensure we will be able to get a GL context at all before initializing
@@ -205,11 +199,6 @@
   video_decode_accelerator_.reset(new VaapiVideoDecodeAccelerator(
       glx_context->display(), glx_context_handle, this,
       make_context_current_));
-#elif defined(OS_MACOSX)
-  video_decode_accelerator_.reset(new MacVideoDecodeAccelerator(
-      static_cast<CGLContextObj>(
-          stub_->decoder()->GetGLContext()->GetHandle()),
-      this));
 #elif defined(OS_ANDROID)
   video_decode_accelerator_.reset(new AndroidVideoDecodeAccelerator(
       this,
@@ -240,6 +229,7 @@
       const std::vector<int32>& buffer_ids,
       const std::vector<uint32>& texture_ids,
       const std::vector<gfx::Size>& sizes) {
+  DCHECK(stub_);
   if (buffer_ids.size() != texture_ids.size() ||
       buffer_ids.size() != sizes.size()) {
     NotifyError(media::VideoDecodeAccelerator::INVALID_ARGUMENT);
@@ -316,7 +306,7 @@
 
 void GpuVideoDecodeAccelerator::OnDestroy() {
   DCHECK(video_decode_accelerator_.get());
-  video_decode_accelerator_.release()->Destroy();
+  delete this;
 }
 
 void GpuVideoDecodeAccelerator::NotifyEndOfBitstreamBuffer(
@@ -347,14 +337,8 @@
     DLOG(ERROR) << "Send(AcceleratedVideoDecoderHostMsg_ResetDone) failed";
 }
 
-void GpuVideoDecodeAccelerator::OnWillDestroyStub(GpuCommandBufferStub* stub) {
-  DCHECK_EQ(stub, stub_.get());
-  if (video_decode_accelerator_.get())
-    video_decode_accelerator_.release()->Destroy();
-  if (stub_) {
-    stub_->RemoveDestructionObserver(this);
-    stub_.reset();
-  }
+void GpuVideoDecodeAccelerator::OnWillDestroyStub() {
+  delete this;
 }
 
 bool GpuVideoDecodeAccelerator::Send(IPC::Message* message) {
diff --git a/content/common/gpu/media/gpu_video_decode_accelerator.h b/content/common/gpu/media/gpu_video_decode_accelerator.h
index 52d0417..91f1b7c 100644
--- a/content/common/gpu/media/gpu_video_decode_accelerator.h
+++ b/content/common/gpu/media/gpu_video_decode_accelerator.h
@@ -45,7 +45,7 @@
   virtual void NotifyResetDone() OVERRIDE;
 
   // GpuCommandBufferStub::DestructionObserver implementation.
-  virtual void OnWillDestroyStub(GpuCommandBufferStub* stub) OVERRIDE;
+  virtual void OnWillDestroyStub() OVERRIDE;
 
   // Function to delegate sending to actual sender.
   virtual bool Send(IPC::Message* message) OVERRIDE;
@@ -79,7 +79,7 @@
   int32 host_route_id_;
 
   // Unowned pointer to the underlying GpuCommandBufferStub.
-  base::WeakPtr<GpuCommandBufferStub> stub_;
+  GpuCommandBufferStub* stub_;
 
   // The underlying VideoDecodeAccelerator.
   scoped_ptr<media::VideoDecodeAccelerator> video_decode_accelerator_;
diff --git a/content/common/gpu/media/mac_video_decode_accelerator.h b/content/common/gpu/media/mac_video_decode_accelerator.h
deleted file mode 100644
index 3582f10..0000000
--- a/content/common/gpu/media/mac_video_decode_accelerator.h
+++ /dev/null
@@ -1,137 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_COMMON_GPU_MEDIA_MAC_VIDEO_DECODE_ACCELERATOR_H_
-#define CONTENT_COMMON_GPU_MEDIA_MAC_VIDEO_DECODE_ACCELERATOR_H_
-
-#include <CoreVideo/CoreVideo.h>
-#include <map>
-#include <list>
-
-#include "base/mac/scoped_cftyperef.h"
-#include "base/memory/ref_counted.h"
-#include "base/threading/non_thread_safe.h"
-#include "content/common/content_export.h"
-#include "content/common/gpu/media/avc_config_record_builder.h"
-#include "content/common/gpu/media/h264_parser.h"
-#include "media/video/video_decode_accelerator.h"
-
-namespace base {
-class RefCountedBytes;
-}
-namespace gfx {
-class GLContext;
-class VideoDecodeAccelerationSupport;
-}
-
-namespace content {
-
-class GpuCommandBufferStub;
-
-class CONTENT_EXPORT MacVideoDecodeAccelerator
-    : public media::VideoDecodeAccelerator,
-      public base::NonThreadSafe {
- public:
-  // Does not take ownership of |client| which must outlive |*this|.
-  MacVideoDecodeAccelerator(CGLContextObj cgl_context,
-                            media::VideoDecodeAccelerator::Client* client);
-  virtual ~MacVideoDecodeAccelerator();
-
-  // media::VideoDecodeAccelerator implementation.
-  virtual bool Initialize(media::VideoCodecProfile profile) OVERRIDE;
-  virtual void Decode(const media::BitstreamBuffer& bitstream_buffer) OVERRIDE;
-  virtual void AssignPictureBuffers(
-      const std::vector<media::PictureBuffer>& buffers) OVERRIDE;
-  virtual void ReusePictureBuffer(int32 picture_buffer_id) OVERRIDE;
-  virtual void Flush() OVERRIDE;
-  virtual void Reset() OVERRIDE;
-  virtual void Destroy() OVERRIDE;
-
- private:
-
-  // Callback for a completed frame.
-  void OnFrameReady(int32 bitstream_buffer_id,
-                    scoped_refptr<base::RefCountedBytes> bytes,
-                    CVImageBufferRef image,
-                    int status);
-
-  // Sends available decoded frames to the client.
-  void SendImages();
-
-  // Stop the component when any error is detected.
-  void StopOnError(media::VideoDecodeAccelerator::Error error);
-
-  // Create the decoder.
-  bool CreateDecoder(const std::vector<uint8_t>& extra_data);
-
-  // Send the given NALU to the decoder.
-  void DecodeNALU(const H264NALU& nalu, int32 bitstream_buffer_id);
-
-  // Calls the client's initialize completed callback.
-  void NotifyInitializeDone();
-
-  // Requests pictures from the client.
-  void RequestPictures();
-
-  // Calls the client's flush completed callback.
-  void NotifyFlushDone();
-
-  // Calls the client's reset completed callback.
-  void NotifyResetDone();
-
-  // Notifies the client that the input buffer identifed by |input_buffer_id|
-  // has been processed.
-  void NotifyInputBufferRead(int input_buffer_id);
-
-  // Helper for Destroy(), doing all the actual work except for deleting self.
-  void Cleanup();
-
-  // To expose client callbacks from VideoDecodeAccelerator.
-  Client* client_;
-  // C++ wrapper around the Mac VDA API.
-  scoped_refptr<gfx::VideoDecodeAccelerationSupport> vda_support_;
-  // Picture buffers that are available for use by the decoder to draw decoded
-  // video frames on.
-  std::list<media::PictureBuffer> available_pictures_;
-
-  // Maps ids to picture buffers that are in use by the client.
-  struct UsedPictureInfo {
-    UsedPictureInfo(const media::PictureBuffer& pic,
-                    const base::mac::ScopedCFTypeRef<CVImageBufferRef>& image);
-    ~UsedPictureInfo();
-    const media::PictureBuffer picture_buffer;
-    const base::mac::ScopedCFTypeRef<CVImageBufferRef> image;
-  };
-  std::map<int32, UsedPictureInfo> used_pictures_;
-
-  // List of decoded images waiting to be sent to the client.
-  struct DecodedImageInfo {
-    DecodedImageInfo();
-    ~DecodedImageInfo();
-    base::mac::ScopedCFTypeRef<CVImageBufferRef> image;
-    int32 bitstream_buffer_id;
-  };
-  std::list<DecodedImageInfo> decoded_images_;
-
-  // The context to use to perform OpenGL operations.
-  CGLContextObj cgl_context_;
-
-  // Flag to check if AVC decoder configuration record has been built.
-  bool did_build_config_record_;
-
-  // Parser for the H264 stream.
-  H264Parser h264_parser_;
-
-  // Utility to build the AVC configuration record.
-  AVCConfigRecordBuilder config_record_builder_;
-
-  // Maps a bitstream ID to the number of NALUs that are being decoded for
-  // that bitstream. This is used to ensure that NotifyEndOfBitstreamBuffer()
-  // is called after all NALUs contained in a bitstream have been decoded.
-  std::map<int32, int> bitstream_nalu_count_;
-};
-
-}  // namespace content
-
-#endif  // CONTENT_COMMON_GPU_MEDIA_VIDEO_DECODE_ACCELERATOR_MAC_H_
diff --git a/content/common/gpu/media/mac_video_decode_accelerator.mm b/content/common/gpu/media/mac_video_decode_accelerator.mm
deleted file mode 100644
index cfc3077..0000000
--- a/content/common/gpu/media/mac_video_decode_accelerator.mm
+++ /dev/null
@@ -1,390 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/common/gpu/media/mac_video_decode_accelerator.h"
-
-#include "base/bind.h"
-#include "base/files/file_path.h"
-#include "base/location.h"
-#import "base/mac/foundation_util.h"
-#import "base/memory/ref_counted_memory.h"
-#import "base/message_loop.h"
-#include "base/native_library.h"
-#include "ui/gfx/video_decode_acceleration_support_mac.h"
-#include "ui/surface/io_surface_support_mac.h"
-
-namespace content {
-
-// Helper macros for dealing with failure.  If |result| evaluates false, emit
-// |log| to ERROR, register |error| with the decoder, and return |ret_val|
-// (which may be omitted for functions that return void).
-#define RETURN_ON_FAILURE(result, log, error, ret_val)             \
-  do {                                                             \
-    if (!(result)) {                                               \
-      DLOG(ERROR) << log;                                          \
-      StopOnError(error);                                          \
-      return ret_val;                                              \
-    }                                                              \
-  } while (0)
-
-namespace {
-
-enum { kNumPictureBuffers = 4 };
-
-class ScopedContextSetter {
- public:
-  ScopedContextSetter(CGLContextObj context)
-      : old_context_(NULL),
-        did_succeed_(false) {
-    old_context_ = CGLGetCurrentContext();
-    did_succeed_ = CGLSetCurrentContext(context) == kCGLNoError;
-  }
-
-  ~ScopedContextSetter() {
-    if (did_succeed_)
-      CGLSetCurrentContext(old_context_);
-  }
-
-  bool did_succeed() const {
-    return did_succeed_;
-  }
-
- private:
-  CGLContextObj old_context_;
-  bool did_succeed_;
-};
-
-}  // namespace
-
-static bool BindImageToTexture(CGLContextObj context,
-                               CVImageBufferRef image,
-                               uint32 texture_id) {
-  ScopedContextSetter scoped_context_setter(context);
-  if (!scoped_context_setter.did_succeed()) {
-    DVLOG(1) << "Unable to set OpenGL context.";
-    return false;
-  }
-
-  IOSurfaceSupport* io_surface_support = IOSurfaceSupport::Initialize();
-  DCHECK(io_surface_support);
-
-  CFTypeRef io_surface =
-      io_surface_support->CVPixelBufferGetIOSurface(image);
-  if (!io_surface) {
-    DVLOG(1) << "Unable to get IOSurface for CVPixelBuffer.";
-    return false;
-  }
-
-  glEnable(GL_TEXTURE_RECTANGLE_ARB);
-  glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture_id);
-  if (io_surface_support->CGLTexImageIOSurface2D(
-          context,
-          GL_TEXTURE_RECTANGLE_ARB,
-          GL_RGB,
-          io_surface_support->IOSurfaceGetWidth(io_surface),
-          io_surface_support->IOSurfaceGetHeight(io_surface),
-          GL_YCBCR_422_APPLE,
-          GL_UNSIGNED_SHORT_8_8_APPLE,
-          io_surface,
-          0) != kCGLNoError) {
-    DVLOG(1) << "Failed to bind image to texture.";
-    return false;
-  }
-  return glGetError() == GL_NO_ERROR;
-}
-
-MacVideoDecodeAccelerator::MacVideoDecodeAccelerator(
-    CGLContextObj cgl_context, media::VideoDecodeAccelerator::Client* client)
-    : client_(client),
-      cgl_context_(cgl_context),
-      did_build_config_record_(false) {
-}
-
-bool MacVideoDecodeAccelerator::Initialize(media::VideoCodecProfile profile) {
-  DCHECK(CalledOnValidThread());
-
-  // MacVDA still fails on too many videos to be useful, even to users who
-  // ignore the GPU blacklist.  Fail unconditionally here until enough of
-  // crbug.com/133828's blockers are resolved.
-  if (true)
-    return false;
-
-  if (profile < media::H264PROFILE_MIN || profile > media::H264PROFILE_MAX)
-    return false;
-
-  IOSurfaceSupport* io_surface_support = IOSurfaceSupport::Initialize();
-  if (!io_surface_support)
-    return false;
-
-  MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
-      &MacVideoDecodeAccelerator::NotifyInitializeDone, base::AsWeakPtr(this)));
-  return true;
-}
-
-void MacVideoDecodeAccelerator::Decode(
-    const media::BitstreamBuffer& bitstream_buffer) {
-  DCHECK(CalledOnValidThread());
-  RETURN_ON_FAILURE(client_,
-                    "Call to Decode() during invalid state.", ILLEGAL_STATE,);
-
-  base::SharedMemory memory(bitstream_buffer.handle(), true);
-  RETURN_ON_FAILURE(memory.Map(bitstream_buffer.size()),
-                    "Failed to SharedMemory::Map().", UNREADABLE_INPUT,);
-
-  h264_parser_.SetStream(static_cast<const uint8_t*>(memory.memory()),
-                         bitstream_buffer.size());
-  while (true) {
-    H264NALU nalu;
-    H264Parser::Result result = h264_parser_.AdvanceToNextNALU(&nalu);
-    if (result == H264Parser::kEOStream) {
-      if (bitstream_nalu_count_.count(bitstream_buffer.id()) == 0) {
-        MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
-            &MacVideoDecodeAccelerator::NotifyInputBufferRead,
-            base::AsWeakPtr(this), bitstream_buffer.id()));
-      }
-      return;
-    }
-    RETURN_ON_FAILURE(result == H264Parser::kOk,
-                      "Unable to parse bitstream.", UNREADABLE_INPUT,);
-    if (!did_build_config_record_) {
-      std::vector<uint8_t> config_record;
-      RETURN_ON_FAILURE(config_record_builder_.ProcessNALU(&h264_parser_, nalu,
-                                                           &config_record),
-                        "Unable to build AVC configuraiton record.",
-                        UNREADABLE_INPUT,);
-      if (!config_record.empty()) {
-        did_build_config_record_ = true;
-        if (!CreateDecoder(config_record))
-          return;
-      }
-    }
-    // If the decoder has been created and this is a slice type then pass it
-    // to the decoder.
-    if (vda_support_.get() && nalu.nal_unit_type >= 1 &&
-        nalu.nal_unit_type <= 5) {
-      bitstream_nalu_count_[bitstream_buffer.id()]++;
-      DecodeNALU(nalu, bitstream_buffer.id());
-    }
-  }
-}
-
-void MacVideoDecodeAccelerator::AssignPictureBuffers(
-    const std::vector<media::PictureBuffer>& buffers) {
-  DCHECK(CalledOnValidThread());
-  RETURN_ON_FAILURE(client_,
-                    "Call to AssignPictureBuffers() during invalid state.",
-                    ILLEGAL_STATE,);
-  available_pictures_.insert(
-      available_pictures_.end(), buffers.begin(), buffers.end());
-  SendImages();
-}
-
-void MacVideoDecodeAccelerator::ReusePictureBuffer(int32 picture_buffer_id) {
-  DCHECK(CalledOnValidThread());
-  RETURN_ON_FAILURE(client_,
-                    "Call to ReusePictureBuffe() during invalid state.",
-                    ILLEGAL_STATE,);
-
-  std::map<int32, UsedPictureInfo>::iterator it =
-      used_pictures_.find(picture_buffer_id);
-  RETURN_ON_FAILURE(it != used_pictures_.end(),
-                    "Missing picture buffer id: " << picture_buffer_id,
-                    INVALID_ARGUMENT,);
-  UsedPictureInfo info = it->second;
-  used_pictures_.erase(it);
-  available_pictures_.push_back(info.picture_buffer);
-  SendImages();
-}
-
-void MacVideoDecodeAccelerator::Flush() {
-  DCHECK(CalledOnValidThread());
-  RETURN_ON_FAILURE(vda_support_,
-                    "Call to Flush() during invalid state.", ILLEGAL_STATE,);
-  vda_support_->Flush(true);
-  MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
-      &MacVideoDecodeAccelerator::NotifyFlushDone, base::AsWeakPtr(this)));
-}
-
-void MacVideoDecodeAccelerator::Reset() {
-  DCHECK(CalledOnValidThread());
-  RETURN_ON_FAILURE(vda_support_,
-                    "Call to Reset() during invalid state.", ILLEGAL_STATE,);
-  vda_support_->Flush(false);
-  MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
-      &MacVideoDecodeAccelerator::NotifyResetDone, base::AsWeakPtr(this)));
-}
-
-void MacVideoDecodeAccelerator::Cleanup() {
-  DCHECK(CalledOnValidThread());
-  if (vda_support_) {
-    vda_support_->Destroy();
-    vda_support_ = NULL;
-  }
-  client_ = NULL;
-  decoded_images_.clear();
-}
-
-void MacVideoDecodeAccelerator::Destroy() {
-  DCHECK(CalledOnValidThread());
-  Cleanup();
-  delete this;
-}
-
-MacVideoDecodeAccelerator::~MacVideoDecodeAccelerator() {
-  DCHECK(CalledOnValidThread());
-  DCHECK(!vda_support_);
-  DCHECK(!client_);
-  DCHECK(decoded_images_.empty());
-}
-
-void MacVideoDecodeAccelerator::OnFrameReady(
-    int32 bitstream_buffer_id,
-    scoped_refptr<base::RefCountedBytes> bytes,
-    CVImageBufferRef image,
-    int status) {
-  DCHECK(CalledOnValidThread());
-  RETURN_ON_FAILURE(status == noErr,
-                    "Decoding image failed with error code: " << status,
-                    PLATFORM_FAILURE,);
-  if (!client_)
-    return;
-  if (image) {
-    DecodedImageInfo info;
-    info.image.reset(image, base::scoped_policy::RETAIN);
-    info.bitstream_buffer_id = bitstream_buffer_id;
-    decoded_images_.push_back(info);
-    SendImages();
-  }
-  std::map<int32, int>::iterator bitstream_count_it =
-      bitstream_nalu_count_.find(bitstream_buffer_id);
-  if (--bitstream_count_it->second == 0) {
-    bitstream_nalu_count_.erase(bitstream_count_it);
-    MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
-        &MacVideoDecodeAccelerator::NotifyInputBufferRead,
-        base::AsWeakPtr(this), bitstream_buffer_id));
-  }
-}
-
-void MacVideoDecodeAccelerator::SendImages() {
-  if (!client_) {
-    DCHECK(decoded_images_.empty());
-    return;
-  }
-
-  while (available_pictures_.size() && decoded_images_.size()) {
-    DecodedImageInfo info = decoded_images_.front();
-    decoded_images_.pop_front();
-    media::PictureBuffer picture_buffer = available_pictures_.front();
-    available_pictures_.pop_front();
-
-    RETURN_ON_FAILURE(BindImageToTexture(
-        cgl_context_, info.image, picture_buffer.texture_id()),
-        "Error binding image to texture.", PLATFORM_FAILURE,);
-
-    used_pictures_.insert(std::make_pair(
-        picture_buffer.id(), UsedPictureInfo(picture_buffer, info.image)));
-    client_->PictureReady(
-        media::Picture(picture_buffer.id(), info.bitstream_buffer_id));
-  }
-}
-
-void MacVideoDecodeAccelerator::StopOnError(
-    media::VideoDecodeAccelerator::Error error) {
-  if (client_)
-    client_->NotifyError(error);
-  Cleanup();
-}
-
-bool MacVideoDecodeAccelerator::CreateDecoder(
-    const std::vector<uint8_t>& extra_data) {
-  DCHECK(client_);
-  DCHECK(!vda_support_.get());
-
-  vda_support_ = new gfx::VideoDecodeAccelerationSupport();
-  gfx::VideoDecodeAccelerationSupport::Status status = vda_support_->Create(
-      config_record_builder_.coded_width(),
-      config_record_builder_.coded_height(),
-      kCVPixelFormatType_422YpCbCr8,
-      &extra_data[0], extra_data.size());
-  RETURN_ON_FAILURE(status == gfx::VideoDecodeAccelerationSupport::SUCCESS,
-                    "Creating video decoder failed with error: " << status,
-                    PLATFORM_FAILURE, false);
-
-  MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
-      &MacVideoDecodeAccelerator::RequestPictures, base::AsWeakPtr(this)));
-  return true;
-}
-
-void MacVideoDecodeAccelerator::DecodeNALU(const H264NALU& nalu,
-                                           int32 bitstream_buffer_id) {
-  // Assume the NALU length field size is 4 bytes.
-  const int kNALULengthFieldSize = 4;
-  std::vector<uint8_t> data(kNALULengthFieldSize + nalu.size);
-
-  // Store the buffer size at the beginning of the buffer as the decoder
-  // expects.
-  for (size_t i = 0; i < kNALULengthFieldSize; ++i) {
-    size_t shift = kNALULengthFieldSize * 8 - (i + 1) * 8;
-    data[i] = (nalu.size >> shift) & 0xff;
-  }
-
-  // Copy the NALU data.
-  memcpy(&data[kNALULengthFieldSize], nalu.data, nalu.size);
-
-  // Keep a ref counted copy of the buffer.
-  scoped_refptr<base::RefCountedBytes> bytes(
-      base::RefCountedBytes::TakeVector(&data));
-  vda_support_->Decode(bytes->front(), bytes->size(), base::Bind(
-      &MacVideoDecodeAccelerator::OnFrameReady,
-      base::AsWeakPtr(this), bitstream_buffer_id, bytes));
-}
-
-void MacVideoDecodeAccelerator::NotifyInitializeDone() {
-  if (client_)
-    client_->NotifyInitializeDone();
-}
-
-void MacVideoDecodeAccelerator::RequestPictures() {
-  if (client_) {
-    client_->ProvidePictureBuffers(
-        kNumPictureBuffers,
-        gfx::Size(config_record_builder_.coded_width(),
-                  config_record_builder_.coded_height()),
-        GL_TEXTURE_RECTANGLE_ARB);
-  }
-}
-
-void MacVideoDecodeAccelerator::NotifyFlushDone() {
-  if (client_)
-    client_->NotifyFlushDone();
-}
-
-void MacVideoDecodeAccelerator::NotifyResetDone() {
-  decoded_images_.clear();
-  if (client_)
-    client_->NotifyResetDone();
-}
-
-void MacVideoDecodeAccelerator::NotifyInputBufferRead(int input_buffer_id) {
-  if (client_)
-    client_->NotifyEndOfBitstreamBuffer(input_buffer_id);
-}
-
-MacVideoDecodeAccelerator::UsedPictureInfo::UsedPictureInfo(
-    const media::PictureBuffer& pic,
-    const base::mac::ScopedCFTypeRef<CVImageBufferRef>& image)
-    : picture_buffer(pic),
-      image(image, base::scoped_policy::RETAIN) {
-}
-
-MacVideoDecodeAccelerator::UsedPictureInfo::~UsedPictureInfo() {
-}
-
-MacVideoDecodeAccelerator::DecodedImageInfo::DecodedImageInfo() {
-}
-
-MacVideoDecodeAccelerator::DecodedImageInfo::~DecodedImageInfo() {
-}
-
-}  // namespace content
diff --git a/content/common/gpu/media/omx_video_decode_accelerator.cc b/content/common/gpu/media/omx_video_decode_accelerator.cc
index 06897a8..929b711 100644
--- a/content/common/gpu/media/omx_video_decode_accelerator.cc
+++ b/content/common/gpu/media/omx_video_decode_accelerator.cc
@@ -135,7 +135,7 @@
     EGLDisplay egl_display, EGLContext egl_context,
     media::VideoDecodeAccelerator::Client* client,
     const base::Callback<bool(void)>& make_context_current)
-    : message_loop_(MessageLoop::current()),
+    : message_loop_(base::MessageLoop::current()),
       component_handle_(NULL),
       weak_this_(base::AsWeakPtr(this)),
       init_begun_(false),
@@ -150,7 +150,8 @@
       egl_display_(egl_display),
       egl_context_(egl_context),
       make_context_current_(make_context_current),
-      client_(client),
+      client_ptr_factory_(client),
+      client_(client_ptr_factory_.GetWeakPtr()),
       codec_(UNKNOWN),
       h264_profile_(OMX_VIDEO_AVCProfileMax),
       component_name_is_nvidia_(false) {
@@ -162,7 +163,7 @@
 }
 
 OmxVideoDecodeAccelerator::~OmxVideoDecodeAccelerator() {
-  DCHECK_EQ(message_loop_, MessageLoop::current());
+  DCHECK_EQ(message_loop_, base::MessageLoop::current());
   DCHECK(free_input_buffers_.empty());
   DCHECK_EQ(0, input_buffers_at_component_);
   DCHECK_EQ(0, output_buffers_at_component_);
@@ -178,7 +179,7 @@
 }
 
 bool OmxVideoDecodeAccelerator::Initialize(media::VideoCodecProfile profile) {
-  DCHECK_EQ(message_loop_, MessageLoop::current());
+  DCHECK_EQ(message_loop_, base::MessageLoop::current());
 
   if (profile >= media::H264PROFILE_MIN && profile <= media::H264PROFILE_MAX) {
     codec_ = H264;
@@ -219,7 +220,7 @@
 }
 
 bool OmxVideoDecodeAccelerator::CreateComponent() {
-  DCHECK_EQ(message_loop_, MessageLoop::current());
+  DCHECK_EQ(message_loop_, base::MessageLoop::current());
   OMX_CALLBACKTYPE omx_accelerator_callbacks = {
     &OmxVideoDecodeAccelerator::EventHandler,
     &OmxVideoDecodeAccelerator::EmptyBufferCallback,
@@ -332,7 +333,7 @@
     const media::BitstreamBuffer& bitstream_buffer) {
   TRACE_EVENT1("Video Decoder", "OVDA::Decode",
                "Buffer id", bitstream_buffer.id());
-  DCHECK_EQ(message_loop_, MessageLoop::current());
+  DCHECK_EQ(message_loop_, base::MessageLoop::current());
 
   if (current_state_change_ == RESETTING ||
       !queued_bitstream_buffers_.empty() ||
@@ -395,7 +396,7 @@
 
 void OmxVideoDecodeAccelerator::AssignPictureBuffers(
     const std::vector<media::PictureBuffer>& buffers) {
-  DCHECK_EQ(message_loop_, MessageLoop::current());
+  DCHECK_EQ(message_loop_, base::MessageLoop::current());
 
   // If we are resetting/destroying/erroring, don't bother, as
   // OMX_FillThisBuffer will fail anyway. In case we're in the middle of
@@ -408,6 +409,9 @@
     return;
 
   RETURN_ON_FAILURE(CanFillBuffer(), "Can't fill buffer", ILLEGAL_STATE,);
+  RETURN_ON_FAILURE((kNumPictureBuffers == buffers.size()),
+      "Failed to provide requested picture buffers. (Got " << buffers.size() <<
+      ", requested " << kNumPictureBuffers << ")", INVALID_ARGUMENT,);
 
   DCHECK_EQ(output_buffers_at_component_, 0);
   DCHECK_EQ(fake_output_buffers_.size(), 0U);
@@ -426,10 +430,6 @@
         buffers[i].id(), OutputPicture(buffers[i], NULL, egl_image))).second);
   }
 
-  if (pictures_.size() < kNumPictureBuffers)
-    return;  // get all the buffers first.
-  DCHECK_EQ(pictures_.size(), kNumPictureBuffers);
-
   // These do their own RETURN_ON_FAILURE dances.
   if (!AllocateOutputBuffers())
     return;
@@ -438,7 +438,7 @@
 }
 
 void OmxVideoDecodeAccelerator::ReusePictureBuffer(int32 picture_buffer_id) {
-  DCHECK_EQ(message_loop_, MessageLoop::current());
+  DCHECK_EQ(message_loop_, base::MessageLoop::current());
   TRACE_EVENT1("Video Decoder", "OVDA::ReusePictureBuffer",
                "Picture id", picture_buffer_id);
   scoped_ptr<PictureSyncObject> egl_sync_obj(
@@ -451,14 +451,14 @@
 void OmxVideoDecodeAccelerator::CheckPictureStatus(
     int32 picture_buffer_id,
     scoped_ptr<PictureSyncObject> egl_sync_obj) {
-  DCHECK_EQ(message_loop_, MessageLoop::current());
+  DCHECK_EQ(message_loop_, base::MessageLoop::current());
 
   // It's possible for this task to never run if the message loop is
   // stopped. In that case we may never call QueuePictureBuffer().
   // This is fine though, because all pictures, irrespective of their state,
   // are in pictures_ map and that's what will be used to do the clean up.
   if (!egl_sync_obj->IsSynced()) {
-    MessageLoop::current()->PostDelayedTask(FROM_HERE, base::Bind(
+    base::MessageLoop::current()->PostDelayedTask(FROM_HERE, base::Bind(
         &OmxVideoDecodeAccelerator::CheckPictureStatus, weak_this_,
         picture_buffer_id, base::Passed(&egl_sync_obj)),
         base::TimeDelta::FromMilliseconds(kSyncPollDelayMs));
@@ -470,7 +470,7 @@
 }
 
 void OmxVideoDecodeAccelerator::QueuePictureBuffer(int32 picture_buffer_id) {
-  DCHECK_EQ(message_loop_, MessageLoop::current());
+  DCHECK_EQ(message_loop_, base::MessageLoop::current());
 
   // During port-flushing, do not call OMX FillThisBuffer.
   if (current_state_change_ == RESETTING) {
@@ -498,7 +498,7 @@
 }
 
 void OmxVideoDecodeAccelerator::Flush() {
-  DCHECK_EQ(message_loop_, MessageLoop::current());
+  DCHECK_EQ(message_loop_, base::MessageLoop::current());
   DCHECK_EQ(current_state_change_, NO_TRANSITION);
   DCHECK_EQ(client_state_, OMX_StateExecuting);
   current_state_change_ = FLUSHING;
@@ -507,7 +507,7 @@
 }
 
 void OmxVideoDecodeAccelerator::OnReachedEOSInFlushing() {
-  DCHECK_EQ(message_loop_, MessageLoop::current());
+  DCHECK_EQ(message_loop_, base::MessageLoop::current());
   DCHECK_EQ(client_state_, OMX_StateExecuting);
   current_state_change_ = NO_TRANSITION;
   if (client_)
@@ -515,7 +515,7 @@
 }
 
 void OmxVideoDecodeAccelerator::FlushIOPorts() {
-  DCHECK_EQ(message_loop_, MessageLoop::current());
+  DCHECK_EQ(message_loop_, base::MessageLoop::current());
 
   // Flush input port first.
   if (!SendCommandToPort(OMX_CommandFlush, input_port_))
@@ -523,20 +523,20 @@
 }
 
 void OmxVideoDecodeAccelerator::InputPortFlushDone() {
-  DCHECK_EQ(message_loop_, MessageLoop::current());
+  DCHECK_EQ(message_loop_, base::MessageLoop::current());
   DCHECK_EQ(input_buffers_at_component_, 0);
   if (!SendCommandToPort(OMX_CommandFlush, output_port_))
     return;
 }
 
 void OmxVideoDecodeAccelerator::OutputPortFlushDone() {
-  DCHECK_EQ(message_loop_, MessageLoop::current());
+  DCHECK_EQ(message_loop_, base::MessageLoop::current());
   DCHECK_EQ(output_buffers_at_component_, 0);
   BeginTransitionToState(OMX_StateExecuting);
 }
 
 void OmxVideoDecodeAccelerator::Reset() {
-  DCHECK_EQ(message_loop_, MessageLoop::current());
+  DCHECK_EQ(message_loop_, base::MessageLoop::current());
   DCHECK_EQ(current_state_change_, NO_TRANSITION);
   DCHECK_EQ(client_state_, OMX_StateExecuting);
   current_state_change_ = RESETTING;
@@ -544,9 +544,10 @@
 }
 
 void OmxVideoDecodeAccelerator::Destroy() {
-  DCHECK_EQ(message_loop_, MessageLoop::current());
+  DCHECK_EQ(message_loop_, base::MessageLoop::current());
 
   scoped_ptr<OmxVideoDecodeAccelerator> deleter(this);
+  client_ptr_factory_.InvalidateWeakPtrs();
 
   if (current_state_change_ == ERRORING ||
       current_state_change_ == DESTROYING) {
@@ -569,14 +570,13 @@
          client_state_ == OMX_StateIdle ||
          client_state_ == OMX_StatePause);
   current_state_change_ = DESTROYING;
-  client_ = NULL;
   BeginTransitionToState(OMX_StateIdle);
   BusyLoopInDestroying(deleter.Pass());
 }
 
 void OmxVideoDecodeAccelerator::BeginTransitionToState(
     OMX_STATETYPE new_state) {
-  DCHECK_EQ(message_loop_, MessageLoop::current());
+  DCHECK_EQ(message_loop_, base::MessageLoop::current());
   if (new_state != OMX_StateInvalid)
     DCHECK_NE(current_state_change_, NO_TRANSITION);
   if (current_state_change_ == ERRORING)
@@ -696,7 +696,7 @@
   // Can't use PostDelayedTask here because MessageLoop doesn't drain delayed
   // tasks.  Instead we sleep for 5ms.  Really.
   base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(5));
-  MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
+  base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
       &OmxVideoDecodeAccelerator::BusyLoopInDestroying,
       base::Unretained(this), base::Passed(&self)));
 }
@@ -741,14 +741,14 @@
 
 void OmxVideoDecodeAccelerator::StopOnError(
     media::VideoDecodeAccelerator::Error error) {
-  DCHECK_EQ(message_loop_, MessageLoop::current());
+  DCHECK_EQ(message_loop_, base::MessageLoop::current());
 
   if (current_state_change_ == ERRORING)
     return;
 
   if (client_ && init_begun_)
     client_->NotifyError(error);
-  client_ = NULL;
+  client_ptr_factory_.InvalidateWeakPtrs();
 
   if (client_state_ == OMX_StateInvalid || client_state_ == OMX_StateMax)
       return;
@@ -758,7 +758,7 @@
 }
 
 bool OmxVideoDecodeAccelerator::AllocateInputBuffers() {
-  DCHECK_EQ(message_loop_, MessageLoop::current());
+  DCHECK_EQ(message_loop_, base::MessageLoop::current());
   for (int i = 0; i < input_buffer_count_; ++i) {
     OMX_BUFFERHEADERTYPE* buffer;
     // While registering the buffer header we use fake buffer information
@@ -798,7 +798,7 @@
 }
 
 bool OmxVideoDecodeAccelerator::AllocateOutputBuffers() {
-  DCHECK_EQ(message_loop_, MessageLoop::current());
+  DCHECK_EQ(message_loop_, base::MessageLoop::current());
 
   DCHECK(!pictures_.empty());
   for (OutputPictureById::iterator it = pictures_.begin();
@@ -820,7 +820,7 @@
 }
 
 void OmxVideoDecodeAccelerator::FreeOMXBuffers() {
-  DCHECK_EQ(message_loop_, MessageLoop::current());
+  DCHECK_EQ(message_loop_, base::MessageLoop::current());
   bool failure_seen = false;
   while (!free_input_buffers_.empty()) {
     OMX_BUFFERHEADERTYPE* omx_buffer = free_input_buffers_.front();
@@ -865,15 +865,17 @@
   fake_output_buffers_.clear();
 
   // Dequeue pending queued_picture_buffer_ids_
-  for (size_t i = 0; i < queued_picture_buffer_ids_.size(); ++i)
-    client_->DismissPictureBuffer(queued_picture_buffer_ids_[i]);
+  if (client_) {
+    for (size_t i = 0; i < queued_picture_buffer_ids_.size(); ++i)
+      client_->DismissPictureBuffer(queued_picture_buffer_ids_[i]);
+  }
   queued_picture_buffer_ids_.clear();
 
   RETURN_ON_FAILURE(!failure_seen, "OMX_FreeBuffer", PLATFORM_FAILURE,);
 }
 
 void OmxVideoDecodeAccelerator::OnOutputPortDisabled() {
-  DCHECK_EQ(message_loop_, MessageLoop::current());
+  DCHECK_EQ(message_loop_, base::MessageLoop::current());
   OMX_PARAM_PORTDEFINITIONTYPE port_format;
   InitParam(*this, &port_format);
   port_format.nPortIndex = output_port_;
@@ -901,7 +903,7 @@
 }
 
 void OmxVideoDecodeAccelerator::OnOutputPortEnabled() {
-  DCHECK_EQ(message_loop_, MessageLoop::current());
+  DCHECK_EQ(message_loop_, base::MessageLoop::current());
 
   if (current_state_change_ == RESETTING) {
     for (OutputPictureById::iterator it = pictures_.begin();
@@ -940,7 +942,7 @@
   TRACE_EVENT2("Video Decoder", "OVDA::FillBufferDoneTask",
                "Buffer id", buffer->nTimeStamp,
                "Picture id", picture_buffer_id);
-  DCHECK_EQ(message_loop_, MessageLoop::current());
+  DCHECK_EQ(message_loop_, base::MessageLoop::current());
   DCHECK_GT(output_buffers_at_component_, 0);
   --output_buffers_at_component_;
 
@@ -989,7 +991,7 @@
     OMX_BUFFERHEADERTYPE* buffer) {
   TRACE_EVENT1("Video Decoder", "OVDA::EmptyBufferDoneTask",
                "Buffer id", buffer->nTimeStamp);
-  DCHECK_EQ(message_loop_, MessageLoop::current());
+  DCHECK_EQ(message_loop_, base::MessageLoop::current());
   DCHECK_GT(input_buffers_at_component_, 0);
   free_input_buffers_.push(buffer);
   input_buffers_at_component_--;
@@ -1010,7 +1012,7 @@
 }
 
 void OmxVideoDecodeAccelerator::DispatchStateReached(OMX_STATETYPE reached) {
-  DCHECK_EQ(message_loop_, MessageLoop::current());
+  DCHECK_EQ(message_loop_, base::MessageLoop::current());
   switch (current_state_change_) {
     case INITIALIZING:
       switch (reached) {
@@ -1074,7 +1076,7 @@
 void OmxVideoDecodeAccelerator::EventHandlerCompleteTask(OMX_EVENTTYPE event,
                                                          OMX_U32 data1,
                                                          OMX_U32 data2) {
-  DCHECK_EQ(message_loop_, MessageLoop::current());
+  DCHECK_EQ(message_loop_, base::MessageLoop::current());
   switch (event) {
     case OMX_EventCmdComplete:
       switch (data1) {
@@ -1237,7 +1239,7 @@
 }
 
 bool OmxVideoDecodeAccelerator::CanFillBuffer() {
-  DCHECK_EQ(message_loop_, MessageLoop::current());
+  DCHECK_EQ(message_loop_, base::MessageLoop::current());
   const CurrentStateChange csc = current_state_change_;
   const OMX_STATETYPE cs = client_state_;
   return (csc != DESTROYING && csc != ERRORING && csc != RESETTING) &&
@@ -1246,7 +1248,7 @@
 
 bool OmxVideoDecodeAccelerator::SendCommandToPort(
     OMX_COMMANDTYPE cmd, int port_index) {
-  DCHECK_EQ(message_loop_, MessageLoop::current());
+  DCHECK_EQ(message_loop_, base::MessageLoop::current());
   OMX_ERRORTYPE result = OMX_SendCommand(component_handle_,
                                          cmd, port_index, 0);
   RETURN_ON_OMX_FAILURE(result, "SendCommand() failed" << cmd,
diff --git a/content/common/gpu/media/omx_video_decode_accelerator.h b/content/common/gpu/media/omx_video_decode_accelerator.h
index 8855809..d57d3b1 100644
--- a/content/common/gpu/media/omx_video_decode_accelerator.h
+++ b/content/common/gpu/media/omx_video_decode_accelerator.h
@@ -94,7 +94,7 @@
   };
   typedef std::map<int32, OutputPicture> OutputPictureById;
 
-  MessageLoop* message_loop_;
+  base::MessageLoop* message_loop_;
   OMX_HANDLETYPE component_handle_;
 
   // Create the Component for OMX. Handles all OMX initialization.
@@ -206,8 +206,10 @@
   std::vector<int> queued_picture_buffer_ids_;
 
   // To expose client callbacks from VideoDecodeAccelerator.
-  // NOTE: all calls to this object *MUST* be executed in message_loop_.
-  Client* client_;
+  // NOTE: all calls to these objects *MUST* be executed on
+  // message_loop_.
+  base::WeakPtrFactory<Client> client_ptr_factory_;
+  base::WeakPtr<Client> client_;
 
   scoped_ptr<Gles2TextureToEglImageTranslator> texture_to_egl_image_translator_;
 
diff --git a/content/common/gpu/media/rendering_helper_gl.cc b/content/common/gpu/media/rendering_helper_gl.cc
index fc58a7e..dd32163 100644
--- a/content/common/gpu/media/rendering_helper_gl.cc
+++ b/content/common/gpu/media/rendering_helper_gl.cc
@@ -119,7 +119,7 @@
   void MakeCurrent(int window_id);
 
 
-  MessageLoop* message_loop_;
+  base::MessageLoop* message_loop_;
   std::vector<gfx::Size> dimensions_;
   bool suppress_swap_to_display_;
 
@@ -210,7 +210,7 @@
 
   CHECK_GT(dimensions.size(), 0U);
   dimensions_ = dimensions;
-  message_loop_ = MessageLoop::current();
+  message_loop_ = base::MessageLoop::current();
   CHECK_GT(num_windows, 0);
 
 #if GL_VARIANT_GLX
@@ -398,7 +398,7 @@
 }
 
 void RenderingHelperGL::UnInitialize(base::WaitableEvent* done) {
-  CHECK_EQ(MessageLoop::current(), message_loop_);
+  CHECK_EQ(base::MessageLoop::current(), message_loop_);
 #if GL_VARIANT_GLX
 
   glXDestroyContext(x_display_, gl_context_);
@@ -417,7 +417,7 @@
                                       uint32 texture_target,
                                       uint32* texture_id,
                                       base::WaitableEvent* done) {
-  if (MessageLoop::current() != message_loop_) {
+  if (base::MessageLoop::current() != message_loop_) {
     message_loop_->PostTask(
         FROM_HERE,
         base::Bind(&RenderingHelper::CreateTexture, base::Unretained(this),
@@ -444,7 +444,7 @@
 }
 
 void RenderingHelperGL::RenderTexture(uint32 texture_id) {
-  CHECK_EQ(MessageLoop::current(), message_loop_);
+  CHECK_EQ(base::MessageLoop::current(), message_loop_);
   size_t window_id = texture_id_to_surface_index_[texture_id];
   MakeCurrent(window_id);
   int dimensions_id = window_id % dimensions_.size();
diff --git a/content/common/gpu/media/rendering_helper_mac.mm b/content/common/gpu/media/rendering_helper_mac.mm
deleted file mode 100644
index a315791..0000000
--- a/content/common/gpu/media/rendering_helper_mac.mm
+++ /dev/null
@@ -1,222 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/common/gpu/media/rendering_helper.h"
-
-#import <Cocoa/Cocoa.h>
-#import <OpenGL/CGLMacro.h>
-
-#include "base/mac/scoped_nsautorelease_pool.h"
-#include "base/memory/scoped_nsobject.h"
-#include "base/message_loop.h"
-#include "base/synchronization/waitable_event.h"
-
-// Gets the pixel format to be used by the OpenGL view.
-static scoped_nsobject<NSOpenGLPixelFormat> GetPixelFormat() {
-  NSOpenGLPixelFormatAttribute attributes[] = {
-    NSOpenGLPFAWindow,
-    NSOpenGLPFADoubleBuffer,
-    NSOpenGLPFAAccelerated,
-    NSOpenGLPFANoRecovery,
-    NSOpenGLPFAColorSize, (NSOpenGLPixelFormatAttribute)32,
-    NSOpenGLPFAAlphaSize, (NSOpenGLPixelFormatAttribute)8,
-    NSOpenGLPFADepthSize, (NSOpenGLPixelFormatAttribute)24,
-    (NSOpenGLPixelFormatAttribute)0
-  };
-  return scoped_nsobject<NSOpenGLPixelFormat>(
-    [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes]);
-}
-
-// Gets the CGLContext from the given OpenGL view.
-static CGLContextObj GetCGLContext(NSOpenGLView* gl_view) {
-  return static_cast<CGLContextObj>([[gl_view openGLContext] CGLContextObj]);
-}
-
-// Sets up a view port for the OpenGL view.
-static void SetupGLViewPort(NSOpenGLView* gl_view, int width, int height) {
-  CGLContextObj cgl_ctx = GetCGLContext(gl_view);
-  glViewport(0, 0, width, height);
-  glClearColor(1.0, 0.0, 0.0, 0.0);
-  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-  [[gl_view openGLContext] flushBuffer];
-  CHECK_EQ(static_cast<int>(glGetError()), GL_NO_ERROR);
-}
-
-// Draw the given texture to the OpenGL view.
-static void DrawTexture(NSOpenGLView* gl_view,
-                        GLuint texture_id,
-                        bool suppress_swap_to_display) {
-  CGLContextObj cgl_ctx = GetCGLContext(gl_view);
-  [gl_view lockFocus];
-
-  GLfloat width = [gl_view bounds].size.width;
-  GLfloat height = [gl_view bounds].size.height;
-
-  glEnable(GL_TEXTURE_RECTANGLE_ARB);
-  glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture_id);
-  glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
-
-  glBegin(GL_QUADS);
-    glTexCoord2f(0.0, height);
-    glVertex3f(-1.0, -1.0, 0.0);
-    glTexCoord2f(width, height);
-    glVertex3f(1.0, -1.0, 0.0);
-    glTexCoord2f(width, 0.0);
-    glVertex3f(1.0, 1.0, 0.0);
-    glTexCoord2f(0.0, 0.0);
-    glVertex3f(-1.0, 1.0, 0.0);
-  glEnd();
-
-  glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
-  glDisable(GL_TEXTURE_RECTANGLE_ARB);
-
-  if (!suppress_swap_to_display)
-    [[gl_view openGLContext] flushBuffer];
-  [gl_view unlockFocus];
-  CHECK_EQ(static_cast<int>(glGetError()), GL_NO_ERROR);
-}
-
-namespace content {
-
-class RenderingHelperMac : public RenderingHelper {
- public:
-  RenderingHelperMac();
-  virtual ~RenderingHelperMac();
-
-  // Implement RenderingHelper.
-  virtual void Initialize(bool suppress_swap_to_display,
-                          int num_windows,
-                          const std::vector<gfx::Size>& dimensions,
-                          base::WaitableEvent* done) OVERRIDE;
-  virtual void UnInitialize(base::WaitableEvent* done) OVERRIDE;
-  virtual void CreateTexture(int window_id,
-                             uint32 texture_target,
-                             GLuint* texture_id,
-                             base::WaitableEvent* done) OVERRIDE;
-  virtual void RenderTexture(GLuint texture_id) OVERRIDE;
-  virtual void DeleteTexture(GLuint texture_id) OVERRIDE;
-  virtual void* GetGLContext() OVERRIDE;
-  virtual void* GetGLDisplay() OVERRIDE;
-
- private:
-  MessageLoop* message_loop_;
-  int width_;
-  int height_;
-  bool suppress_swap_to_display_;
-  scoped_nsobject<NSWindow> window_;
-  scoped_nsobject<NSOpenGLView> gl_view_;
-  base::mac::ScopedNSAutoreleasePool pool_;
-};
-
-// static
-RenderingHelper* RenderingHelper::Create() {
-  return new RenderingHelperMac;
-}
-
-// static
-void RenderingHelper::InitializePlatform() {
-  // Initialize the Cocoa framework.
-  base::mac::ScopedNSAutoreleasePool pool_;
-  [NSApplication sharedApplication];
-}
-
-RenderingHelperMac::RenderingHelperMac()
-    : message_loop_(NULL),
-      width_(0),
-      height_(0),
-      suppress_swap_to_display_(false) {
-}
-
-RenderingHelperMac::~RenderingHelperMac() {
-  CHECK_EQ(width_, 0) << "Must call UnInitialize before dtor.";
-}
-
-void RenderingHelperMac::Initialize(
-    bool suppress_swap_to_display,
-    int num_windows,
-    const std::vector<gfx::Size>& dimensions,
-    base::WaitableEvent* done) {
-  // Use width_ != 0 as a proxy for the class having already been
-  // Initialize()'d, and UnInitialize() before continuing.
-  if (width_) {
-    base::WaitableEvent done2(false, false);
-    UnInitialize(&done2);
-    done2.Wait();
-  }
-
-  // A separate window is created for each decoder. Since the Mac API
-  // only supports a single instance only one window should be created.
-  CHECK_EQ(num_windows, 1);
-
-  // There should be only one window dimension as only one window is created.
-  CHECK_EQ(dimensions.size(), 1U);
-  width_ = dimensions[0].width();
-  height_ = dimensions[0].height();
-  suppress_swap_to_display_ = suppress_swap_to_display;
-  message_loop_ = MessageLoop::current();
-
-  // Create a window to host the OpenGL contents.
-  NSRect rect = NSMakeRect(0, 0, width_, height_);
-  window_.reset([[NSWindow alloc]
-      initWithContentRect:rect
-                styleMask:NSTitledWindowMask
-                  backing:NSBackingStoreBuffered
-                    defer:NO]);
-  [window_ center];
-  [window_ makeKeyAndOrderFront:nil];
-
-  // Create an OpenGL view.
-  scoped_nsobject<NSOpenGLPixelFormat> pixel_format(GetPixelFormat());
-  gl_view_.reset([[NSOpenGLView alloc] initWithFrame:rect
-                                         pixelFormat:pixel_format]);
-  [[window_ contentView] addSubview:gl_view_];
-  SetupGLViewPort(gl_view_, width_, height_);
-
-  done->Signal();
-}
-
-void RenderingHelperMac::UnInitialize(base::WaitableEvent* done) {
-  CHECK_EQ(MessageLoop::current(), message_loop_);
-  width_ = 0;
-  height_ = 0;
-  message_loop_ = NULL;
-  [window_ close];
-  window_.reset();
-  gl_view_.reset();
-  done->Signal();
-}
-
-void RenderingHelperMac::CreateTexture(int window_id,
-                                       uint32 texture_target,
-                                       GLuint* texture_id,
-                                       base::WaitableEvent* done) {
-  CHECK_EQ(MessageLoop::current(), message_loop_);
-  CHECK_EQ(static_cast<uint32>(GL_TEXTURE_RECTANGLE_ARB), texture_target);
-  CGLContextObj cgl_ctx = GetCGLContext(gl_view_);
-  glGenTextures(1, texture_id);
-  CHECK_EQ(GL_NO_ERROR, static_cast<int>(glGetError()));
-  done->Signal();
-}
-
-void RenderingHelperMac::RenderTexture(GLuint texture_id) {
-  CHECK_EQ(MessageLoop::current(), message_loop_);
-  DrawTexture(gl_view_, texture_id, suppress_swap_to_display_);
-}
-
-void RenderingHelperMac::DeleteTexture(GLuint texture_id) {
-  CHECK_EQ(MessageLoop::current(), message_loop_);
-  CGLContextObj cgl_ctx = GetCGLContext(gl_view_);
-  glDeleteTextures(1, &texture_id);
-  CHECK_EQ(GL_NO_ERROR, static_cast<int>(glGetError()));
-}
-
-void* RenderingHelperMac::GetGLContext() {
-  return GetCGLContext(gl_view_);
-}
-
-void* RenderingHelperMac::GetGLDisplay() {
-  return NULL;
-}
-
-}  // namespace content
diff --git a/content/common/gpu/media/vaapi_h264_decoder.cc b/content/common/gpu/media/vaapi_h264_decoder.cc
index 65fd5cd..03cfc4f 100644
--- a/content/common/gpu/media/vaapi_h264_decoder.cc
+++ b/content/common/gpu/media/vaapi_h264_decoder.cc
@@ -9,6 +9,7 @@
 
 #include "base/bind.h"
 #include "base/bind_helpers.h"
+#include "base/metrics/histogram.h"
 #include "base/stl_util.h"
 #include "content/common/gpu/gl_scoped_binders.h"
 #include "content/common/gpu/media/vaapi_h264_decoder.h"
@@ -16,19 +17,43 @@
 #include "third_party/libva/va/va_x11.h"
 #include "ui/gl/gl_bindings.h"
 
+namespace {
+
+enum VAVDAH264DecoderFailure {
+  FRAME_MBS_ONLY_FLAG_NOT_ONE = 0,
+  GAPS_IN_FRAME_NUM = 1,
+  MID_STREAM_RESOLUTION_CHANGE = 2,
+  INTERLACED_STREAM = 3,
+  VAAPI_ERROR = 4,
+  VAVDA_H264_DECODER_FAILURES_MAX,
+};
+
+static void ReportToUMA(VAVDAH264DecoderFailure failure) {
+  UMA_HISTOGRAM_ENUMERATION("Media.VAVDAH264.DecoderFailure",
+                            failure,
+                            VAVDA_H264_DECODER_FAILURES_MAX);
+}
+
+}  // namespace
+
+#define LOG_VA_ERROR_AND_RECORD_UMA(va_res, err_msg)       \
+  do {                                                     \
+      DVLOG(1) << err_msg                                  \
+               << " VA error: " << VAAPI_ErrorStr(va_res); \
+      ReportToUMA(VAAPI_ERROR);                            \
+  } while (0)
+
 #define VA_LOG_ON_ERROR(va_res, err_msg)                   \
   do {                                                     \
     if ((va_res) != VA_STATUS_SUCCESS) {                   \
-      DVLOG(1) << err_msg                                  \
-               << " VA error: " << VAAPI_ErrorStr(va_res); \
+      LOG_VA_ERROR_AND_RECORD_UMA(va_res, err_msg);        \
     }                                                      \
   } while (0)
 
 #define VA_SUCCESS_OR_RETURN(va_res, err_msg, ret)         \
   do {                                                     \
     if ((va_res) != VA_STATUS_SUCCESS) {                   \
-      DVLOG(1) << err_msg                                  \
-               << " VA error: " << VAAPI_ErrorStr(va_res); \
+      LOG_VA_ERROR_AND_RECORD_UMA(va_res, err_msg);        \
       return (ret);                                        \
     }                                                      \
   } while (0)
@@ -479,7 +504,7 @@
   scoped_ptr_malloc<GLXFBConfig, ScopedPtrXFree> glx_fb_configs(
       glXChooseFBConfig(x_display_, DefaultScreen(x_display_), fbconfig_attr,
                         &num_fbconfigs));
-  if (!glx_fb_configs.get())
+  if (!glx_fb_configs)
     return false;
   if (!num_fbconfigs)
     return false;
@@ -1940,6 +1965,7 @@
       } else {
         // Shouldn't get here.
         DVLOG(1) << "Interlaced video not supported.";
+        ReportToUMA(INTERLACED_STREAM);
       }
     } else {
       // Stream has instructions how to discard pictures from DPB and how
@@ -1950,6 +1976,7 @@
       } else {
         // Shouldn't get here.
         DVLOG(1) << "Interlaced video not supported.";
+        ReportToUMA(INTERLACED_STREAM);
       }
     }
   }
@@ -2018,7 +2045,7 @@
     if (!(*output_candidate)->ref) {
       // Current picture hasn't been inserted into DPB yet, so don't remove it
       // if we managed to output it immediately.
-      if (*output_candidate != pic.get())
+      if (*output_candidate != pic)
         dpb_.RemoveByPOC((*output_candidate)->pic_order_cnt);
       // Mark as unused.
       UnassignSurfaceFromPoC((*output_candidate)->pic_order_cnt);
@@ -2070,8 +2097,15 @@
   const H264SPS* sps = parser_.GetSPS(sps_id);
   DCHECK(sps);
 
+  if (sps->frame_mbs_only_flag == 0) {
+    DVLOG(1) << "frame_mbs_only_flag != 1 not supported";
+    ReportToUMA(FRAME_MBS_ONLY_FLAG_NOT_ONE);
+    return false;
+  }
+
   if (sps->gaps_in_frame_num_value_allowed_flag) {
     DVLOG(1) << "Gaps in frame numbers not supported";
+    ReportToUMA(GAPS_IN_FRAME_NUM);
     return false;
   }
 
@@ -2095,6 +2129,7 @@
   if ((pic_width_ != -1 || pic_height_ != -1) &&
       (width != pic_width_ || height != pic_height_)) {
     DVLOG(1) << "Picture size changed mid-stream";
+    ReportToUMA(MID_STREAM_RESOLUTION_CHANGE);
     return false;
   }
 
@@ -2144,6 +2179,7 @@
 
   if (prev_frame_num_ > 0 && prev_frame_num_ < frame_num_ - 1) {
     DVLOG(1) << "Gap in frame_num!";
+    ReportToUMA(GAPS_IN_FRAME_NUM);
     return false;
   }
 
diff --git a/content/common/gpu/media/vaapi_video_decode_accelerator.cc b/content/common/gpu/media/vaapi_video_decode_accelerator.cc
index 679162c..a401ef6 100644
--- a/content/common/gpu/media/vaapi_video_decode_accelerator.cc
+++ b/content/common/gpu/media/vaapi_video_decode_accelerator.cc
@@ -36,8 +36,8 @@
 }
 
 void VaapiVideoDecodeAccelerator::NotifyError(Error error) {
-  if (message_loop_ != MessageLoop::current()) {
-    DCHECK_EQ(decoder_thread_.message_loop(), MessageLoop::current());
+  if (message_loop_ != base::MessageLoop::current()) {
+    DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
     message_loop_->PostTask(FROM_HERE, base::Bind(
         &VaapiVideoDecodeAccelerator::NotifyError, weak_this_, error));
     return;
@@ -64,7 +64,7 @@
       state_(kUninitialized),
       input_ready_(&lock_),
       output_ready_(&lock_),
-      message_loop_(MessageLoop::current()),
+      message_loop_(base::MessageLoop::current()),
       weak_this_(base::AsWeakPtr(this)),
       client_ptr_factory_(client),
       client_(client_ptr_factory_.GetWeakPtr()),
@@ -79,12 +79,12 @@
 }
 
 VaapiVideoDecodeAccelerator::~VaapiVideoDecodeAccelerator() {
-  DCHECK_EQ(message_loop_, MessageLoop::current());
+  DCHECK_EQ(message_loop_, base::MessageLoop::current());
 }
 
 bool VaapiVideoDecodeAccelerator::Initialize(
     media::VideoCodecProfile profile) {
-  DCHECK_EQ(message_loop_, MessageLoop::current());
+  DCHECK_EQ(message_loop_, base::MessageLoop::current());
 
   base::AutoLock auto_lock(lock_);
   DCHECK_EQ(state_, kUninitialized);
@@ -114,7 +114,8 @@
     int32 output_id,
     scoped_ptr<std::queue<VABufferID> > va_bufs,
     scoped_ptr<std::queue<VABufferID> > slice_bufs) {
-  DCHECK_EQ(message_loop_, MessageLoop::current());
+  DCHECK_EQ(message_loop_, base::MessageLoop::current());
+  base::AutoLock auto_lock(lock_);
 
   TRACE_EVENT1("Video Decoder", "VAVDA::Decode", "output_id", output_id);
 
@@ -130,7 +131,7 @@
 
 void VaapiVideoDecodeAccelerator::NotifyPictureReady(int32 input_id,
                                                      int32 output_id) {
-  DCHECK_EQ(message_loop_, MessageLoop::current());
+  DCHECK_EQ(message_loop_, base::MessageLoop::current());
   TRACE_EVENT2("Video Decoder", "VAVDA::NotifyPictureReady",
                "input_id", input_id, "output_id", output_id);
 
@@ -160,7 +161,7 @@
 
 void VaapiVideoDecodeAccelerator::MapAndQueueNewInputBuffer(
     const media::BitstreamBuffer& bitstream_buffer) {
-  DCHECK_EQ(message_loop_, MessageLoop::current());
+  DCHECK_EQ(message_loop_, base::MessageLoop::current());
   TRACE_EVENT1("Video Decoder", "MapAndQueueNewInputBuffer", "input_id",
       bitstream_buffer.id());
 
@@ -189,7 +190,7 @@
 }
 
 void VaapiVideoDecodeAccelerator::InitialDecodeTask() {
-  DCHECK_EQ(decoder_thread_.message_loop(), MessageLoop::current());
+  DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
   base::AutoLock auto_lock(lock_);
 
   // Try to initialize or resume playback after reset.
@@ -209,7 +210,7 @@
       case VaapiH264Decoder::kReadyToDecode:
         if (state_ == kInitialized) {
           state_ = kPicturesRequested;
-          int num_pics = decoder_.GetRequiredNumOfPictures();
+          size_t num_pics = decoder_.GetRequiredNumOfPictures();
           gfx::Size size(decoder_.pic_width(), decoder_.pic_height());
           DVLOG(1) << "Requesting " << num_pics << " pictures of size: "
                    << size.width() << "x" << size.height();
@@ -250,7 +251,7 @@
 }
 
 bool VaapiVideoDecodeAccelerator::GetInputBuffer_Locked() {
-  DCHECK_EQ(decoder_thread_.message_loop(), MessageLoop::current());
+  DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
   lock_.AssertAcquired();
 
   if (curr_input_buffer_.get())
@@ -298,7 +299,7 @@
 
 void VaapiVideoDecodeAccelerator::ReturnCurrInputBuffer_Locked() {
   lock_.AssertAcquired();
-  DCHECK_EQ(decoder_thread_.message_loop(), MessageLoop::current());
+  DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
   DCHECK(curr_input_buffer_.get());
 
   int32 id = curr_input_buffer_->id;
@@ -314,7 +315,7 @@
 
 bool VaapiVideoDecodeAccelerator::GetOutputBuffers_Locked() {
   lock_.AssertAcquired();
-  DCHECK_EQ(decoder_thread_.message_loop(), MessageLoop::current());
+  DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
 
   while (output_buffers_.empty() &&
          (state_ == kDecoding || state_ == kFlushing || state_ == kIdle)) {
@@ -333,7 +334,7 @@
 }
 
 void VaapiVideoDecodeAccelerator::DecodeTask() {
-  DCHECK_EQ(decoder_thread_.message_loop(), MessageLoop::current());
+  DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
   TRACE_EVENT0("Video Decoder", "VAVDA::DecodeTask");
   base::AutoLock auto_lock(lock_);
 
@@ -346,10 +347,7 @@
     DCHECK(curr_input_buffer_.get());
 
     VaapiH264Decoder::DecResult res;
-    {
-      base::AutoUnlock auto_unlock(lock_);
-      res = decoder_.DecodeOneFrame(curr_input_buffer_->id);
-    }
+    res = decoder_.DecodeOneFrame(curr_input_buffer_->id);
 
     switch (res) {
       case VaapiH264Decoder::kNeedMoreStreamData:
@@ -383,7 +381,7 @@
 
 void VaapiVideoDecodeAccelerator::Decode(
     const media::BitstreamBuffer& bitstream_buffer) {
-  DCHECK_EQ(message_loop_, MessageLoop::current());
+  DCHECK_EQ(message_loop_, base::MessageLoop::current());
 
   TRACE_EVENT1("Video Decoder", "VAVDA::Decode", "Buffer id",
                bitstream_buffer.id());
@@ -427,10 +425,14 @@
 
 void VaapiVideoDecodeAccelerator::AssignPictureBuffers(
     const std::vector<media::PictureBuffer>& buffers) {
-  DCHECK_EQ(message_loop_, MessageLoop::current());
+  DCHECK_EQ(message_loop_, base::MessageLoop::current());
 
   base::AutoLock auto_lock(lock_);
   DCHECK_EQ(state_, kPicturesRequested);
+  size_t num_pics = decoder_.GetRequiredNumOfPictures();
+  RETURN_AND_NOTIFY_ON_FAILURE((num_pics == buffers.size()),
+      "Failed to provide requested picture buffers. (Got " << buffers.size() <<
+      ", requested " << num_pics << ")", INVALID_ARGUMENT,);
 
   for (size_t i = 0; i < buffers.size(); ++i) {
     DVLOG(2) << "Assigning picture id " << buffers[i].id()
@@ -449,7 +451,7 @@
 }
 
 void VaapiVideoDecodeAccelerator::ReusePictureBuffer(int32 picture_buffer_id) {
-  DCHECK_EQ(message_loop_, MessageLoop::current());
+  DCHECK_EQ(message_loop_, base::MessageLoop::current());
   TRACE_EVENT1("Video Decoder", "VAVDA::ReusePictureBuffer", "Picture id",
                picture_buffer_id);
 
@@ -462,9 +464,11 @@
 }
 
 void VaapiVideoDecodeAccelerator::FlushTask() {
-  DCHECK_EQ(decoder_thread_.message_loop(), MessageLoop::current());
+  DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
   DVLOG(1) << "Flush task";
 
+  base::AutoLock auto_lock(lock_);
+
   // First flush all the pictures that haven't been outputted, notifying the
   // client to output them.
   bool res = decoder_.Flush();
@@ -479,7 +483,7 @@
 }
 
 void VaapiVideoDecodeAccelerator::Flush() {
-  DCHECK_EQ(message_loop_, MessageLoop::current());
+  DCHECK_EQ(message_loop_, base::MessageLoop::current());
   DVLOG(1) << "Got flush request";
 
   base::AutoLock auto_lock(lock_);
@@ -493,7 +497,7 @@
 }
 
 void VaapiVideoDecodeAccelerator::FinishFlush() {
-  DCHECK_EQ(message_loop_, MessageLoop::current());
+  DCHECK_EQ(message_loop_, base::MessageLoop::current());
 
   base::AutoLock auto_lock(lock_);
   if (state_ != kFlushing) {
@@ -510,15 +514,15 @@
 }
 
 void VaapiVideoDecodeAccelerator::ResetTask() {
-  DCHECK_EQ(decoder_thread_.message_loop(), MessageLoop::current());
+  DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
+
+  base::AutoLock auto_lock(lock_);
 
   // All the decoding tasks from before the reset request from client are done
   // by now, as this task was scheduled after them and client is expected not
   // to call Decode() after Reset() and before NotifyResetDone.
   decoder_.Reset();
 
-  base::AutoLock auto_lock(lock_);
-
   // Return current input buffer, if present.
   if (curr_input_buffer_.get())
     ReturnCurrInputBuffer_Locked();
@@ -529,7 +533,7 @@
 }
 
 void VaapiVideoDecodeAccelerator::Reset() {
-  DCHECK_EQ(message_loop_, MessageLoop::current());
+  DCHECK_EQ(message_loop_, base::MessageLoop::current());
   DVLOG(1) << "Got reset request";
 
   // This will make any new decode tasks exit early.
@@ -552,7 +556,7 @@
 }
 
 void VaapiVideoDecodeAccelerator::FinishReset() {
-  DCHECK_EQ(message_loop_, MessageLoop::current());
+  DCHECK_EQ(message_loop_, base::MessageLoop::current());
 
   base::AutoLock auto_lock(lock_);
   if (state_ != kResetting) {
@@ -580,7 +584,7 @@
 }
 
 void VaapiVideoDecodeAccelerator::Cleanup() {
-  DCHECK_EQ(message_loop_, MessageLoop::current());
+  DCHECK_EQ(message_loop_, base::MessageLoop::current());
 
   if (state_ == kUninitialized || state_ == kDestroying)
     return;
@@ -608,7 +612,7 @@
 }
 
 void VaapiVideoDecodeAccelerator::Destroy() {
-  DCHECK_EQ(message_loop_, MessageLoop::current());
+  DCHECK_EQ(message_loop_, base::MessageLoop::current());
   Cleanup();
   delete this;
 }
diff --git a/content/common/gpu/media/vaapi_video_decode_accelerator.h b/content/common/gpu/media/vaapi_video_decode_accelerator.h
index f1cd07a..8c6b71b 100644
--- a/content/common/gpu/media/vaapi_video_decode_accelerator.h
+++ b/content/common/gpu/media/vaapi_video_decode_accelerator.h
@@ -184,7 +184,7 @@
   base::ConditionVariable output_ready_;
 
   // ChildThread's message loop
-  MessageLoop* message_loop_;
+  base::MessageLoop* message_loop_;
 
   // WeakPtr<> pointing to |this| for use in posting tasks from the decoder
   // thread back to the ChildThread.  Because the decoder thread is a member of
diff --git a/content/common/gpu/media/video_decode_accelerator_unittest.cc b/content/common/gpu/media/video_decode_accelerator_unittest.cc
index 6b01a9a..764689f 100644
--- a/content/common/gpu/media/video_decode_accelerator_unittest.cc
+++ b/content/common/gpu/media/video_decode_accelerator_unittest.cc
@@ -44,12 +44,9 @@
 
 #if defined(OS_WIN)
 #include "content/common/gpu/media/dxva_video_decode_accelerator.h"
-#elif defined(OS_MACOSX)
-#include "content/common/gpu/media/mac_video_decode_accelerator.h"
 #elif defined(OS_CHROMEOS)
 #if defined(ARCH_CPU_ARMEL)
 #include "content/common/gpu/media/exynos_video_decode_accelerator.h"
-#include "content/common/gpu/media/omx_video_decode_accelerator.h"
 #elif defined(ARCH_CPU_X86_FAMILY)
 #include "content/common/gpu/media/vaapi_video_decode_accelerator.h"
 #endif  // ARCH_CPU_ARMEL
@@ -79,14 +76,18 @@
 //   (the latter tests just decode speed).
 // - |profile| is the media::VideoCodecProfile set during Initialization.
 // An empty value for a numeric field means "ignore".
-#if defined(OS_MACOSX)
-const base::FilePath::CharType* test_video_data =
-    FILE_PATH_LITERAL("test-25fps_high.h264:1280:720:250:252:50:100:4");
-#else
 const base::FilePath::CharType* test_video_data =
     // FILE_PATH_LITERAL("test-25fps.vp8:320:240:250:250:50:175:11");
     FILE_PATH_LITERAL("test-25fps.h264:320:240:250:258:50:175:1");
-#endif
+
+// Magic constants for differentiating the reasons for NotifyResetDone being
+// called.
+enum ResetPoint {
+  MID_STREAM_RESET = -2,
+  END_OF_STREAM_RESET = -1
+};
+
+const int kMaxResetAfterFrameNum = 100;
 
 struct TestVideoFile {
   explicit TestVideoFile(base::FilePath::StringType file_name)
@@ -97,7 +98,8 @@
         num_fragments(-1),
         min_fps_render(-1),
         min_fps_no_render(-1),
-        profile(-1) {
+        profile(-1),
+        reset_after_frame_num(END_OF_STREAM_RESET) {
   }
 
   base::FilePath::StringType file_name;
@@ -108,6 +110,7 @@
   int min_fps_render;
   int min_fps_no_render;
   int profile;
+  int reset_after_frame_num;
   std::string data_str;
 };
 
@@ -116,7 +119,7 @@
 // missing required data. Unspecified optional fields are set to -1.
 void ParseAndReadTestVideoData(base::FilePath::StringType data,
                                size_t num_concurrent_decoders,
-                               int reset_after_frame_num,
+                               int reset_point,
                                std::vector<TestVideoFile*>* test_video_files) {
   std::vector<base::FilePath::StringType> entries;
   base::SplitString(data, ';', &entries);
@@ -135,8 +138,14 @@
       CHECK(base::StringToInt(fields[3], &video_file->num_frames));
       // If we reset mid-stream and start playback over, account for frames
       // that are decoded twice in our expectations.
-      if (video_file->num_frames > 0 && reset_after_frame_num >= 0)
-        video_file->num_frames += reset_after_frame_num;
+      if (video_file->num_frames > 0 && reset_point == MID_STREAM_RESET) {
+        // Reset should not go beyond the last frame; reset after the first
+        // frame for short videos.
+        video_file->reset_after_frame_num = kMaxResetAfterFrameNum;
+        if (video_file->num_frames <= kMaxResetAfterFrameNum)
+          video_file->reset_after_frame_num = 1;
+        video_file->num_frames += video_file->reset_after_frame_num;
+      }
     }
     if (!fields[4].empty())
       CHECK(base::StringToInt(fields[4], &video_file->num_fragments));
@@ -214,13 +223,6 @@
   return ret;
 }
 
-// Magic constants for differentiating the reasons for NotifyResetDone being
-// called.
-enum ResetPoint {
-  MID_STREAM_RESET = -2,
-  END_OF_STREAM_RESET = -1
-};
-
 // Client that can accept callbacks from a VideoDecodeAccelerator and is used by
 // the TESTs below.
 class GLRenderingVDAClient : public VideoDecodeAccelerator::Client {
@@ -361,9 +363,7 @@
   SetState(CS_DESTROYED);
 }
 
-#if !defined(OS_MACOSX)
 static bool DoNothingReturnTrue() { return true; }
-#endif
 
 void GLRenderingVDAClient::CreateDecoder() {
   CHECK(decoder_deleted());
@@ -371,24 +371,13 @@
 #if defined(OS_WIN)
   decoder_.reset(new DXVAVideoDecodeAccelerator(
       this, base::Bind(&DoNothingReturnTrue)));
-#elif defined(OS_MACOSX)
-  decoder_.reset(new MacVideoDecodeAccelerator(
-      static_cast<CGLContextObj>(rendering_helper_->GetGLContext()), this));
 #elif defined(OS_CHROMEOS)
 #if defined(ARCH_CPU_ARMEL)
-  if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kUseExynosVda)) {
-    decoder_.reset(
-        new ExynosVideoDecodeAccelerator(
-            static_cast<EGLDisplay>(rendering_helper_->GetGLDisplay()),
-            static_cast<EGLContext>(rendering_helper_->GetGLContext()),
-            this, base::Bind(&DoNothingReturnTrue)));
-  } else {
-    decoder_.reset(
-        new OmxVideoDecodeAccelerator(
-            static_cast<EGLDisplay>(rendering_helper_->GetGLDisplay()),
-            static_cast<EGLContext>(rendering_helper_->GetGLContext()),
-            this, base::Bind(&DoNothingReturnTrue)));
-  }
+  decoder_.reset(
+      new ExynosVideoDecodeAccelerator(
+          static_cast<EGLDisplay>(rendering_helper_->GetGLDisplay()),
+          static_cast<EGLContext>(rendering_helper_->GetGLContext()),
+          this, base::Bind(&DoNothingReturnTrue)));
 #elif defined(ARCH_CPU_X86_FAMILY)
   decoder_.reset(new VaapiVideoDecodeAccelerator(
       static_cast<Display*>(rendering_helper_->GetGLDisplay()),
@@ -710,11 +699,7 @@
 // We assert a minimal number of concurrent decoders we expect to succeed.
 // Different platforms can support more concurrent decoders, so we don't assert
 // failure above this.
-#if defined(OS_MACOSX)
-enum { kMinSupportedNumConcurrentDecoders = 1 };
-#else
 enum { kMinSupportedNumConcurrentDecoders = 3 };
-#endif
 
 // Test the most straightforward case possible: data is decoded from a single
 // chunk and rendered to the screen.
@@ -729,12 +714,12 @@
   const size_t num_concurrent_decoders = GetParam().b;
   const size_t num_in_flight_decodes = GetParam().c;
   const int num_play_throughs = GetParam().d;
-  const int reset_after_frame_num = GetParam().e;
+  const int reset_point = GetParam().e;
   const int delete_decoder_state = GetParam().f;
 
   std::vector<TestVideoFile*> test_video_files;
   ParseAndReadTestVideoData(test_video_data, num_concurrent_decoders,
-                            reset_after_frame_num, &test_video_files);
+                            reset_point, &test_video_files);
 
   // Suppress GL swapping in all but a few tests, to cut down overall test
   // runtime.
@@ -746,11 +731,11 @@
   // Initialize the rendering helper.
   base::Thread rendering_thread("GLRenderingVDAClientThread");
   base::Thread::Options options;
-  options.message_loop_type = MessageLoop::TYPE_DEFAULT;
+  options.message_loop_type = base::MessageLoop::TYPE_DEFAULT;
 #if defined(OS_WIN)
   // For windows the decoding thread initializes the media foundation decoder
   // which uses COM. We need the thread to be a UI thread.
-  options.message_loop_type = MessageLoop::TYPE_UI;
+  options.message_loop_type = base::MessageLoop::TYPE_UI;
 #endif  // OS_WIN
 
   rendering_thread.StartWithOptions(options);
@@ -779,8 +764,8 @@
     GLRenderingVDAClient* client = new GLRenderingVDAClient(
         rendering_helper.get(), index, note, video_file->data_str,
         num_fragments_per_decode, num_in_flight_decodes, num_play_throughs,
-        reset_after_frame_num, delete_decoder_state, video_file->width,
-        video_file->height, video_file->profile);
+        video_file->reset_after_frame_num, delete_decoder_state,
+        video_file->width, video_file->height, video_file->profile);
     clients[index] = client;
 
     rendering_thread.message_loop()->PostTask(
@@ -838,9 +823,15 @@
       continue;
     GLRenderingVDAClient* client = clients[i];
     TestVideoFile* video_file = test_video_files[i % test_video_files.size()];
-    if (video_file->num_frames > 0)
-      EXPECT_EQ(client->num_decoded_frames(), video_file->num_frames);
-    if (reset_after_frame_num < 0) {
+    if (video_file->num_frames > 0) {
+      // Expect the decoded frames may be more than the video frames as frames
+      // could still be returned until resetting done.
+      if (video_file->reset_after_frame_num > 0)
+        EXPECT_GE(client->num_decoded_frames(), video_file->num_frames);
+      else
+        EXPECT_EQ(client->num_decoded_frames(), video_file->num_frames);
+    }
+    if (reset_point == END_OF_STREAM_RESET) {
       EXPECT_EQ(video_file->num_fragments, client->num_skipped_fragments() +
                 client->num_queued_fragments());
       EXPECT_EQ(client->num_done_bitstream_buffers(),
@@ -886,7 +877,7 @@
 INSTANTIATE_TEST_CASE_P(
     MidStreamReset, VideoDecodeAcceleratorTest,
     ::testing::Values(
-        MakeTuple(1, 1, 1, 1, static_cast<ResetPoint>(100), CS_RESET)));
+        MakeTuple(1, 1, 1, 1, MID_STREAM_RESET, CS_RESET)));
 
 // Test that Destroy() mid-stream works fine (primarily this is testing that no
 // crashes occur).
@@ -974,10 +965,6 @@
     }
     if (it->first == "v" || it->first == "vmodule")
       continue;
-#if defined(OS_CHROMEOS) && defined(ARCH_CPU_ARMEL)
-    if (it->first == switches::kUseExynosVda)
-      continue;
-#endif
     LOG(FATAL) << "Unexpected switch: " << it->first << ":" << it->second;
   }
 
@@ -988,10 +975,7 @@
   content::DXVAVideoDecodeAccelerator::PreSandboxInitialization();
 #elif defined(OS_CHROMEOS)
 #if defined(ARCH_CPU_ARMEL)
-  if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kUseExynosVda))
-    content::ExynosVideoDecodeAccelerator::PreSandboxInitialization();
-  else
-    content::OmxVideoDecodeAccelerator::PreSandboxInitialization();
+  content::ExynosVideoDecodeAccelerator::PreSandboxInitialization();
 #elif defined(ARCH_CPU_X86_FAMILY)
   content::VaapiVideoDecodeAccelerator::PreSandboxInitialization();
 #endif  // ARCH_CPU_ARMEL
diff --git a/content/common/gpu/stream_texture_manager_android.cc b/content/common/gpu/stream_texture_manager_android.cc
index 6eb7a10..8b663a9 100644
--- a/content/common/gpu/stream_texture_manager_android.cc
+++ b/content/common/gpu/stream_texture_manager_android.cc
@@ -5,17 +5,17 @@
 #include "content/common/gpu/stream_texture_manager_android.h"
 
 #include "base/bind.h"
-#include "content/common/android/surface_texture_bridge.h"
 #include "content/common/gpu/gpu_channel.h"
 #include "content/common/gpu/gpu_messages.h"
 #include "gpu/command_buffer/service/stream_texture.h"
 #include "ui/gfx/size.h"
+#include "ui/gl/android/surface_texture_bridge.h"
 
 namespace content {
 
 StreamTextureManagerAndroid::StreamTextureAndroid::StreamTextureAndroid(
     GpuChannel* channel, int service_id)
-    : surface_texture_bridge_(new SurfaceTextureBridge(service_id)),
+    : surface_texture_bridge_(new gfx::SurfaceTextureBridge(service_id)),
       has_updated_(false),
       channel_(channel) {
   memset(current_matrix_, 0, sizeof(current_matrix_));
diff --git a/content/common/gpu/stream_texture_manager_android.h b/content/common/gpu/stream_texture_manager_android.h
index e514fc9..0f7dea9 100644
--- a/content/common/gpu/stream_texture_manager_android.h
+++ b/content/common/gpu/stream_texture_manager_android.h
@@ -17,13 +17,12 @@
 
 namespace gfx {
 class Size;
+class SurfaceTextureBridge;
 }
 
 namespace content {
 class GpuChannel;
 
-class SurfaceTextureBridge;
-
 // Class for managing the stream texture.
 class StreamTextureManagerAndroid : public gpu::StreamTextureManager {
  public:
@@ -57,7 +56,7 @@
 
     virtual void Update() OVERRIDE;
 
-    scoped_refptr<SurfaceTextureBridge> surface_texture_bridge() {
+    scoped_refptr<gfx::SurfaceTextureBridge> surface_texture_bridge() {
         return surface_texture_bridge_;
     }
 
@@ -75,7 +74,7 @@
     }
 
    private:
-    scoped_refptr<SurfaceTextureBridge> surface_texture_bridge_;
+    scoped_refptr<gfx::SurfaceTextureBridge> surface_texture_bridge_;
 
     // Current transform matrix of the surface texture.
     float current_matrix_[16];
diff --git a/content/common/gpu/testdata/bear.README b/content/common/gpu/testdata/bear.README
new file mode 100644
index 0000000..177951d
--- /dev/null
+++ b/content/common/gpu/testdata/bear.README
@@ -0,0 +1,7 @@
+bear video files in this directory and their provenance:
+
+bear.h264:
+  Using ffmpeg version 0.8.6-4:0.8.6-0ubuntu0.12.04.1, generated with
+  bear.mp4 (https://chromiumcodereview.appspot.com/10805089):
+  ffmpeg -i bear.mp4 -vcodec copy -vbsf h264_mp4toannexb \
+      -an bear.h264
diff --git a/content/common/gpu/testdata/bear.h264 b/content/common/gpu/testdata/bear.h264
new file mode 100644
index 0000000..aaf0a9f
--- /dev/null
+++ b/content/common/gpu/testdata/bear.h264
Binary files differ
diff --git a/content/common/gpu/testdata/npot-video.README b/content/common/gpu/testdata/npot-video.README
new file mode 100644
index 0000000..ff1378b
--- /dev/null
+++ b/content/common/gpu/testdata/npot-video.README
@@ -0,0 +1,29 @@
+npot-video video files in this directory and their provenance:
+
+npot-video.h264:
+  Using ffmpeg version 0.8.6-4:0.8.6-0ubuntu0.12.04.1, generated with
+  npot-video.mp4 (https://codereview.chromium.org/8342021):
+  ffmpeg -i npot-video.mp4 -vcodec copy -vbsf h264_mp4toannexb \
+      -an npot-video.h264
+
+
+Copyright (c) 2012 The Khronos Group Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and/or associated documentation files (the
+"Materials"), to deal in the Materials without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Materials, and to
+permit persons to whom the Materials are 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 Materials.
+
+THE MATERIALS ARE 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
+MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
diff --git a/content/common/gpu/testdata/npot-video.h264 b/content/common/gpu/testdata/npot-video.h264
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/content/common/gpu/testdata/npot-video.h264
diff --git a/content/common/gpu/testdata/red-green.README b/content/common/gpu/testdata/red-green.README
new file mode 100644
index 0000000..0f31b90
--- /dev/null
+++ b/content/common/gpu/testdata/red-green.README
@@ -0,0 +1,29 @@
+red-green video files in this directory and their provenance:
+
+red-green.h264:
+  Using ffmpeg version 0.8.6-4:0.8.6-0ubuntu0.12.04.1, generated with
+  red-green.mp4 (https://codereview.chromium.org/8342021):
+  ffmpeg -i red-green.mp4 -vcodec copy -vbsf h264_mp4toannexb \
+      -an red-green.h264
+
+
+Copyright (c) 2012 The Khronos Group Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and/or associated documentation files (the
+"Materials"), to deal in the Materials without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Materials, and to
+permit persons to whom the Materials are 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 Materials.
+
+THE MATERIALS ARE 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
+MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
diff --git a/content/common/gpu/testdata/red-green.h264 b/content/common/gpu/testdata/red-green.h264
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/content/common/gpu/testdata/red-green.h264
diff --git a/content/common/gpu/testdata/README b/content/common/gpu/testdata/test-25fps.README
similarity index 88%
rename from content/common/gpu/testdata/README
rename to content/common/gpu/testdata/test-25fps.README
index 0c0e63f..ba46586 100644
--- a/content/common/gpu/testdata/README
+++ b/content/common/gpu/testdata/test-25fps.README
@@ -1,4 +1,4 @@
-Files in this directory and their provenance:
+test-25fps video files in this directory and their provenance:
 
 test-25fps.h264:
   Using ffmpeg SVN-r0.5.9-4:0.5.9-0ubuntu0.10.04.1 @ WebKit r122718, generated
diff --git a/content/common/gpu/texture_image_transport_surface.cc b/content/common/gpu/texture_image_transport_surface.cc
index 5eeb2a1..9710b35 100644
--- a/content/common/gpu/texture_image_transport_surface.cc
+++ b/content/common/gpu/texture_image_transport_surface.cc
@@ -54,7 +54,7 @@
 
   GpuChannelManager* manager = helper_->manager();
   surface_ = manager->GetDefaultOffscreenSurface();
-  if (!surface_.get())
+  if (!surface_)
     return false;
 
   if (!helper_->Initialize())
@@ -71,7 +71,7 @@
 }
 
 void TextureImageTransportSurface::Destroy() {
-  if (surface_.get())
+  if (surface_)
     surface_ = NULL;
 
   helper_->Destroy();
@@ -173,10 +173,8 @@
   CreateBackTexture();
 }
 
-void TextureImageTransportSurface::OnWillDestroyStub(
-    GpuCommandBufferStub* stub) {
-  DCHECK(stub == helper_->stub());
-  stub->RemoveDestructionObserver(this);
+void TextureImageTransportSurface::OnWillDestroyStub() {
+  helper_->stub()->RemoveDestructionObserver(this);
 
   GpuHostMsg_AcceleratedSurfaceRelease_Params params;
   helper_->SendAcceleratedSurfaceRelease(params);
@@ -194,8 +192,14 @@
   stub_destroyed_ = true;
 }
 
+void TextureImageTransportSurface::SetLatencyInfo(
+    const cc::LatencyInfo& latency_info) {
+  latency_info_ = latency_info;
+}
+
 bool TextureImageTransportSurface::SwapBuffers() {
   DCHECK(backbuffer_suggested_allocation_);
+
   if (!frontbuffer_suggested_allocation_)
     return true;
 
@@ -217,6 +221,7 @@
   // so we do not leak a texture in the mailbox.
   AddRef();
 
+  params.latency_info = latency_info_;
   helper_->SendAcceleratedSurfaceBuffersSwapped(params);
 
   DCHECK(!is_swap_buffers_pending_);
@@ -258,6 +263,7 @@
   // so we do not leak a texture in the mailbox.
   AddRef();
 
+  params.latency_info = latency_info_;
   helper_->SendAcceleratedSurfacePostSubBuffer(params);
 
   DCHECK(!is_swap_buffers_pending_);
@@ -321,7 +327,7 @@
     // of the service ids.
     DCHECK(context_.get() && surface_.get());
     uint32 service_id = backbuffer_->ReleaseServiceId();
-    if (context_->MakeCurrent(surface_.get()))
+    if (context_->MakeCurrent(surface_))
       glDeleteTextures(1, &service_id);
 
     return;
@@ -461,6 +467,7 @@
       GL_CLAMP_TO_EDGE,
       GL_NONE,
       true,
+      false,
       level_infos);
 }
 
diff --git a/content/common/gpu/texture_image_transport_surface.h b/content/common/gpu/texture_image_transport_surface.h
index 93a54c5..9ab9abc 100644
--- a/content/common/gpu/texture_image_transport_surface.h
+++ b/content/common/gpu/texture_image_transport_surface.h
@@ -55,9 +55,11 @@
       const AcceleratedSurfaceMsg_BufferPresented_Params& params) OVERRIDE;
   virtual void OnResizeViewACK() OVERRIDE;
   virtual void OnResize(gfx::Size size) OVERRIDE;
+  virtual void SetLatencyInfo(
+      const cc::LatencyInfo& latency_info) OVERRIDE;
 
   // GpuCommandBufferStub::DestructionObserver implementation.
-  virtual void OnWillDestroyStub(GpuCommandBufferStub* stub) OVERRIDE;
+  virtual void OnWillDestroyStub() OVERRIDE;
 
  private:
 
@@ -117,6 +119,7 @@
   // Holds a reference to the mailbox manager for cleanup.
   scoped_refptr<gpu::gles2::MailboxManager> mailbox_manager_;
 
+  cc::LatencyInfo latency_info_;
   DISALLOW_COPY_AND_ASSIGN(TextureImageTransportSurface);
 };
 
diff --git a/content/common/icon_messages.h b/content/common/icon_messages.h
deleted file mode 100644
index 63f9ab9..0000000
--- a/content/common/icon_messages.h
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Multiply-included message file, no traditional include guard.
-#include <vector>
-
-#include "content/public/common/favicon_url.h"
-#include "ipc/ipc_message.h"
-#include "ipc/ipc_message_macros.h"
-#include "ipc/ipc_param_traits.h"
-#include "third_party/skia/include/core/SkBitmap.h"
-
-#define IPC_MESSAGE_START IconMsgStart
-
-IPC_ENUM_TRAITS(content::FaviconURL::IconType)
-
-IPC_STRUCT_TRAITS_BEGIN(content::FaviconURL)
-  IPC_STRUCT_TRAITS_MEMBER(icon_url)
-  IPC_STRUCT_TRAITS_MEMBER(icon_type)
-IPC_STRUCT_TRAITS_END()
-
-// Messages sent from the browser to the renderer.
-
-// Requests the renderer to download the specified favicon image, decode it,
-// and send the image data back via IconHostMsg_DidDownloadFavicon.
-IPC_MESSAGE_ROUTED4(IconMsg_DownloadFavicon,
-                    int /* identifier for the request */,
-                    GURL /* URL of the image */,
-                    bool /* is favicon (turn off cookies) */,
-                    int /* Preferred favicon size. Passed on to
-                           IconHostMsg_DidDownloadFavicon, unused otherwise */)
-
-// Messages sent from the renderer to the browser.
-
-// Notification that the urls for the favicon of a site has been determined.
-IPC_MESSAGE_ROUTED2(IconHostMsg_UpdateFaviconURL,
-                    int32 /* page_id */,
-                    std::vector<content::FaviconURL> /* urls of the favicon */)
-
-IPC_MESSAGE_ROUTED4(IconHostMsg_DidDownloadFavicon,
-                    int /* Identifier of the request */,
-                    GURL /* URL of the image */,
-                    int /* Preferred icon size passed to
-                           IconMsg_DownloadFavicon */,
-                    std::vector<SkBitmap> /* image_data */)
diff --git a/content/common/image_messages.h b/content/common/image_messages.h
new file mode 100644
index 0000000..78d7cff
--- /dev/null
+++ b/content/common/image_messages.h
@@ -0,0 +1,33 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Multiply-included message file, no traditional include guard.
+#include <vector>
+
+#include "ipc/ipc_message.h"
+#include "ipc/ipc_message_macros.h"
+#include "ipc/ipc_param_traits.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+
+#define IPC_MESSAGE_START ImageMsgStart
+
+// Messages sent from the browser to the renderer.
+
+// Requests the renderer to download the specified image, decode it,
+// and send the image data back via ImageHostMsg_DidDownloadImage.
+IPC_MESSAGE_ROUTED4(ImageMsg_DownloadImage,
+                    int /* identifier for the request */,
+                    GURL /* URL of the image */,
+                    bool /* is favicon (turn off cookies) */,
+                    int /* Preferred image size. Passed on to
+                           ImageHostMsg_DidDownloadFavicon, unused otherwise */)
+
+// Messages sent from the renderer to the browser.
+
+IPC_MESSAGE_ROUTED4(ImageHostMsg_DidDownloadImage,
+                    int /* Identifier of the request */,
+                    GURL /* URL of the image */,
+                    int /* Preferred image size passed to
+                           ImageMsg_DownloadImage */,
+                    std::vector<SkBitmap> /* image_data */)
diff --git a/content/common/indexed_db/OWNERS b/content/common/indexed_db/OWNERS
index ba0cc18..ed5258c 100644
--- a/content/common/indexed_db/OWNERS
+++ b/content/common/indexed_db/OWNERS
@@ -12,3 +12,4 @@
 per-file *_messages.h=jschuh@chromium.org
 per-file *_messages.h=palmer@chromium.org
 per-file *_messages.h=tsepez@chromium.org
+per-file *_messages.h=kenrb@chromium.org
diff --git a/content/common/indexed_db/indexed_db_dispatcher.cc b/content/common/indexed_db/indexed_db_dispatcher.cc
index f79b9dd..fc9f1a7 100644
--- a/content/common/indexed_db/indexed_db_dispatcher.cc
+++ b/content/common/indexed_db/indexed_db_dispatcher.cc
@@ -13,16 +13,12 @@
 #include "content/common/indexed_db/proxy_webidbcursor_impl.h"
 #include "content/common/indexed_db/proxy_webidbdatabase_impl.h"
 #include "ipc/ipc_channel.h"
-#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
-#include "third_party/WebKit/Source/WebKit/chromium/public/WebIDBDatabaseCallbacks.h"
-#include "third_party/WebKit/Source/WebKit/chromium/public/WebIDBDatabaseError.h"
-#include "third_party/WebKit/Source/WebKit/chromium/public/WebIDBDatabaseException.h"
-#include "third_party/WebKit/Source/WebKit/chromium/public/WebIDBKeyRange.h"
+#include "third_party/WebKit/Source/Platform/chromium/public/WebIDBDatabaseCallbacks.h"
+#include "third_party/WebKit/Source/Platform/chromium/public/WebIDBDatabaseError.h"
+#include "third_party/WebKit/Source/Platform/chromium/public/WebIDBDatabaseException.h"
+#include "third_party/WebKit/Source/Platform/chromium/public/WebIDBKeyRange.h"
 
-using WebKit::WebDOMStringList;
 using WebKit::WebData;
-using WebKit::WebExceptionCode;
-using WebKit::WebFrame;
 using WebKit::WebIDBCallbacks;
 using WebKit::WebIDBDatabase;
 using WebKit::WebIDBDatabaseCallbacks;
@@ -170,6 +166,11 @@
 }
 
 bool IndexedDBDispatcher::Send(IPC::Message* msg) {
+  if (!ChildThread::current()) {
+    // Unexpected - this may be happening during shutdown.
+    NOTREACHED();
+    return false;
+  }
   if (CurrentWorkerId()) {
     scoped_refptr<IPC::SyncMessageFilter> filter(
         ChildThread::current()->sync_message_filter());
@@ -181,8 +182,7 @@
 void IndexedDBDispatcher::RequestIDBCursorAdvance(
     unsigned long count,
     WebIDBCallbacks* callbacks_ptr,
-    int32 ipc_cursor_id,
-    WebExceptionCode* ec) {
+    int32 ipc_cursor_id) {
   // Reset all cursor prefetch caches except for this cursor.
   ResetCursorPrefetchCaches(ipc_cursor_id);
 
@@ -196,8 +196,7 @@
 void IndexedDBDispatcher::RequestIDBCursorContinue(
     const IndexedDBKey& key,
     WebIDBCallbacks* callbacks_ptr,
-    int32 ipc_cursor_id,
-    WebExceptionCode* ec) {
+    int32 ipc_cursor_id) {
   // Reset all cursor prefetch caches except for this cursor.
   ResetCursorPrefetchCaches(ipc_cursor_id);
 
@@ -212,8 +211,7 @@
 void IndexedDBDispatcher::RequestIDBCursorPrefetch(
     int n,
     WebIDBCallbacks* callbacks_ptr,
-    int32 ipc_cursor_id,
-    WebExceptionCode* ec) {
+    int32 ipc_cursor_id) {
   scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
 
   int32 ipc_callbacks_id = pending_callbacks_.Add(callbacks.release());
@@ -230,8 +228,7 @@
 
 void IndexedDBDispatcher::RequestIDBCursorDelete(
     WebIDBCallbacks* callbacks_ptr,
-    int32 ipc_cursor_id,
-    WebExceptionCode* ec) {
+    int32 ipc_cursor_id) {
   ResetCursorPrefetchCaches();
   scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
 
@@ -243,54 +240,21 @@
 void IndexedDBDispatcher::RequestIDBFactoryOpen(
     const string16& name,
     int64 version,
-    WebIDBCallbacks* callbacks_ptr,
-    WebIDBDatabaseCallbacks* database_callbacks_ptr,
-    const string16& origin,
-    WebFrame* web_frame) {
-  ResetCursorPrefetchCaches();
-  scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
-  scoped_ptr<WebIDBDatabaseCallbacks>
-      database_callbacks(database_callbacks_ptr);
-
-  if (!CurrentWorkerId() &&
-      !ChildThread::current()->IsWebFrameValid(web_frame))
-    return;
-
-  IndexedDBHostMsg_FactoryOpen_Params params;
-  params.ipc_thread_id = CurrentWorkerId();
-  params.ipc_callbacks_id = pending_callbacks_.Add(callbacks.release());
-  params.ipc_database_callbacks_id = pending_database_callbacks_.Add(
-      database_callbacks.release());
-  params.origin = origin;
-  params.name = name;
-  params.transaction_id = 0;
-  params.version = version;
-  Send(new IndexedDBHostMsg_FactoryOpen(params));
-}
-
-void IndexedDBDispatcher::RequestIDBFactoryOpen(
-    const string16& name,
-    int64 version,
     int64 transaction_id,
     WebIDBCallbacks* callbacks_ptr,
     WebIDBDatabaseCallbacks* database_callbacks_ptr,
-    const string16& origin,
-    WebFrame* web_frame) {
+    const string16& database_identifier) {
   ResetCursorPrefetchCaches();
   scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
   scoped_ptr<WebIDBDatabaseCallbacks>
       database_callbacks(database_callbacks_ptr);
 
-  if (!CurrentWorkerId() &&
-      !ChildThread::current()->IsWebFrameValid(web_frame))
-    return;
-
   IndexedDBHostMsg_FactoryOpen_Params params;
   params.ipc_thread_id = CurrentWorkerId();
   params.ipc_callbacks_id = pending_callbacks_.Add(callbacks.release());
   params.ipc_database_callbacks_id = pending_database_callbacks_.Add(
       database_callbacks.release());
-  params.origin = origin;
+  params.database_identifier = database_identifier;
   params.name = name;
   params.transaction_id = transaction_id;
   params.version = version;
@@ -299,38 +263,28 @@
 
 void IndexedDBDispatcher::RequestIDBFactoryGetDatabaseNames(
     WebIDBCallbacks* callbacks_ptr,
-    const string16& origin,
-    WebFrame* web_frame) {
+    const string16& database_identifier) {
   ResetCursorPrefetchCaches();
   scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
 
-  if (!CurrentWorkerId() &&
-      !ChildThread::current()->IsWebFrameValid(web_frame))
-    return;
-
   IndexedDBHostMsg_FactoryGetDatabaseNames_Params params;
   params.ipc_thread_id = CurrentWorkerId();
   params.ipc_callbacks_id = pending_callbacks_.Add(callbacks.release());
-  params.origin = origin;
+  params.database_identifier = database_identifier;
   Send(new IndexedDBHostMsg_FactoryGetDatabaseNames(params));
 }
 
 void IndexedDBDispatcher::RequestIDBFactoryDeleteDatabase(
     const string16& name,
     WebIDBCallbacks* callbacks_ptr,
-    const string16& origin,
-    WebFrame* web_frame) {
+    const string16& database_identifier) {
   ResetCursorPrefetchCaches();
   scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
 
-  if (!CurrentWorkerId() &&
-      !ChildThread::current()->IsWebFrameValid(web_frame))
-    return;
-
   IndexedDBHostMsg_FactoryDeleteDatabase_Params params;
   params.ipc_thread_id = CurrentWorkerId();
   params.ipc_callbacks_id = pending_callbacks_.Add(callbacks.release());
-  params.origin = origin;
+  params.database_identifier = database_identifier;
   params.name = name;
   Send(new IndexedDBHostMsg_FactoryDeleteDatabase(params));
 }
@@ -558,11 +512,7 @@
   WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(ipc_callbacks_id);
   if (!callbacks)
     return;
-  WebDOMStringList string_list;
-  for (std::vector<string16>::const_iterator it = value.begin();
-       it != value.end(); ++it)
-      string_list.append(*it);
-  callbacks->onSuccess(string_list);
+  callbacks->onSuccess(WebVector<WebString>(value));
   pending_callbacks_.Remove(ipc_callbacks_id);
 }
 
diff --git a/content/common/indexed_db/indexed_db_dispatcher.h b/content/common/indexed_db/indexed_db_dispatcher.h
index bf17dba..a9a287c 100644
--- a/content/common/indexed_db/indexed_db_dispatcher.h
+++ b/content/common/indexed_db/indexed_db_dispatcher.h
@@ -13,11 +13,10 @@
 #include "base/nullable_string16.h"
 #include "content/common/content_export.h"
 #include "ipc/ipc_sync_message_filter.h"
-#include "third_party/WebKit/Source/WebKit/chromium/public/WebExceptionCode.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/WebIDBDatabase.h"
-#include "third_party/WebKit/Source/WebKit/chromium/public/WebIDBDatabaseCallbacks.h"
+#include "third_party/WebKit/Source/Platform/chromium/public/WebIDBCallbacks.h"
+#include "third_party/WebKit/Source/Platform/chromium/public/WebIDBCursor.h"
+#include "third_party/WebKit/Source/Platform/chromium/public/WebIDBDatabase.h"
+#include "third_party/WebKit/Source/Platform/chromium/public/WebIDBDatabaseCallbacks.h"
 #include "webkit/glue/worker_task_runner.h"
 
 struct IndexedDBDatabaseMetadata;
@@ -28,7 +27,6 @@
 
 namespace WebKit {
 class WebData;
-class WebFrame;
 }
 
 namespace content {
@@ -64,16 +62,7 @@
 
   void RequestIDBFactoryGetDatabaseNames(
       WebKit::WebIDBCallbacks* callbacks,
-      const string16& origin,
-      WebKit::WebFrame* web_frame);
-
-  void RequestIDBFactoryOpen(
-      const string16& name,
-      int64 version,
-      WebKit::WebIDBCallbacks* callbacks,
-      WebKit::WebIDBDatabaseCallbacks* database_callbacks,
-      const string16& origin,
-      WebKit::WebFrame* web_frame);
+      const string16& database_identifier);
 
   void RequestIDBFactoryOpen(
       const string16& name,
@@ -81,40 +70,34 @@
       int64 transaction_id,
       WebKit::WebIDBCallbacks* callbacks,
       WebKit::WebIDBDatabaseCallbacks* database_callbacks,
-      const string16& origin,
-      WebKit::WebFrame* web_frame);
+      const string16& database_identifier);
 
   void RequestIDBFactoryDeleteDatabase(
       const string16& name,
       WebKit::WebIDBCallbacks* callbacks,
-      const string16& origin,
-      WebKit::WebFrame* web_frame);
+      const string16& database_identifier);
 
   void RequestIDBCursorAdvance(
       unsigned long count,
       WebKit::WebIDBCallbacks* callbacks_ptr,
-      int32 ipc_cursor_id,
-      WebKit::WebExceptionCode* ec);
+      int32 ipc_cursor_id);
 
   virtual void RequestIDBCursorContinue(
       const IndexedDBKey& key,
       WebKit::WebIDBCallbacks* callbacks_ptr,
-      int32 ipc_cursor_id,
-      WebKit::WebExceptionCode* ec);
+      int32 ipc_cursor_id);
 
   virtual void RequestIDBCursorPrefetch(
       int n,
       WebKit::WebIDBCallbacks* callbacks_ptr,
-      int32 ipc_cursor_id,
-      WebKit::WebExceptionCode* ec);
+      int32 ipc_cursor_id);
 
   void RequestIDBCursorPrefetchReset(int used_prefetches, int unused_prefetches,
                                      int32 ipc_cursor_id);
 
   void RequestIDBCursorDelete(
       WebKit::WebIDBCallbacks* callbacks_ptr,
-      int32 ipc_cursor_id,
-      WebKit::WebExceptionCode* ec);
+      int32 ipc_cursor_id);
 
   void RequestIDBDatabaseClose(
       int32 ipc_database_id,
diff --git a/content/common/indexed_db/indexed_db_dispatcher_unittest.cc b/content/common/indexed_db/indexed_db_dispatcher_unittest.cc
index 3d815c9..f9be36d 100644
--- a/content/common/indexed_db/indexed_db_dispatcher_unittest.cc
+++ b/content/common/indexed_db/indexed_db_dispatcher_unittest.cc
@@ -8,7 +8,7 @@
 #include "content/common/indexed_db/indexed_db_key.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/WebKit/Source/Platform/chromium/public/WebData.h"
-#include "third_party/WebKit/Source/WebKit/chromium/public/WebIDBCallbacks.h"
+#include "third_party/WebKit/Source/Platform/chromium/public/WebIDBCallbacks.h"
 
 using WebKit::WebData;
 using WebKit::WebIDBCallbacks;
diff --git a/content/common/indexed_db/indexed_db_key.h b/content/common/indexed_db/indexed_db_key.h
index 0e11bf9..4a546f4 100644
--- a/content/common/indexed_db/indexed_db_key.h
+++ b/content/common/indexed_db/indexed_db_key.h
@@ -10,7 +10,7 @@
 #include "base/basictypes.h"
 #include "base/string16.h"
 #include "content/common/content_export.h"
-#include "third_party/WebKit/Source/WebKit/chromium/public/WebIDBKey.h"
+#include "third_party/WebKit/Source/Platform/chromium/public/WebIDBKey.h"
 
 namespace content {
 
diff --git a/content/common/indexed_db/indexed_db_key_path.h b/content/common/indexed_db/indexed_db_key_path.h
index fd44e60..185c894 100644
--- a/content/common/indexed_db/indexed_db_key_path.h
+++ b/content/common/indexed_db/indexed_db_key_path.h
@@ -10,7 +10,7 @@
 #include "base/basictypes.h"
 #include "base/string16.h"
 #include "content/common/content_export.h"
-#include "third_party/WebKit/Source/WebKit/chromium/public/WebIDBKeyPath.h"
+#include "third_party/WebKit/Source/Platform/chromium/public/WebIDBKeyPath.h"
 
 namespace content {
 
diff --git a/content/common/indexed_db/indexed_db_key_range.h b/content/common/indexed_db/indexed_db_key_range.h
index dd390f5..9cc9043 100644
--- a/content/common/indexed_db/indexed_db_key_range.h
+++ b/content/common/indexed_db/indexed_db_key_range.h
@@ -8,7 +8,7 @@
 #include "base/basictypes.h"
 #include "content/common/content_export.h"
 #include "content/common/indexed_db/indexed_db_key.h"
-#include "third_party/WebKit/Source/WebKit/chromium/public/WebIDBKeyRange.h"
+#include "third_party/WebKit/Source/Platform/chromium/public/WebIDBKeyRange.h"
 
 namespace content {
 
diff --git a/content/common/indexed_db/indexed_db_message_filter.cc b/content/common/indexed_db/indexed_db_message_filter.cc
index 189f568..29265c3 100644
--- a/content/common/indexed_db/indexed_db_message_filter.cc
+++ b/content/common/indexed_db/indexed_db_message_filter.cc
@@ -8,6 +8,7 @@
 #include "base/location.h"
 #include "base/message_loop_proxy.h"
 #include "base/pickle.h"
+#include "content/common/child_thread.h"
 #include "content/common/indexed_db/indexed_db_dispatcher.h"
 #include "content/common/indexed_db/indexed_db_messages.h"
 #include "webkit/glue/worker_task_runner.h"
@@ -28,10 +29,15 @@
   DCHECK(result);
   base::Closure closure = base::Bind(
       &IndexedDBMessageFilter::DispatchMessage, this, msg);
-  if (ipc_thread_id)
-    WorkerTaskRunner::Instance()->PostTask(ipc_thread_id, closure);
-  else
+  if (!ipc_thread_id) {
     main_thread_loop_proxy_->PostTask(FROM_HERE, closure);
+    return true;
+  }
+  if (WorkerTaskRunner::Instance()->PostTask(ipc_thread_id, closure))
+    return true;
+
+  // Message for a terminated worker - perform necessary cleanup
+  OnStaleMessageReceived(msg);
   return true;
 }
 
@@ -41,4 +47,33 @@
   IndexedDBDispatcher::ThreadSpecificInstance()->OnMessageReceived(msg);
 }
 
+void IndexedDBMessageFilter::OnStaleMessageReceived(const IPC::Message& msg) {
+  IPC_BEGIN_MESSAGE_MAP(IndexedDBMessageFilter, msg)
+    IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessIDBDatabase,
+                        OnStaleSuccessIDBDatabase)
+    IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksUpgradeNeeded,
+                        OnStaleUpgradeNeeded)
+  IPC_END_MESSAGE_MAP()
+}
+
+void IndexedDBMessageFilter::OnStaleSuccessIDBDatabase(
+    int32 ipc_thread_id,
+    int32 ipc_callbacks_id,
+    int32 ipc_database_callbacks_id,
+    int32 ipc_database_id,
+    const IndexedDBDatabaseMetadata& idb_metadata) {
+  scoped_refptr<IPC::SyncMessageFilter> filter(
+      ChildThread::current()->sync_message_filter());
+  filter->Send(
+      new IndexedDBHostMsg_DatabaseClose(ipc_database_id));
+}
+
+void IndexedDBMessageFilter::OnStaleUpgradeNeeded(
+    const IndexedDBMsg_CallbacksUpgradeNeeded_Params& p) {
+  scoped_refptr<IPC::SyncMessageFilter> filter(
+      ChildThread::current()->sync_message_filter());
+  filter->Send(
+      new IndexedDBHostMsg_DatabaseClose(p.ipc_database_id));
+}
+
 }  // namespace content
diff --git a/content/common/indexed_db/indexed_db_message_filter.h b/content/common/indexed_db/indexed_db_message_filter.h
index 749564b..d09af93 100644
--- a/content/common/indexed_db/indexed_db_message_filter.h
+++ b/content/common/indexed_db/indexed_db_message_filter.h
@@ -7,6 +7,9 @@
 
 #include "ipc/ipc_channel_proxy.h"
 
+struct IndexedDBDatabaseMetadata;
+struct IndexedDBMsg_CallbacksUpgradeNeeded_Params;
+
 namespace base {
 class MessageLoopProxy;
 }  // namespace base
@@ -26,6 +29,14 @@
 
  private:
   void DispatchMessage(const IPC::Message& msg);
+  void OnStaleMessageReceived(const IPC::Message& msg);
+  void OnStaleSuccessIDBDatabase(int32 ipc_thread_id,
+                                 int32 ipc_callbacks_id,
+                                 int32 ipc_database_callbacks_id,
+                                 int32 ipc_object_id,
+                                 const IndexedDBDatabaseMetadata&);
+  void OnStaleUpgradeNeeded(const IndexedDBMsg_CallbacksUpgradeNeeded_Params&);
+
   scoped_refptr<base::MessageLoopProxy> main_thread_loop_proxy_;
 
   DISALLOW_COPY_AND_ASSIGN(IndexedDBMessageFilter);
diff --git a/content/common/indexed_db/indexed_db_messages.h b/content/common/indexed_db/indexed_db_messages.h
index 0e2d61c..54c8403 100644
--- a/content/common/indexed_db/indexed_db_messages.h
+++ b/content/common/indexed_db/indexed_db_messages.h
@@ -12,10 +12,9 @@
 #include "content/common/indexed_db/indexed_db_param_traits.h"
 #include "ipc/ipc_message_macros.h"
 #include "ipc/ipc_param_traits.h"
-#include "third_party/WebKit/Source/WebKit/chromium/public/WebExceptionCode.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/WebIDBMetadata.h"
+#include "third_party/WebKit/Source/Platform/chromium/public/WebIDBCursor.h"
+#include "third_party/WebKit/Source/Platform/chromium/public/WebIDBDatabase.h"
+#include "third_party/WebKit/Source/Platform/chromium/public/WebIDBMetadata.h"
 
 #define IPC_MESSAGE_START IndexedDBMsgStart
 
@@ -30,8 +29,8 @@
   // The response should have these ids.
   IPC_STRUCT_MEMBER(int32, ipc_thread_id)
   IPC_STRUCT_MEMBER(int32, ipc_callbacks_id)
-  // The origin doing the initiating.
-  IPC_STRUCT_MEMBER(string16, origin)
+  // The string id of the origin doing the initiating.
+  IPC_STRUCT_MEMBER(string16, database_identifier)
 IPC_STRUCT_END()
 
 // Used to open an indexed database.
@@ -42,8 +41,8 @@
   IPC_STRUCT_MEMBER(int32, ipc_callbacks_id)
   // Identifier for database callbacks
   IPC_STRUCT_MEMBER(int32, ipc_database_callbacks_id)
-  // The origin doing the initiating.
-  IPC_STRUCT_MEMBER(string16, origin)
+  // The string id of the origin doing the initiating.
+  IPC_STRUCT_MEMBER(string16, database_identifier)
   // The name of the database.
   IPC_STRUCT_MEMBER(string16, name)
   // The transaction id used if a database upgrade is needed.
@@ -57,8 +56,8 @@
   // The response should have these ids.
   IPC_STRUCT_MEMBER(int32, ipc_thread_id)
   IPC_STRUCT_MEMBER(int32, ipc_callbacks_id)
-  // The origin doing the initiating.
-  IPC_STRUCT_MEMBER(string16, origin)
+  // The string id of the origin doing the initiating.
+  IPC_STRUCT_MEMBER(string16, database_identifier)
   // The name of the database.
   IPC_STRUCT_MEMBER(string16, name)
 IPC_STRUCT_END()
diff --git a/content/common/indexed_db/proxy_webidbcursor_impl.cc b/content/common/indexed_db/proxy_webidbcursor_impl.cc
index 56810a4..16ccf6b 100644
--- a/content/common/indexed_db/proxy_webidbcursor_impl.cc
+++ b/content/common/indexed_db/proxy_webidbcursor_impl.cc
@@ -11,7 +11,6 @@
 #include "content/common/indexed_db/indexed_db_dispatcher.h"
 
 using WebKit::WebData;
-using WebKit::WebExceptionCode;
 using WebKit::WebIDBCallbacks;
 using WebKit::WebIDBKey;
 
@@ -42,19 +41,18 @@
 }
 
 void RendererWebIDBCursorImpl::advance(unsigned long count,
-                                       WebIDBCallbacks* callbacks_ptr,
-                                       WebExceptionCode& ec) {
+                                       WebIDBCallbacks* callbacks_ptr) {
   IndexedDBDispatcher* dispatcher =
       IndexedDBDispatcher::ThreadSpecificInstance();
   scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
   ResetPrefetchCache();
   dispatcher->RequestIDBCursorAdvance(count, callbacks.release(),
-                                      ipc_cursor_id_, &ec);
+                                      ipc_cursor_id_);
 }
 
-void RendererWebIDBCursorImpl::continueFunction(const WebIDBKey& key,
-                                                WebIDBCallbacks* callbacks_ptr,
-                                                WebExceptionCode& ec) {
+void RendererWebIDBCursorImpl::continueFunction(
+    const WebIDBKey& key,
+    WebIDBCallbacks* callbacks_ptr) {
   IndexedDBDispatcher* dispatcher =
       IndexedDBDispatcher::ThreadSpecificInstance();
   scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
@@ -74,7 +72,7 @@
       ++pending_onsuccess_callbacks_;
       dispatcher->RequestIDBCursorPrefetch(prefetch_amount_,
                                            callbacks.release(),
-                                           ipc_cursor_id_, &ec);
+                                           ipc_cursor_id_);
 
       // Increase prefetch_amount_ exponentially.
       prefetch_amount_ *= 2;
@@ -90,14 +88,13 @@
 
   dispatcher->RequestIDBCursorContinue(IndexedDBKey(key),
                                        callbacks.release(),
-                                       ipc_cursor_id_, &ec);
+                                       ipc_cursor_id_);
 }
 
-void RendererWebIDBCursorImpl::deleteFunction(WebIDBCallbacks* callbacks,
-                                              WebExceptionCode& ec) {
+void RendererWebIDBCursorImpl::deleteFunction(WebIDBCallbacks* callbacks) {
   IndexedDBDispatcher* dispatcher =
       IndexedDBDispatcher::ThreadSpecificInstance();
-  dispatcher->RequestIDBCursorDelete(callbacks, ipc_cursor_id_, &ec);
+  dispatcher->RequestIDBCursorDelete(callbacks, ipc_cursor_id_);
 }
 
 void RendererWebIDBCursorImpl::postSuccessHandlerCallback() {
diff --git a/content/common/indexed_db/proxy_webidbcursor_impl.h b/content/common/indexed_db/proxy_webidbcursor_impl.h
index 0383cbe..1fc72e0 100644
--- a/content/common/indexed_db/proxy_webidbcursor_impl.h
+++ b/content/common/indexed_db/proxy_webidbcursor_impl.h
@@ -14,9 +14,9 @@
 #include "content/common/content_export.h"
 #include "content/common/indexed_db/indexed_db_key.h"
 #include "third_party/WebKit/Source/Platform/chromium/public/WebData.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/WebIDBKey.h"
+#include "third_party/WebKit/Source/Platform/chromium/public/WebIDBCallbacks.h"
+#include "third_party/WebKit/Source/Platform/chromium/public/WebIDBCursor.h"
+#include "third_party/WebKit/Source/Platform/chromium/public/WebIDBKey.h"
 
 namespace content {
 
@@ -27,13 +27,10 @@
   virtual ~RendererWebIDBCursorImpl();
 
   virtual void advance(unsigned long count,
-                       WebKit::WebIDBCallbacks* callback,
-                       WebKit::WebExceptionCode& ec);
+                       WebKit::WebIDBCallbacks* callback);
   virtual void continueFunction(const WebKit::WebIDBKey& key,
-                                WebKit::WebIDBCallbacks* callback,
-                                WebKit::WebExceptionCode& ec);
-  virtual void deleteFunction(WebKit::WebIDBCallbacks* callback,
-                              WebKit::WebExceptionCode& ec);
+                                WebKit::WebIDBCallbacks* callback);
+  virtual void deleteFunction(WebKit::WebIDBCallbacks* callback);
   virtual void postSuccessHandlerCallback();
 
   void SetPrefetchData(
diff --git a/content/common/indexed_db/proxy_webidbcursor_impl_unittest.cc b/content/common/indexed_db/proxy_webidbcursor_impl_unittest.cc
index 0c2984e..ffbd02c 100644
--- a/content/common/indexed_db/proxy_webidbcursor_impl_unittest.cc
+++ b/content/common/indexed_db/proxy_webidbcursor_impl_unittest.cc
@@ -9,11 +9,9 @@
 #include "content/common/indexed_db/proxy_webidbcursor_impl.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/WebKit/Source/Platform/chromium/public/WebData.h"
-#include "third_party/WebKit/Source/WebKit/chromium/public/WebExceptionCode.h"
-#include "third_party/WebKit/Source/WebKit/chromium/public/WebIDBCallbacks.h"
+#include "third_party/WebKit/Source/Platform/chromium/public/WebIDBCallbacks.h"
 
 using WebKit::WebData;
-using WebKit::WebExceptionCode;
 using WebKit::WebIDBCallbacks;
 using WebKit::WebIDBDatabase;
 using WebKit::WebIDBDatabaseError;
@@ -35,8 +33,7 @@
   virtual void RequestIDBCursorPrefetch(
       int n,
       WebIDBCallbacks* callbacks,
-      int32 ipc_cursor_id,
-      WebExceptionCode*) OVERRIDE {
+      int32 ipc_cursor_id) OVERRIDE {
     ++prefetch_calls_;
     last_prefetch_count_ = n;
     callbacks_.reset(callbacks);
@@ -45,8 +42,7 @@
   virtual void RequestIDBCursorContinue(
       const IndexedDBKey&,
       WebIDBCallbacks* callbacks,
-      int32 ipc_cursor_id,
-      WebExceptionCode*) OVERRIDE {
+      int32 ipc_cursor_id) OVERRIDE {
     ++continue_calls_;
     callbacks_.reset(callbacks);
   }
@@ -91,7 +87,6 @@
 
   WebIDBKey null_key;
   null_key.assignNull();
-  WebExceptionCode ec = 0;
 
   MockDispatcher dispatcher;
 
@@ -103,8 +98,7 @@
     EXPECT_EQ(dispatcher.continue_calls(), 0);
     for (int i = 0; i < RendererWebIDBCursorImpl::kPrefetchContinueThreshold;
          ++i) {
-      cursor.continueFunction(null_key, new MockContinueCallbacks(), ec);
-      EXPECT_EQ(ec, 0);
+      cursor.continueFunction(null_key, new MockContinueCallbacks());
       EXPECT_EQ(dispatcher.continue_calls(), ++continue_calls);
       EXPECT_EQ(dispatcher.prefetch_calls(), 0);
     }
@@ -119,8 +113,7 @@
          ++repetitions) {
 
       // Initiate the prefetch
-      cursor.continueFunction(null_key, new MockContinueCallbacks(), ec);
-      EXPECT_EQ(ec, 0);
+      cursor.continueFunction(null_key, new MockContinueCallbacks());
       EXPECT_EQ(dispatcher.continue_calls(), continue_calls);
       EXPECT_EQ(dispatcher.prefetch_calls(), repetitions + 1);
 
@@ -145,8 +138,7 @@
       // Verify that the cache is used for subsequent continue() calls.
       for (int i = 0; i < prefetch_count; ++i) {
         IndexedDBKey key;
-        cursor.continueFunction(null_key, new MockContinueCallbacks(&key), ec);
-        EXPECT_EQ(ec, 0);
+        cursor.continueFunction(null_key, new MockContinueCallbacks(&key));
         EXPECT_EQ(dispatcher.continue_calls(), continue_calls);
         EXPECT_EQ(dispatcher.prefetch_calls(), repetitions + 1);
 
diff --git a/content/common/indexed_db/proxy_webidbdatabase_impl.cc b/content/common/indexed_db/proxy_webidbdatabase_impl.cc
index 81a59f9..b032b3d 100644
--- a/content/common/indexed_db/proxy_webidbdatabase_impl.cc
+++ b/content/common/indexed_db/proxy_webidbdatabase_impl.cc
@@ -7,17 +7,14 @@
 #include <vector>
 
 #include "content/common/child_thread.h"
-#include "content/common/indexed_db/indexed_db_messages.h"
 #include "content/common/indexed_db/indexed_db_dispatcher.h"
+#include "content/common/indexed_db/indexed_db_messages.h"
+#include "third_party/WebKit/Source/Platform/chromium/public/WebIDBKeyPath.h"
+#include "third_party/WebKit/Source/Platform/chromium/public/WebIDBMetadata.h"
 #include "third_party/WebKit/Source/Platform/chromium/public/WebString.h"
 #include "third_party/WebKit/Source/Platform/chromium/public/WebVector.h"
-#include "third_party/WebKit/Source/WebKit/chromium/public/WebIDBKeyPath.h"
-#include "third_party/WebKit/Source/WebKit/chromium/public/WebIDBMetadata.h"
 #include "webkit/glue/worker_task_runner.h"
 
-using WebKit::WebDOMStringList;
-using WebKit::WebExceptionCode;
-using WebKit::WebFrame;
 using WebKit::WebIDBCallbacks;
 using WebKit::WebIDBDatabaseCallbacks;
 using WebKit::WebIDBMetadata;
diff --git a/content/common/indexed_db/proxy_webidbdatabase_impl.h b/content/common/indexed_db/proxy_webidbdatabase_impl.h
index 9795516..ed6aa61 100644
--- a/content/common/indexed_db/proxy_webidbdatabase_impl.h
+++ b/content/common/indexed_db/proxy_webidbdatabase_impl.h
@@ -6,7 +6,7 @@
 #define CONTENT_COMMON_INDEXED_DB_PROXY_WEBIDBDATABASE_IMPL_H_
 
 #include "base/basictypes.h"
-#include "third_party/WebKit/Source/WebKit/chromium/public/WebIDBDatabase.h"
+#include "third_party/WebKit/Source/Platform/chromium/public/WebIDBDatabase.h"
 
 namespace WebKit {
 class WebIDBCallbacks;
diff --git a/content/common/indexed_db/proxy_webidbfactory_impl.cc b/content/common/indexed_db/proxy_webidbfactory_impl.cc
index 0b053e8..a927e44 100644
--- a/content/common/indexed_db/proxy_webidbfactory_impl.cc
+++ b/content/common/indexed_db/proxy_webidbfactory_impl.cc
@@ -7,14 +7,10 @@
 #include "content/common/indexed_db/indexed_db_dispatcher.h"
 #include "content/common/child_thread.h"
 #include "third_party/WebKit/Source/Platform/chromium/public/WebString.h"
-#include "third_party/WebKit/Source/WebKit/chromium/public/WebDOMStringList.h"
 
-using WebKit::WebDOMStringList;
-using WebKit::WebFrame;
 using WebKit::WebIDBCallbacks;
 using WebKit::WebIDBDatabase;
 using WebKit::WebIDBDatabaseCallbacks;
-using WebKit::WebSecurityOrigin;
 using WebKit::WebString;
 
 namespace content {
@@ -27,30 +23,12 @@
 
 void RendererWebIDBFactoryImpl::getDatabaseNames(
     WebIDBCallbacks* callbacks,
-    const WebSecurityOrigin& origin,
-    WebFrame* web_frame,
+    const WebString& database_identifier,
     const WebString& data_dir_unused) {
   IndexedDBDispatcher* dispatcher =
       IndexedDBDispatcher::ThreadSpecificInstance();
   dispatcher->RequestIDBFactoryGetDatabaseNames(
-      callbacks, origin.databaseIdentifier(), web_frame);
-}
-
-void RendererWebIDBFactoryImpl::open(
-    const WebString& name,
-    long long version,
-    WebIDBCallbacks* callbacks,
-    WebIDBDatabaseCallbacks* database_callbacks,
-    const WebSecurityOrigin& origin,
-    WebFrame* web_frame,
-    const WebString& data_dir) {
-  // Don't send the data_dir. We know what we want on the Browser side of
-  // things.
-  IndexedDBDispatcher* dispatcher =
-      IndexedDBDispatcher::ThreadSpecificInstance();
-  dispatcher->RequestIDBFactoryOpen(
-      name, version, callbacks, database_callbacks, origin.databaseIdentifier(),
-      web_frame);
+      callbacks, database_identifier);
 }
 
 void RendererWebIDBFactoryImpl::open(
@@ -59,8 +37,7 @@
     long long transaction_id,
     WebIDBCallbacks* callbacks,
     WebIDBDatabaseCallbacks* database_callbacks,
-    const WebSecurityOrigin& origin,
-    WebFrame* web_frame,
+    const WebString& database_identifier,
     const WebString& data_dir) {
   // Don't send the data_dir. We know what we want on the Browser side of
   // things.
@@ -68,22 +45,20 @@
       IndexedDBDispatcher::ThreadSpecificInstance();
   dispatcher->RequestIDBFactoryOpen(
       name, version, transaction_id, callbacks, database_callbacks,
-      origin.databaseIdentifier(),
-      web_frame);
+      database_identifier);
 }
 
 void RendererWebIDBFactoryImpl::deleteDatabase(
     const WebString& name,
     WebIDBCallbacks* callbacks,
-    const WebSecurityOrigin& origin,
-    WebFrame* web_frame,
+    const WebString& database_identifier,
     const WebString& data_dir) {
   // Don't send the data_dir. We know what we want on the Browser side of
   // things.
   IndexedDBDispatcher* dispatcher =
       IndexedDBDispatcher::ThreadSpecificInstance();
   dispatcher->RequestIDBFactoryDeleteDatabase(
-      name, callbacks, origin.databaseIdentifier(), web_frame);
+      name, callbacks, database_identifier);
 }
 
 }  // namespace content
diff --git a/content/common/indexed_db/proxy_webidbfactory_impl.h b/content/common/indexed_db/proxy_webidbfactory_impl.h
index e550b05..b50a162 100644
--- a/content/common/indexed_db/proxy_webidbfactory_impl.h
+++ b/content/common/indexed_db/proxy_webidbfactory_impl.h
@@ -5,14 +5,12 @@
 #ifndef CONTENT_COMMON_INDEXED_DB_PROXY_WEBIDBFACTORY_IMPL_H_
 #define CONTENT_COMMON_INDEXED_DB_PROXY_WEBIDBFACTORY_IMPL_H_
 
+#include "third_party/WebKit/Source/Platform/chromium/public/WebIDBCallbacks.h"
+#include "third_party/WebKit/Source/Platform/chromium/public/WebIDBDatabaseCallbacks.h"
+#include "third_party/WebKit/Source/Platform/chromium/public/WebIDBFactory.h"
 #include "third_party/WebKit/Source/Platform/chromium/public/WebVector.h"
-#include "third_party/WebKit/Source/WebKit/chromium/public/WebIDBCallbacks.h"
-#include "third_party/WebKit/Source/WebKit/chromium/public/WebIDBDatabaseCallbacks.h"
-#include "third_party/WebKit/Source/WebKit/chromium/public/WebIDBFactory.h"
 
 namespace WebKit {
-class WebFrame;
-class WebSecurityOrigin;
 class WebString;
 }
 
@@ -26,16 +24,7 @@
   // See WebIDBFactory.h for documentation on these functions.
   virtual void getDatabaseNames(
       WebKit::WebIDBCallbacks* callbacks,
-      const WebKit::WebSecurityOrigin& origin,
-      WebKit::WebFrame* web_frame,
-      const WebKit::WebString& data_dir);
-  virtual void open(
-      const WebKit::WebString& name,
-      long long version,
-      WebKit::WebIDBCallbacks* callbacks,
-      WebKit::WebIDBDatabaseCallbacks* databaseCallbacks,
-      const WebKit::WebSecurityOrigin& origin,
-      WebKit::WebFrame* web_frame,
+      const WebKit::WebString& database_identifier,
       const WebKit::WebString& data_dir);
   virtual void open(
       const WebKit::WebString& name,
@@ -43,14 +32,12 @@
       long long transaction_id,
       WebKit::WebIDBCallbacks* callbacks,
       WebKit::WebIDBDatabaseCallbacks* databaseCallbacks,
-      const WebKit::WebSecurityOrigin& origin,
-      WebKit::WebFrame* web_frame,
+      const WebKit::WebString& database_identifier,
       const WebKit::WebString& data_dir);
   virtual void deleteDatabase(
       const WebKit::WebString& name,
       WebKit::WebIDBCallbacks* callbacks,
-      const WebKit::WebSecurityOrigin& origin,
-      WebKit::WebFrame* web_frame,
+      const WebKit::WebString& database_identifier,
       const WebKit::WebString& data_dir);
 };
 
diff --git a/content/common/input_messages.h b/content/common/input_messages.h
new file mode 100644
index 0000000..2c9c0b9
--- /dev/null
+++ b/content/common/input_messages.h
@@ -0,0 +1,135 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// IPC messages for input events and other messages that require processing in
+// order relative to input events.
+// Multiply-included message file, hence no include guard.
+
+#include "base/string16.h"
+#include "content/common/content_export.h"
+#include "content/common/content_param_traits.h"
+#include "content/common/edit_command.h"
+#include "content/port/common/input_event_ack_state.h"
+#include "content/public/common/common_param_traits.h"
+#include "ipc/ipc_message_macros.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h"
+#include "ui/gfx/point.h"
+#include "ui/gfx/rect.h"
+
+#undef IPC_MESSAGE_EXPORT
+#define IPC_MESSAGE_EXPORT CONTENT_EXPORT
+
+#ifdef IPC_MESSAGE_START
+#error IPC_MESSAGE_START
+#endif
+
+#define IPC_MESSAGE_START InputMsgStart
+
+IPC_ENUM_TRAITS(content::InputEventAckState)
+
+IPC_STRUCT_TRAITS_BEGIN(content::EditCommand)
+  IPC_STRUCT_TRAITS_MEMBER(name)
+  IPC_STRUCT_TRAITS_MEMBER(value)
+IPC_STRUCT_TRAITS_END()
+
+// Sends an input event to the render widget.
+IPC_MESSAGE_ROUTED2(InputMsg_HandleInputEvent,
+                    IPC::WebInputEventPointer /* event */,
+                    bool /* is_keyboard_shortcut */)
+
+// Sends the cursor visibility state to the render widget.
+IPC_MESSAGE_ROUTED1(InputMsg_CursorVisibilityChange,
+                    bool /* is_visible */)
+
+// This message notifies the renderer that the next key event is bound to one
+// or more pre-defined edit commands. If the next key event is not handled
+// by webkit, the specified edit commands shall be executed against current
+// focused frame.
+// Parameters
+// * edit_commands (see chrome/common/edit_command_types.h)
+//   Contains one or more edit commands.
+// 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.
+IPC_MESSAGE_ROUTED1(InputMsg_SetEditCommandsForNextKeyEvent,
+                    std::vector<content::EditCommand> /* edit_commands */)
+
+// Message payload is the name/value of a WebCore edit command to execute.
+IPC_MESSAGE_ROUTED2(InputMsg_ExecuteEditCommand,
+                    std::string, /* name */
+                    std::string /* value */)
+
+IPC_MESSAGE_ROUTED0(InputMsg_MouseCaptureLost)
+
+// TODO(darin): figure out how this meshes with RestoreFocus
+IPC_MESSAGE_ROUTED1(InputMsg_SetFocus,
+                    bool /* enable */)
+
+// Tells the renderer to focus the first (last if reverse is true) focusable
+// node.
+IPC_MESSAGE_ROUTED1(InputMsg_SetInitialFocus,
+                    bool /* reverse */)
+
+// Tells the renderer to scroll the currently focused node into rect only if
+// the currently focused node is a Text node (textfield, text area or content
+// editable divs).
+IPC_MESSAGE_ROUTED1(InputMsg_ScrollFocusedEditableNodeIntoRect, gfx::Rect)
+
+// These messages are typically generated from context menus and request the
+// renderer to apply the specified operation to the current selection.
+IPC_MESSAGE_ROUTED0(InputMsg_Undo)
+IPC_MESSAGE_ROUTED0(InputMsg_Redo)
+IPC_MESSAGE_ROUTED0(InputMsg_Cut)
+IPC_MESSAGE_ROUTED0(InputMsg_Copy)
+#if defined(OS_MACOSX)
+IPC_MESSAGE_ROUTED0(InputMsg_CopyToFindPboard)
+#endif
+IPC_MESSAGE_ROUTED0(InputMsg_Paste)
+IPC_MESSAGE_ROUTED0(InputMsg_PasteAndMatchStyle)
+// Replaces the selected region or a word around the cursor with the
+// specified string.
+IPC_MESSAGE_ROUTED1(InputMsg_Replace,
+                    string16)
+// Replaces the misspelling in the selected region with the specified string.
+IPC_MESSAGE_ROUTED1(InputMsg_ReplaceMisspelling,
+                    string16)
+IPC_MESSAGE_ROUTED0(InputMsg_Delete)
+IPC_MESSAGE_ROUTED0(InputMsg_SelectAll)
+
+IPC_MESSAGE_ROUTED0(InputMsg_Unselect)
+
+// Requests the renderer to select the region between two points.
+// Expects a SelectRange_ACK message when finished.
+IPC_MESSAGE_ROUTED2(InputMsg_SelectRange,
+                    gfx::Point /* start */,
+                    gfx::Point /* end */)
+
+// Requests the renderer to move the caret selection toward the point.
+// Expects a MoveCaret_ACK message when finished.
+IPC_MESSAGE_ROUTED1(InputMsg_MoveCaret,
+                    gfx::Point /* location */)
+
+#if defined(OS_ANDROID)
+// Sent when the user clicks on the find result bar to activate a find result.
+// The point (x,y) is in fractions of the content document's width and height.
+IPC_MESSAGE_ROUTED3(InputMsg_ActivateNearestFindResult,
+                    int /* request_id */,
+                    float /* x */,
+                    float /* y */)
+#endif
+
+// -----------------------------------------------------------------------------
+// Messages sent from the renderer to the browser.
+
+// Acknowledges receipt of a InputMsg_HandleInputEvent message.
+IPC_MESSAGE_ROUTED2(InputHostMsg_HandleInputEvent_ACK,
+                    WebKit::WebInputEvent::Type,
+                    content::InputEventAckState /* ack_result */)
+
+
+// Adding a new message? Stick to the sort order above: first platform
+// independent InputMsg, then ifdefs for platform specific InputMsg, then
+// platform independent InputHostMsg, then ifdefs for platform specific
+// InputHostMsg.
diff --git a/content/common/inter_process_time_ticks_converter.cc b/content/common/inter_process_time_ticks_converter.cc
index 6ae309c..de3fb13 100644
--- a/content/common/inter_process_time_ticks_converter.cc
+++ b/content/common/inter_process_time_ticks_converter.cc
@@ -48,7 +48,7 @@
 }
 
 LocalTimeTicks InterProcessTimeTicksConverter::ToLocalTimeTicks(
-    const RemoteTimeTicks& remote_ms) {
+    const RemoteTimeTicks& remote_ms) const {
   // If input time is "null", return another "null" time.
   if (remote_ms.value_ == 0)
     return LocalTimeTicks(0);
@@ -60,12 +60,12 @@
 }
 
 LocalTimeDelta InterProcessTimeTicksConverter::ToLocalTimeDelta(
-    const RemoteTimeDelta& remote_delta) {
+    const RemoteTimeDelta& remote_delta) const {
   DCHECK_GE(remote_upper_bound_, remote_lower_bound_ + remote_delta.value_);
   return LocalTimeDelta(Convert(remote_delta.value_));
 }
 
-int64 InterProcessTimeTicksConverter::Convert(int64 value) {
+int64 InterProcessTimeTicksConverter::Convert(int64 value) const {
   if (value <= 0) {
     return value;
   }
diff --git a/content/common/inter_process_time_ticks_converter.h b/content/common/inter_process_time_ticks_converter.h
index cd95594..d1d405f 100644
--- a/content/common/inter_process_time_ticks_converter.h
+++ b/content/common/inter_process_time_ticks_converter.h
@@ -55,14 +55,14 @@
 
   // Returns the value within the local's bounds that correlates to
   // |remote_ms|.
-  LocalTimeTicks ToLocalTimeTicks(const RemoteTimeTicks& remote_ms);
+  LocalTimeTicks ToLocalTimeTicks(const RemoteTimeTicks& remote_ms) const;
 
   // Returns the equivalent delta after applying remote-to-local scaling to
   // |remote_delta|.
-  LocalTimeDelta ToLocalTimeDelta(const RemoteTimeDelta& remote_delta);
+  LocalTimeDelta ToLocalTimeDelta(const RemoteTimeDelta& remote_delta) const;
 
  private:
-  int64 Convert(int64 value);
+  int64 Convert(int64 value) const;
 
   // The local time which |remote_lower_bound_| is mapped to.
   int64 local_base_time_;
diff --git a/content/common/mac/attributed_string_coder.mm b/content/common/mac/attributed_string_coder.mm
index 78a1efb..a2c1f50 100644
--- a/content/common/mac/attributed_string_coder.mm
+++ b/content/common/mac/attributed_string_coder.mm
@@ -8,7 +8,7 @@
 
 #include "base/logging.h"
 #include "base/memory/scoped_nsobject.h"
-#include "base/sys_string_conversions.h"
+#include "base/strings/sys_string_conversions.h"
 #include "base/utf_string_conversions.h"
 #include "content/common/view_messages.h"
 #include "content/public/common/common_param_traits.h"
diff --git a/content/common/mac/font_descriptor.mm b/content/common/mac/font_descriptor.mm
index 65ab40e..3b5a577 100644
--- a/content/common/mac/font_descriptor.mm
+++ b/content/common/mac/font_descriptor.mm
@@ -6,7 +6,7 @@
 
 #include <Cocoa/Cocoa.h>
 
-#include "base/sys_string_conversions.h"
+#include "base/strings/sys_string_conversions.h"
 
 FontDescriptor::FontDescriptor(NSFont* font) {
   font_name = base::SysNSStringToUTF16([font fontName]);
diff --git a/content/common/mac/font_descriptor_unittest.mm b/content/common/mac/font_descriptor_unittest.mm
index f3ce5e9..9b78d37 100644
--- a/content/common/mac/font_descriptor_unittest.mm
+++ b/content/common/mac/font_descriptor_unittest.mm
@@ -8,7 +8,7 @@
 
 #include "base/logging.h"
 #include "base/utf_string_conversions.h"
-#include "base/sys_string_conversions.h"
+#include "base/strings/sys_string_conversions.h"
 #include "testing/gtest_mac.h"
 #include "testing/platform_test.h"
 
diff --git a/content/common/mac/font_loader.mm b/content/common/mac/font_loader.mm
index faf965f..1cd6fc3 100644
--- a/content/common/mac/font_loader.mm
+++ b/content/common/mac/font_loader.mm
@@ -13,7 +13,7 @@
 #include "base/mac/foundation_util.h"
 #include "base/mac/mac_util.h"
 #include "base/mac/scoped_cftyperef.h"
-#include "base/sys_string_conversions.h"
+#include "base/strings/sys_string_conversions.h"
 #include "base/threading/thread_restrictions.h"
 #include "content/common/mac/font_descriptor.h"
 
diff --git a/content/common/media/OWNERS b/content/common/media/OWNERS
index dccdcaf..e8994e1 100644
--- a/content/common/media/OWNERS
+++ b/content/common/media/OWNERS
@@ -17,3 +17,4 @@
 per-file *_messages.h=jschuh@chromium.org
 per-file *_messages.h=palmer@chromium.org
 per-file *_messages.h=tsepez@chromium.org
+per-file *_messages.h=kenrb@chromium.org
diff --git a/content/common/media/audio_messages.h b/content/common/media/audio_messages.h
index 63b81e4..dc844eb 100644
--- a/content/common/media/audio_messages.h
+++ b/content/common/media/audio_messages.h
@@ -23,6 +23,12 @@
 IPC_ENUM_TRAITS(media::AudioInputIPCDelegate::State)
 IPC_ENUM_TRAITS(media::AudioOutputIPCDelegate::State)
 
+IPC_STRUCT_BEGIN(AudioInputHostMsg_CreateStream_Config)
+  IPC_STRUCT_MEMBER(media::AudioParameters, params)
+  IPC_STRUCT_MEMBER(bool, automatic_gain_control)
+  IPC_STRUCT_MEMBER(uint32, shared_memory_count)
+IPC_STRUCT_END()
+
 // Messages sent from the browser to the renderer.
 
 // Tell the renderer process that an audio stream has been created.
@@ -87,28 +93,22 @@
 
 // Messages sent from the renderer to the browser.
 
-// Request that got sent to browser for creating an audio output stream
-IPC_MESSAGE_CONTROL2(AudioHostMsg_CreateStream,
+// Request that is sent to the browser for creating an audio output stream.
+// |render_view_id| is the routing ID for the render view producing the audio
+// data.
+IPC_MESSAGE_CONTROL3(AudioHostMsg_CreateStream,
                      int /* stream_id */,
+                     int /* render_view_id */,
                      media::AudioParameters /* params */)
 
-// Request that got sent to browser for creating an audio input stream
-IPC_MESSAGE_CONTROL5(AudioInputHostMsg_CreateStream,
+// Request that is sent to the browser for creating an audio input stream.
+// |render_view_id| is the routing ID for the render view consuming the audio
+// data.
+IPC_MESSAGE_CONTROL4(AudioInputHostMsg_CreateStream,
                      int /* stream_id */,
+                     int /* render_view_id */,
                      int /* session_id */,
-                     media::AudioParameters /* params */,
-                     bool /* automatic_gain_control */,
-                     uint32 /* shared memory count */)
-
-// Indicate that audio for a stream is produced by the specified render view.
-IPC_MESSAGE_CONTROL2(AudioHostMsg_AssociateStreamWithProducer,
-                     int /* stream_id */,
-                     int /* render_view_id */)
-
-// Indicate that audio for a stream is consumed by the specified render view.
-IPC_MESSAGE_CONTROL2(AudioInputHostMsg_AssociateStreamWithConsumer,
-                     int /* stream_id */,
-                     int /* render_view_id */)
+                     AudioInputHostMsg_CreateStream_Config)
 
 // Start buffering and play the audio stream specified by stream_id.
 IPC_MESSAGE_CONTROL1(AudioHostMsg_PlayStream,
@@ -122,10 +122,6 @@
 IPC_MESSAGE_CONTROL1(AudioHostMsg_PauseStream,
                      int /* stream_id */)
 
-// Discard all buffered audio data for the specified audio stream.
-IPC_MESSAGE_CONTROL1(AudioHostMsg_FlushStream,
-                     int /* stream_id */)
-
 // Close an audio stream specified by stream_id.
 IPC_MESSAGE_CONTROL1(AudioHostMsg_CloseStream,
                      int /* stream_id */)
diff --git a/content/common/media/media_player_messages.h b/content/common/media/media_player_messages.h
index 4cf8c3a..3df3c0c 100644
--- a/content/common/media/media_player_messages.h
+++ b/content/common/media/media_player_messages.h
@@ -11,11 +11,56 @@
 #include "content/common/content_export.h"
 #include "googleurl/src/gurl.h"
 #include "ipc/ipc_message_macros.h"
+#include "ui/gfx/rect_f.h"
 
 #undef IPC_MESSAGE_EXPORT
 #define IPC_MESSAGE_EXPORT CONTENT_EXPORT
 #define IPC_MESSAGE_START MediaPlayerMsgStart
 
+#if defined(GOOGLE_TV)
+#include "media/base/android/demuxer_stream_player_params.h"
+
+IPC_ENUM_TRAITS(media::AudioCodec)
+IPC_ENUM_TRAITS(media::DemuxerStream::Status)
+IPC_ENUM_TRAITS(media::DemuxerStream::Type)
+IPC_ENUM_TRAITS(media::VideoCodec)
+
+IPC_STRUCT_TRAITS_BEGIN(media::MediaPlayerHostMsg_DemuxerReady_Params)
+  IPC_STRUCT_TRAITS_MEMBER(audio_codec)
+  IPC_STRUCT_TRAITS_MEMBER(audio_channels)
+  IPC_STRUCT_TRAITS_MEMBER(audio_sampling_rate)
+  IPC_STRUCT_TRAITS_MEMBER(is_audio_encrypted)
+
+  IPC_STRUCT_TRAITS_MEMBER(video_codec)
+  IPC_STRUCT_TRAITS_MEMBER(video_size)
+  IPC_STRUCT_TRAITS_MEMBER(is_video_encrypted)
+
+  IPC_STRUCT_TRAITS_MEMBER(duration_ms)
+  IPC_STRUCT_TRAITS_MEMBER(key_system)
+IPC_STRUCT_TRAITS_END()
+
+IPC_STRUCT_TRAITS_BEGIN(media::MediaPlayerHostMsg_ReadFromDemuxerAck_Params)
+  IPC_STRUCT_TRAITS_MEMBER(type)
+  IPC_STRUCT_TRAITS_MEMBER(access_units)
+IPC_STRUCT_TRAITS_END()
+
+IPC_STRUCT_TRAITS_BEGIN(
+    media::MediaPlayerHostMsg_ReadFromDemuxerAck_Params::AccessUnit)
+  IPC_STRUCT_TRAITS_MEMBER(status)
+  IPC_STRUCT_TRAITS_MEMBER(end_of_stream)
+  IPC_STRUCT_TRAITS_MEMBER(data)
+  IPC_STRUCT_TRAITS_MEMBER(timestamp)
+  IPC_STRUCT_TRAITS_MEMBER(key_id)
+  IPC_STRUCT_TRAITS_MEMBER(iv)
+  IPC_STRUCT_TRAITS_MEMBER(subsamples)
+IPC_STRUCT_TRAITS_END()
+
+IPC_STRUCT_TRAITS_BEGIN(media::SubsampleEntry)
+  IPC_STRUCT_TRAITS_MEMBER(clear_bytes)
+  IPC_STRUCT_TRAITS_MEMBER(cypher_bytes)
+IPC_STRUCT_TRAITS_END()
+#endif
+
 // Messages for notifying the render process of media playback status -------
 
 // Media buffering has updated.
@@ -32,10 +77,13 @@
 IPC_MESSAGE_ROUTED1(MediaPlayerMsg_MediaPlaybackCompleted,
                     int /* player_id */)
 
-// Player is prepared.
-IPC_MESSAGE_ROUTED2(MediaPlayerMsg_MediaPrepared,
+// Media metadata has changed.
+IPC_MESSAGE_ROUTED5(MediaPlayerMsg_MediaMetadataChanged,
                     int /* player_id */,
-                    base::TimeDelta /* duration */)
+                    base::TimeDelta /* duration */,
+                    int /* width */,
+                    int /* height */,
+                    bool /* success */)
 
 // Media seek is completed.
 IPC_MESSAGE_ROUTED2(MediaPlayerMsg_MediaSeekCompleted,
@@ -73,6 +121,14 @@
 IPC_MESSAGE_ROUTED1(MediaPlayerMsg_DidMediaPlayerPause,
                     int /* player_id */)
 
+#if defined(GOOGLE_TV)
+// The media source player reads data from demuxer
+IPC_MESSAGE_ROUTED3(MediaPlayerMsg_ReadFromDemuxer,
+                    int /* player_id */,
+                    media::DemuxerStream::Type /* type */,
+                    bool /* seek_done */)
+#endif
+
 // Messages for controllering the media playback in browser process ----------
 
 // Destroy the media player object.
@@ -83,9 +139,10 @@
 IPC_MESSAGE_ROUTED0(MediaPlayerHostMsg_DestroyAllMediaPlayers)
 
 // Initialize a media player object with the given player_id.
-IPC_MESSAGE_ROUTED3(MediaPlayerHostMsg_MediaPlayerInitialize,
+IPC_MESSAGE_ROUTED4(MediaPlayerHostMsg_MediaPlayerInitialize,
                     int /* player_id */,
                     GURL /* url */,
+                    bool /* is_media_source */,
                     GURL /* first_party_for_cookies */)
 
 // Pause the player.
@@ -113,6 +170,23 @@
 IPC_MESSAGE_ROUTED1(MediaPlayerHostMsg_ExitFullscreen,
                     int /* player_id */)
 
+#if defined(GOOGLE_TV)
 // Request the player to use external surface for rendering.
 IPC_MESSAGE_ROUTED1(MediaPlayerHostMsg_RequestExternalSurface,
                     int /* player_id */)
+
+// Request the player to use external surface for rendering.
+IPC_MESSAGE_ROUTED2(MediaPlayerHostMsg_NotifyGeometryChange,
+                    int /* player_id */,
+                    gfx::RectF /* rect */)
+
+// Inform the media source player that the demuxer is ready.
+IPC_MESSAGE_ROUTED2(MediaPlayerHostMsg_DemuxerReady,
+                    int /* player_id */,
+                    media::MediaPlayerHostMsg_DemuxerReady_Params)
+
+// Sent when the data was read from the ChunkDemuxer.
+IPC_MESSAGE_ROUTED2(MediaPlayerHostMsg_ReadFromDemuxerAck,
+                    int /* player_id */,
+                    media::MediaPlayerHostMsg_ReadFromDemuxerAck_Params)
+#endif
diff --git a/content/common/media/video_capture.h b/content/common/media/video_capture.h
index 6494c8b..f6e24ba 100644
--- a/content/common/media/video_capture.h
+++ b/content/common/media/video_capture.h
@@ -20,6 +20,7 @@
   VIDEO_CAPTURE_STATE_STOPPING,
   VIDEO_CAPTURE_STATE_STOPPED,
   VIDEO_CAPTURE_STATE_ERROR,
+  VIDEO_CAPTURE_STATE_ENDED,
 };
 
 }  // namespace content
diff --git a/content/common/media/webrtc_logging_messages.h b/content/common/media/webrtc_logging_messages.h
new file mode 100644
index 0000000..d15d9ac
--- /dev/null
+++ b/content/common/media/webrtc_logging_messages.h
@@ -0,0 +1,26 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// IPC messages for WebRTC logging.
+// Multiply-included message file, hence no include guard.
+
+#include "base/shared_memory.h"
+#include "ipc/ipc_message_macros.h"
+
+#define IPC_MESSAGE_START WebRtcLoggingMsgStart
+
+// Messages sent from the renderer to the browser.
+
+// Request to open a log.
+IPC_MESSAGE_CONTROL0(WebRtcLoggingMsg_OpenLog)
+
+// Messages sent from the browser to the renderer.
+
+// Notification that a log could not be opened.
+IPC_MESSAGE_CONTROL0(WebRtcLoggingMsg_OpenLogFailed)
+
+// Notification that a log has been opened.
+IPC_MESSAGE_CONTROL2(WebRtcLoggingMsg_LogOpened,
+                     base::SharedMemoryHandle /* handle */,
+                     uint32 /* length */)
diff --git a/content/common/message_router.cc b/content/common/message_router.cc
index d3eef77..f73e654 100644
--- a/content/common/message_router.cc
+++ b/content/common/message_router.cc
@@ -42,7 +42,7 @@
 }
 
 bool MessageRouter::RouteMessage(const IPC::Message& msg) {
-  IPC::Listener* listener = ResolveRoute(msg.routing_id());
+  IPC::Listener* listener = routes_.Lookup(msg.routing_id());
   if (!listener)
     return false;
 
@@ -50,8 +50,4 @@
   return true;
 }
 
-IPC::Listener* MessageRouter::ResolveRoute(int32 routing_id) {
-  return routes_.Lookup(routing_id);
-}
-
 }  // namespace content
diff --git a/content/common/message_router.h b/content/common/message_router.h
index 0b34e0c..56acead 100644
--- a/content/common/message_router.h
+++ b/content/common/message_router.h
@@ -52,8 +52,6 @@
   void AddRoute(int32 routing_id, IPC::Listener* listener);
   void RemoveRoute(int32 routing_id);
 
-  IPC::Listener* ResolveRoute(int32 routing_id);
-
  private:
   // A list of all listeners with assigned routing IDs.
   IDMap<IPC::Listener> routes_;
diff --git a/content/common/np_channel_base.cc b/content/common/np_channel_base.cc
index a85fdb5..a1a2338 100644
--- a/content/common/np_channel_base.cc
+++ b/content/common/np_channel_base.cc
@@ -141,7 +141,7 @@
 }
 
 bool NPChannelBase::Send(IPC::Message* message) {
-  if (!channel_.get()) {
+  if (!channel_) {
     VLOG(1) << "Channel is NULL; dropping message";
     delete message;
     return false;
diff --git a/content/common/npobject_proxy.cc b/content/common/npobject_proxy.cc
index 4203b13..eb01acb 100644
--- a/content/common/npobject_proxy.cc
+++ b/content/common/npobject_proxy.cc
@@ -70,7 +70,7 @@
 }
 
 NPObjectProxy::~NPObjectProxy() {
-  if (channel_.get()) {
+  if (channel_) {
     // This NPObjectProxy instance is now invalid and should not be reused for
     // requests initiated by plugins. We may receive requests for the
     // same NPObject in the context of the outgoing NPObjectMsg_Release call.
@@ -94,7 +94,7 @@
 }
 
 bool NPObjectProxy::Send(IPC::Message* msg) {
-  if (channel_.get())
+  if (channel_)
     return channel_->Send(msg);
 
   delete msg;
diff --git a/content/common/npobject_stub.cc b/content/common/npobject_stub.cc
index 668cb08..0e677ee 100644
--- a/content/common/npobject_stub.cc
+++ b/content/common/npobject_stub.cc
@@ -58,7 +58,7 @@
 
     WebBindings::releaseObject(npobject);
 
-    MessageLoop::current()->DeleteSoon(FROM_HERE, this);
+    base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
   }
 }
 
diff --git a/content/common/p2p_messages.h b/content/common/p2p_messages.h
index 59f6a8f..6b13831 100644
--- a/content/common/p2p_messages.h
+++ b/content/common/p2p_messages.h
@@ -35,6 +35,9 @@
                      int /* socket_id */,
                      net::IPEndPoint /* socket_address */)
 
+IPC_MESSAGE_CONTROL1(P2PMsg_OnSendComplete,
+                     int /* socket_id */)
+
 IPC_MESSAGE_CONTROL1(P2PMsg_OnError,
                      int /* socket_id */)
 
diff --git a/content/common/partial_circular_buffer.cc b/content/common/partial_circular_buffer.cc
new file mode 100644
index 0000000..cba2243
--- /dev/null
+++ b/content/common/partial_circular_buffer.cc
@@ -0,0 +1,166 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/common/partial_circular_buffer.h"
+
+#include <algorithm>
+
+#include "base/logging.h"
+
+namespace content {
+
+namespace {
+
+inline uint32 Min3(uint32 a, uint32 b, uint32 c) {
+  return std::min(a, std::min(b, c));
+}
+
+}  // namespace
+
+PartialCircularBuffer::PartialCircularBuffer(void* buffer,
+                                             uint32 buffer_size)
+    : buffer_data_(reinterpret_cast<BufferData*>(buffer)),
+      memory_buffer_size_(buffer_size),
+      data_size_(0),
+      position_(0),
+      total_read_(0) {
+  uint32 header_size =
+      buffer_data_->data - reinterpret_cast<uint8*>(buffer_data_);
+  data_size_ = memory_buffer_size_ - header_size;
+
+  DCHECK(buffer_data_);
+  DCHECK_GE(memory_buffer_size_, header_size);
+  DCHECK_LE(buffer_data_->total_written, data_size_);
+  DCHECK_LT(buffer_data_->wrap_position, data_size_);
+  DCHECK_LT(buffer_data_->end_position, data_size_);
+}
+
+PartialCircularBuffer::PartialCircularBuffer(void* buffer,
+                                             uint32 buffer_size,
+                                             uint32 wrap_position)
+    : buffer_data_(reinterpret_cast<BufferData*>(buffer)),
+      memory_buffer_size_(buffer_size),
+      data_size_(0),
+      position_(0),
+      total_read_(0) {
+  uint32 header_size =
+      buffer_data_->data - reinterpret_cast<uint8*>(buffer_data_);
+  data_size_ = memory_buffer_size_ - header_size;
+
+  DCHECK(buffer_data_);
+  DCHECK_GE(memory_buffer_size_, header_size);
+  DCHECK_LT(wrap_position, data_size_);
+
+  buffer_data_->total_written = 0;
+  buffer_data_->wrap_position = wrap_position;
+  buffer_data_->end_position = 0;
+}
+
+uint32 PartialCircularBuffer::Read(void* buffer, uint32 buffer_size) {
+  DCHECK(buffer_data_);
+  if (total_read_ >= buffer_data_->total_written)
+    return 0;
+
+  uint8* buffer_uint8 = reinterpret_cast<uint8*>(buffer);
+  uint32 read = 0;
+
+  // Read from beginning part.
+  if (position_ < buffer_data_->wrap_position) {
+    uint32 to_wrap_pos = buffer_data_->wrap_position - position_;
+    uint32 to_eow = buffer_data_->total_written - total_read_;
+    uint32 to_read = Min3(buffer_size, to_wrap_pos, to_eow);
+    memcpy(buffer_uint8, buffer_data_->data + position_, to_read);
+    position_ += to_read;
+    total_read_ += to_read;
+    read += to_read;
+    if (position_ == buffer_data_->wrap_position &&
+        buffer_data_->total_written == data_size_) {
+      // We've read all the beginning part, set the position to the middle part.
+      // (The second condition above checks if the wrapping part is filled, i.e.
+      // writing has wrapped.)
+      position_ = buffer_data_->end_position;
+    }
+    if (read >= buffer_size) {
+      DCHECK_EQ(read, buffer_size);
+      return read;
+    }
+    if (read >= to_eow) {
+      DCHECK_EQ(read, to_eow);
+      DCHECK_EQ(total_read_, buffer_data_->total_written);
+      return read;
+    }
+  }
+
+  // Read from middle part.
+  DCHECK_GE(position_, buffer_data_->wrap_position);
+  if (position_ >= buffer_data_->end_position) {
+    uint32 remaining_buffer_size = buffer_size - read;
+    uint32 to_eof = data_size_ - position_;
+    uint32 to_eow = buffer_data_->total_written - total_read_;
+    uint32 to_read = Min3(remaining_buffer_size, to_eof, to_eow);
+    memcpy(buffer_uint8 + read, buffer_data_->data + position_, to_read);
+    position_ += to_read;
+    total_read_ += to_read;
+    read += to_read;
+    if (position_ == data_size_) {
+      // We've read all the middle part, set position to the end part.
+      position_ = buffer_data_->wrap_position;
+    }
+    if (read >= buffer_size) {
+      DCHECK_EQ(read, buffer_size);
+      return read;
+    }
+    if (total_read_ >= buffer_data_->total_written) {
+      DCHECK_EQ(total_read_, buffer_data_->total_written);
+      return read;
+    }
+  }
+
+  // Read from end part.
+  DCHECK_GE(position_, buffer_data_->wrap_position);
+  DCHECK_LT(position_, buffer_data_->end_position);
+  uint32 remaining_buffer_size = buffer_size - read;
+  uint32 to_eob = buffer_data_->end_position - position_;
+  uint32 to_eow = buffer_data_->total_written - total_read_;
+  uint32 to_read = Min3(remaining_buffer_size, to_eob, to_eow);
+  memcpy(buffer_uint8 + read, buffer_data_->data + position_, to_read);
+  position_ += to_read;
+  total_read_ += to_read;
+  read += to_read;
+  DCHECK_LE(read, buffer_size);
+  DCHECK_LE(total_read_, buffer_data_->total_written);
+  return read;
+}
+
+void PartialCircularBuffer::Write(const void* buffer, uint32 buffer_size) {
+  DCHECK(buffer_data_);
+  uint32 position_before_write = position_;
+
+  uint32 to_eof = data_size_ - position_;
+  uint32 to_write = std::min(buffer_size, to_eof);
+  DoWrite(buffer_data_->data + position_, buffer, to_write);
+  if (position_ >= data_size_) {
+    DCHECK_EQ(position_, data_size_);
+    position_ = buffer_data_->wrap_position;
+  }
+
+  if (to_write < buffer_size) {
+    uint32 remainder_to_write = buffer_size - to_write;
+    DCHECK_LT(position_, position_before_write);
+    DCHECK_LE(position_ + remainder_to_write, position_before_write);
+    DoWrite(buffer_data_->data + position_,
+            reinterpret_cast<const uint8*>(buffer) + to_write,
+            remainder_to_write);
+  }
+}
+
+void PartialCircularBuffer::DoWrite(void* dest, const void* src, uint32 num) {
+  memcpy(dest, src, num);
+  position_ += num;
+  buffer_data_->total_written =
+      std::min(buffer_data_->total_written + num, data_size_);
+  buffer_data_->end_position = position_;
+}
+
+}  // namespace content
diff --git a/content/common/partial_circular_buffer.h b/content/common/partial_circular_buffer.h
new file mode 100644
index 0000000..b692ac5
--- /dev/null
+++ b/content/common/partial_circular_buffer.h
@@ -0,0 +1,70 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_COMMON_PARTIAL_CIRCULAR_BUFFER_H_
+#define CONTENT_COMMON_PARTIAL_CIRCULAR_BUFFER_H_
+
+#include "base/basictypes.h"
+#include "base/gtest_prod_util.h"
+#include "content/common/content_export.h"
+
+namespace content {
+
+// A wrapper around a memory buffer that allows circular read and write with a
+// selectable wrapping position. Buffer layout (after wrap; H is header):
+// -----------------------------------------------------------
+// | H | Beginning           | End           | Middle        |
+// -----------------------------------------------------------
+//  ^---- Non-wrapping -----^ ^--------- Wrapping ----------^
+// The non-wrapping part is never overwritten. The wrapping part will be
+// circular. The very first part is the header (see the BufferData struct
+// below). It consists of the following information:
+// - Length written to the buffer (not including header).
+// - Wrapping position.
+// - End position of buffer. (If the last byte is at x, this will be x + 1.)
+// Users of wrappers around the same underlying buffer must ensure that writing
+// is finished before reading is started.
+class CONTENT_EXPORT PartialCircularBuffer {
+ public:
+  // Use for reading. |buffer_size| is in bytes and must be larger than the
+  // header size (see above).
+  PartialCircularBuffer(void* buffer, uint32 buffer_size);
+
+  // Use for writing. |buffer_size| is in bytes and must be larger than the
+  // header size (see above).
+  PartialCircularBuffer(void* buffer,
+                        uint32 buffer_size,
+                        uint32 wrap_position);
+
+  uint32 Read(void* buffer, uint32 buffer_size);
+  void Write(const void* buffer, uint32 buffer_size);
+
+ private:
+  friend class PartialCircularBufferTest;
+
+#pragma pack(push)
+#pragma pack(4)
+  struct BufferData {
+    uint32 total_written;
+    uint32 wrap_position;
+    uint32 end_position;
+    uint8 data[1];
+  };
+#pragma pack(pop)
+
+  void DoWrite(void* dest, const void* src, uint32 num);
+
+  // Used for reading and writing.
+  BufferData* buffer_data_;
+  uint32 memory_buffer_size_;
+  uint32 data_size_;
+  uint32 position_;
+
+  // Used for reading.
+  uint32 total_read_;
+};
+
+}  // namespace content
+
+#endif  // CONTENT_COMMON_PARTIAL_CIRCULAR_BUFFER_H_
diff --git a/content/common/partial_circular_buffer_unittest.cc b/content/common/partial_circular_buffer_unittest.cc
new file mode 100644
index 0000000..5925667
--- /dev/null
+++ b/content/common/partial_circular_buffer_unittest.cc
@@ -0,0 +1,138 @@
+// Copyright (c) 2013 The Chromium 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 test buffer data is 52 bytes, wrap position is set to 20 (this is
+// arbitrarily chosen). The total buffer size is allocated dynamically based on
+// the actual header size. This gives:
+// Header of some size, non-wrapping part 20 bytes, wrapping part 32 bytes.
+// As input data, a 14 byte array is used and repeatedly written. It's chosen
+// not to be an integer factor smaller than the wrapping part. This ensures that
+// the wrapped data isn't repeated at the same position.
+// Note that desipte the number of wraps (if one or more), the reference output
+// data is the same since the offset at each wrap is always the same.
+
+#include "base/memory/scoped_ptr.h"
+#include "content/common/partial_circular_buffer.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+const uint32 kWrapPosition = 20;
+const uint8 kInputData[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14};
+const uint8 kOutputRefDataWrap[] =
+    // The 20 bytes in the non-wrapping part.
+    {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 1, 2, 3, 4, 5, 6,
+     // The 32 bytes in wrapping part.
+     11, 12, 13, 14,
+     1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+     1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14};
+
+class PartialCircularBufferTest : public testing::Test {
+ public:
+  PartialCircularBufferTest() {
+    PartialCircularBuffer::BufferData test_struct;
+    buffer_header_size_ =
+        &test_struct.data[0] - reinterpret_cast<uint8*>(&test_struct);
+
+    buffer_.reset(new uint8[buffer_header_size_ + sizeof(kOutputRefDataWrap)]);
+    pcb_write_.reset(new PartialCircularBuffer(
+        buffer_.get(),
+        buffer_header_size_ + sizeof(kOutputRefDataWrap),
+        kWrapPosition));
+  }
+
+  void WriteToBuffer(int num) {
+    for (int i = 0; i < num; ++i)
+      pcb_write_->Write(kInputData, sizeof(kInputData));
+  }
+
+  void InitReadBuffer() {
+    pcb_read_.reset(new PartialCircularBuffer(
+        buffer_.get(), buffer_header_size_ + sizeof(kOutputRefDataWrap)));
+  }
+
+ protected:
+  scoped_ptr<PartialCircularBuffer> pcb_write_;
+  scoped_ptr<PartialCircularBuffer> pcb_read_;
+  scoped_ptr<uint8[]> buffer_;
+  uint32 buffer_header_size_;
+
+  DISALLOW_COPY_AND_ASSIGN(PartialCircularBufferTest);
+};
+
+TEST_F(PartialCircularBufferTest, NoWrapBeginningPartOnly) {
+  WriteToBuffer(1);
+  InitReadBuffer();
+
+  uint8 output_data[sizeof(kInputData)] = {0};
+  EXPECT_EQ(sizeof(output_data),
+            pcb_read_->Read(output_data, sizeof(output_data)));
+
+  EXPECT_EQ(0, memcmp(kInputData, output_data, sizeof(kInputData)));
+
+  EXPECT_EQ(0u, pcb_read_->Read(output_data, sizeof(output_data)));
+}
+
+TEST_F(PartialCircularBufferTest, NoWrapBeginningAndEndParts) {
+  WriteToBuffer(2);
+  InitReadBuffer();
+
+  uint8 output_data[2 * sizeof(kInputData)] = {0};
+  EXPECT_EQ(sizeof(output_data),
+            pcb_read_->Read(output_data, sizeof(output_data)));
+
+  const uint8 output_ref_data[2 * sizeof(kInputData)] =
+      {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+       1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14};
+  EXPECT_EQ(0, memcmp(output_ref_data, output_data, sizeof(output_data)));
+
+  EXPECT_EQ(0u, pcb_read_->Read(output_data, sizeof(output_data)));
+}
+
+TEST_F(PartialCircularBufferTest, WrapOnce) {
+  WriteToBuffer(4);
+  InitReadBuffer();
+
+  uint8 output_data[sizeof(kOutputRefDataWrap)] = {0};
+  EXPECT_EQ(sizeof(output_data),
+            pcb_read_->Read(output_data, sizeof(output_data)));
+
+  EXPECT_EQ(0, memcmp(kOutputRefDataWrap, output_data, sizeof(output_data)));
+
+  EXPECT_EQ(0u, pcb_read_->Read(output_data, sizeof(output_data)));
+}
+
+TEST_F(PartialCircularBufferTest, WrapTwice) {
+  WriteToBuffer(7);
+  InitReadBuffer();
+
+  uint8 output_data[sizeof(kOutputRefDataWrap)] = {0};
+  EXPECT_EQ(sizeof(output_data),
+            pcb_read_->Read(output_data, sizeof(output_data)));
+
+  EXPECT_EQ(0, memcmp(kOutputRefDataWrap, output_data, sizeof(output_data)));
+
+  EXPECT_EQ(0u, pcb_read_->Read(output_data, sizeof(output_data)));
+}
+
+TEST_F(PartialCircularBufferTest, WrapOnceSmallerOutputBuffer) {
+  WriteToBuffer(4);
+  InitReadBuffer();
+
+  uint8 output_data[sizeof(kOutputRefDataWrap)] = {0};
+  const uint32 size_per_read = 16;
+  uint32 read = 0;
+  for (; read + size_per_read <= sizeof(output_data); read += size_per_read) {
+    EXPECT_EQ(size_per_read,
+              pcb_read_->Read(output_data + read, size_per_read));
+  }
+  EXPECT_EQ(sizeof(output_data) - read,
+            pcb_read_->Read(output_data + read, size_per_read));
+
+  EXPECT_EQ(0, memcmp(kOutputRefDataWrap, output_data, sizeof(output_data)));
+
+  EXPECT_EQ(0u, pcb_read_->Read(output_data, sizeof(output_data)));
+}
+
+}  // namespace content
diff --git a/content/common/resource_dispatcher.cc b/content/common/resource_dispatcher.cc
index 3c0f789..b4addcb 100644
--- a/content/common/resource_dispatcher.cc
+++ b/content/common/resource_dispatcher.cc
@@ -33,6 +33,20 @@
 
 namespace content {
 
+namespace {
+
+// Converts |time| from a remote to local TimeTicks, overwriting the original
+// value.
+void RemoteToLocalTimeTicks(
+    const InterProcessTimeTicksConverter& converter,
+    base::TimeTicks* time) {
+  RemoteTimeTicks remote_time = RemoteTimeTicks::FromTimeTicks(*time);
+  *time = converter.ToLocalTimeTicks(remote_time).ToTimeTicks();
+}
+
+
+}  // namespace
+
 static void CrashOnMapFailure() {
 #if defined(OS_WIN)
   DWORD last_err = GetLastError();
@@ -232,8 +246,6 @@
   response->request_time = result.request_time;
   response->response_time = result.response_time;
   response->encoded_data_length = result.encoded_data_length;
-  response->connection_id = result.connection_id;
-  response->connection_reused = result.connection_reused;
   response->load_timing = result.load_timing;
   response->devtools_info = result.devtools_info;
   response->data.swap(result.data);
@@ -244,7 +256,7 @@
 
 ResourceDispatcher::ResourceDispatcher(IPC::Sender* sender)
     : message_sender_(sender),
-      ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)),
+      weak_factory_(this),
       delegate_(NULL) {
 }
 
@@ -555,9 +567,11 @@
 
     FollowPendingRedirect(request_id, request_info);
 
-    MessageLoop::current()->PostTask(FROM_HERE,
+    base::MessageLoop::current()->PostTask(
+        FROM_HERE,
         base::Bind(&ResourceDispatcher::FlushDeferredMessages,
-                   weak_factory_.GetWeakPtr(), request_id));
+                   weak_factory_.GetWeakPtr(),
+                   request_id));
   }
 }
 
@@ -647,7 +661,7 @@
       request_info.response_start.is_null() ||
       browser_info.request_start.is_null() ||
       browser_info.response_start.is_null() ||
-      browser_info.load_timing.base_ticks.is_null()) {
+      browser_info.load_timing.request_start.is_null()) {
     return;
   }
   InterProcessTimeTicksConverter converter(
@@ -656,28 +670,19 @@
       RemoteTimeTicks::FromTimeTicks(browser_info.request_start),
       RemoteTimeTicks::FromTimeTicks(browser_info.response_start));
 
-  LocalTimeTicks renderer_base_ticks = converter.ToLocalTimeTicks(
-      RemoteTimeTicks::FromTimeTicks(browser_info.load_timing.base_ticks));
-  renderer_info->load_timing.base_ticks = renderer_base_ticks.ToTimeTicks();
-
-#define CONVERT(field) \
-  LocalTimeDelta renderer_##field = converter.ToLocalTimeDelta( \
-      RemoteTimeDelta::FromRawDelta(browser_info.load_timing.field)); \
-  renderer_info->load_timing.field = renderer_##field.ToInt32()
-
-  CONVERT(proxy_start);
-  CONVERT(dns_start);
-  CONVERT(dns_end);
-  CONVERT(connect_start);
-  CONVERT(connect_end);
-  CONVERT(ssl_start);
-  CONVERT(ssl_end);
-  CONVERT(send_start);
-  CONVERT(send_end);
-  CONVERT(receive_headers_start);
-  CONVERT(receive_headers_end);
-
-#undef CONVERT
+  net::LoadTimingInfo* load_timing = &renderer_info->load_timing;
+  RemoteToLocalTimeTicks(converter, &load_timing->request_start);
+  RemoteToLocalTimeTicks(converter, &load_timing->proxy_resolve_start);
+  RemoteToLocalTimeTicks(converter, &load_timing->proxy_resolve_end);
+  RemoteToLocalTimeTicks(converter, &load_timing->connect_timing.dns_start);
+  RemoteToLocalTimeTicks(converter, &load_timing->connect_timing.dns_end);
+  RemoteToLocalTimeTicks(converter, &load_timing->connect_timing.connect_start);
+  RemoteToLocalTimeTicks(converter, &load_timing->connect_timing.connect_end);
+  RemoteToLocalTimeTicks(converter, &load_timing->connect_timing.ssl_start);
+  RemoteToLocalTimeTicks(converter, &load_timing->connect_timing.ssl_end);
+  RemoteToLocalTimeTicks(converter, &load_timing->send_start);
+  RemoteToLocalTimeTicks(converter, &load_timing->send_end);
+  RemoteToLocalTimeTicks(converter, &load_timing->receive_headers_end);
 }
 
 base::TimeTicks ResourceDispatcher::ToRendererCompletionTime(
diff --git a/content/common/resource_dispatcher_unittest.cc b/content/common/resource_dispatcher_unittest.cc
index df65112..7465cec 100644
--- a/content/common/resource_dispatcher_unittest.cc
+++ b/content/common/resource_dispatcher_unittest.cc
@@ -329,7 +329,7 @@
 };
 
 TEST_F(DeferredResourceLoadingTest, DeferredLoadTest) {
-  MessageLoop message_loop(MessageLoop::TYPE_IO);
+  base::MessageLoop message_loop(base::MessageLoop::TYPE_IO);
 
   ResourceLoaderBridge* bridge = CreateBridge();
 
@@ -400,16 +400,19 @@
   response_head.error_code = net::OK;
   response_head.request_start = base::TimeTicks::FromInternalValue(5);
   response_head.response_start = base::TimeTicks::FromInternalValue(15);
-  response_head.load_timing.base_time = base::Time::Now();
-  response_head.load_timing.base_ticks = base::TimeTicks::FromInternalValue(10);
-  response_head.load_timing.dns_start = -1;
-  response_head.load_timing.connect_start = 3;
+  response_head.load_timing.request_start_time = base::Time::Now();
+  response_head.load_timing.request_start =
+      base::TimeTicks::FromInternalValue(10);
+  response_head.load_timing.connect_timing.connect_start =
+      base::TimeTicks::FromInternalValue(13);
 
   PerformTest(response_head);
 
-  EXPECT_LT(0, response_info().load_timing.base_ticks.ToInternalValue());
-  EXPECT_EQ(-1, response_info().load_timing.dns_start);
-  EXPECT_LE(0, response_info().load_timing.connect_start);
+  EXPECT_LT(base::TimeTicks(), response_info().load_timing.request_start);
+  EXPECT_EQ(base::TimeTicks(),
+            response_info().load_timing.connect_timing.dns_start);
+  EXPECT_LE(response_head.load_timing.request_start,
+            response_info().load_timing.connect_timing.connect_start);
 }
 
 TEST_F(TimeConversionTest, PartiallyInitialized) {
@@ -420,8 +423,9 @@
 
   PerformTest(response_head);
 
-  EXPECT_EQ(0, response_info().load_timing.base_ticks.ToInternalValue());
-  EXPECT_EQ(-1, response_info().load_timing.dns_start);
+  EXPECT_EQ(base::TimeTicks(), response_info().load_timing.request_start);
+  EXPECT_EQ(base::TimeTicks(),
+            response_info().load_timing.connect_timing.dns_start);
 }
 
 TEST_F(TimeConversionTest, NotInitialized) {
@@ -430,8 +434,9 @@
 
   PerformTest(response_head);
 
-  EXPECT_EQ(0, response_info().load_timing.base_ticks.ToInternalValue());
-  EXPECT_EQ(-1, response_info().load_timing.dns_start);
+  EXPECT_EQ(base::TimeTicks(), response_info().load_timing.request_start);
+  EXPECT_EQ(base::TimeTicks(),
+            response_info().load_timing.connect_timing.dns_start);
 }
 
 }  // namespace content
diff --git a/content/common/resource_messages.cc b/content/common/resource_messages.cc
index 3edaee3..ad4bd7f 100644
--- a/content/common/resource_messages.cc
+++ b/content/common/resource_messages.cc
@@ -4,6 +4,7 @@
 
 #include "content/common/resource_messages.h"
 
+#include "net/base/load_timing_info.h"
 #include "net/http/http_response_headers.h"
 #include "webkit/glue/resource_loader_bridge.h"
 
@@ -137,7 +138,7 @@
 void ParamTraits<scoped_refptr<webkit_glue::ResourceDevToolsInfo> >::Write(
     Message* m, const param_type& p) {
   WriteParam(m, p.get() != NULL);
-  if (p.get()) {
+  if (p) {
     WriteParam(m, p->http_status_code);
     WriteParam(m, p->http_status_text);
     WriteParam(m, p->request_headers);
@@ -175,81 +176,86 @@
   l->append(")");
 }
 
-void ParamTraits<webkit_glue::ResourceLoadTimingInfo>::Write(
+void ParamTraits<net::LoadTimingInfo>::Write(
     Message* m, const param_type& p) {
-  WriteParam(m, p.base_time.is_null());
-  if (p.base_time.is_null())
+  WriteParam(m, p.socket_log_id);
+  WriteParam(m, p.socket_reused);
+  WriteParam(m, p.request_start_time.is_null());
+  if (p.request_start_time.is_null())
     return;
-  WriteParam(m, p.base_ticks);
-  WriteParam(m, p.base_time);
-  WriteParam(m, p.proxy_start);
-  WriteParam(m, p.proxy_end);
-  WriteParam(m, p.dns_start);
-  WriteParam(m, p.dns_end);
-  WriteParam(m, p.connect_start);
-  WriteParam(m, p.connect_end);
-  WriteParam(m, p.ssl_start);
-  WriteParam(m, p.ssl_end);
+  WriteParam(m, p.request_start_time);
+  WriteParam(m, p.request_start);
+  WriteParam(m, p.proxy_resolve_start);
+  WriteParam(m, p.proxy_resolve_end);
+  WriteParam(m, p.connect_timing.dns_start);
+  WriteParam(m, p.connect_timing.dns_end);
+  WriteParam(m, p.connect_timing.connect_start);
+  WriteParam(m, p.connect_timing.connect_end);
+  WriteParam(m, p.connect_timing.ssl_start);
+  WriteParam(m, p.connect_timing.ssl_end);
   WriteParam(m, p.send_start);
   WriteParam(m, p.send_end);
-  WriteParam(m, p.receive_headers_start);
   WriteParam(m, p.receive_headers_end);
 }
 
-bool ParamTraits<webkit_glue::ResourceLoadTimingInfo>::Read(
+bool ParamTraits<net::LoadTimingInfo>::Read(
     const Message* m, PickleIterator* iter, param_type* r) {
-  bool is_null;
-  if (!ReadParam(m, iter, &is_null))
+  bool has_no_times;
+  if (!ReadParam(m, iter, &r->socket_log_id) ||
+      !ReadParam(m, iter, &r->socket_reused) ||
+      !ReadParam(m, iter, &has_no_times)) {
     return false;
-  if (is_null)
+  }
+  if (has_no_times)
     return true;
 
   return
-      ReadParam(m, iter, &r->base_ticks) &&
-      ReadParam(m, iter, &r->base_time) &&
-      ReadParam(m, iter, &r->proxy_start) &&
-      ReadParam(m, iter, &r->proxy_end) &&
-      ReadParam(m, iter, &r->dns_start) &&
-      ReadParam(m, iter, &r->dns_end) &&
-      ReadParam(m, iter, &r->connect_start) &&
-      ReadParam(m, iter, &r->connect_end) &&
-      ReadParam(m, iter, &r->ssl_start) &&
-      ReadParam(m, iter, &r->ssl_end) &&
+      ReadParam(m, iter, &r->request_start_time) &&
+      ReadParam(m, iter, &r->request_start) &&
+      ReadParam(m, iter, &r->proxy_resolve_start) &&
+      ReadParam(m, iter, &r->proxy_resolve_end) &&
+      ReadParam(m, iter, &r->connect_timing.dns_start) &&
+      ReadParam(m, iter, &r->connect_timing.dns_end) &&
+      ReadParam(m, iter, &r->connect_timing.connect_start) &&
+      ReadParam(m, iter, &r->connect_timing.connect_end) &&
+      ReadParam(m, iter, &r->connect_timing.ssl_start) &&
+      ReadParam(m, iter, &r->connect_timing.ssl_end) &&
       ReadParam(m, iter, &r->send_start) &&
       ReadParam(m, iter, &r->send_end) &&
-      ReadParam(m, iter, &r->receive_headers_start) &&
       ReadParam(m, iter, &r->receive_headers_end);
 }
 
-void ParamTraits<webkit_glue::ResourceLoadTimingInfo>::Log(const param_type& p,
-                                                           std::string* l) {
+void ParamTraits<net::LoadTimingInfo>::Log(const param_type& p,
+                                           std::string* l) {
   l->append("(");
-  LogParam(p.base_ticks, l);
+  LogParam(p.socket_log_id, l);
+  l->append(",");
+  LogParam(p.socket_reused, l);
+  l->append(",");
+  LogParam(p.request_start_time, l);
   l->append(", ");
-  LogParam(p.base_time, l);
+  LogParam(p.request_start, l);
   l->append(", ");
-  LogParam(p.proxy_start, l);
+  LogParam(p.proxy_resolve_start, l);
   l->append(", ");
-  LogParam(p.proxy_end, l);
+  LogParam(p.proxy_resolve_end, l);
   l->append(", ");
-  LogParam(p.dns_start, l);
+  LogParam(p.connect_timing.dns_start, l);
   l->append(", ");
-  LogParam(p.dns_end, l);
+  LogParam(p.connect_timing.dns_end, l);
   l->append(", ");
-  LogParam(p.connect_start, l);
+  LogParam(p.connect_timing.connect_start, l);
   l->append(", ");
-  LogParam(p.connect_end, l);
+  LogParam(p.connect_timing.connect_end, l);
   l->append(", ");
-  LogParam(p.ssl_start, l);
+  LogParam(p.connect_timing.ssl_start, l);
   l->append(", ");
-  LogParam(p.ssl_end, l);
+  LogParam(p.connect_timing.ssl_end, l);
   l->append(", ");
   LogParam(p.send_start, l);
   l->append(", ");
   LogParam(p.send_end, l);
   l->append(", ");
-  LogParam(p.receive_headers_start, l);
-  l->append(", ");
   LogParam(p.receive_headers_end, l);
   l->append(")");
 }
diff --git a/content/common/resource_messages.h b/content/common/resource_messages.h
index abe4964..7aebd09 100644
--- a/content/common/resource_messages.h
+++ b/content/common/resource_messages.h
@@ -19,9 +19,12 @@
 #ifndef CONTENT_COMMON_RESOURCE_MESSAGES_H_
 #define CONTENT_COMMON_RESOURCE_MESSAGES_H_
 
+namespace net {
+struct LoadTimingInfo;
+}
+
 namespace webkit_glue {
 struct ResourceDevToolsInfo;
-struct ResourceLoadTimingInfo;
 }
 
 namespace IPC {
@@ -51,8 +54,8 @@
 };
 
 template <>
-struct ParamTraits<webkit_glue::ResourceLoadTimingInfo> {
-  typedef webkit_glue::ResourceLoadTimingInfo param_type;
+struct ParamTraits<net::LoadTimingInfo> {
+  typedef net::LoadTimingInfo param_type;
   static void Write(Message* m, const param_type& p);
   static bool Read(const Message* m, PickleIterator* iter, param_type* r);
   static void Log(const param_type& p, std::string* l);
@@ -99,8 +102,6 @@
   IPC_STRUCT_TRAITS_MEMBER(encoded_data_length)
   IPC_STRUCT_TRAITS_MEMBER(appcache_id)
   IPC_STRUCT_TRAITS_MEMBER(appcache_manifest_url)
-  IPC_STRUCT_TRAITS_MEMBER(connection_id)
-  IPC_STRUCT_TRAITS_MEMBER(connection_reused)
   IPC_STRUCT_TRAITS_MEMBER(load_timing)
   IPC_STRUCT_TRAITS_MEMBER(devtools_info)
   IPC_STRUCT_TRAITS_MEMBER(download_file_path)
diff --git a/content/common/sandbox_init_linux.cc b/content/common/sandbox_init_linux.cc
deleted file mode 100644
index 25cbf95..0000000
--- a/content/common/sandbox_init_linux.cc
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <string>
-
-#include "base/command_line.h"
-#include "base/logging.h"
-#include "content/common/sandbox_linux.h"
-#include "content/public/common/content_switches.h"
-#include "content/public/common/sandbox_init.h"
-
-namespace content {
-
-// TODO(jln): have call sites provide a process / policy type to
-// InitializeSandbox().
-bool InitializeSandbox() {
-  bool seccomp_legacy_started = false;
-  bool seccomp_bpf_started = false;
-  LinuxSandbox* linux_sandbox = LinuxSandbox::GetInstance();
-  const std::string process_type =
-      CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
-          switches::kProcessType);
-
-  // No matter what, it's always an error to call InitializeSandbox() after
-  // threads have been created.
-  if (!linux_sandbox->IsSingleThreaded()) {
-    std::string error_message = "InitializeSandbox() called with multiple "
-                                "threads in process " + process_type;
-    // TODO(jln): change this into a CHECK() once we are more comfortable it
-    // does not trigger.
-    LOG(ERROR) << error_message;
-    return false;
-  }
-
-  // Attempt to limit the future size of the address space of the process.
-  linux_sandbox->LimitAddressSpace(process_type);
-
-  // First, try to enable seccomp-bpf.
-  seccomp_bpf_started = linux_sandbox->StartSeccompBpf(process_type);
-
-  // If that fails, try to enable seccomp-legacy.
-  if (!seccomp_bpf_started) {
-    seccomp_legacy_started = linux_sandbox->StartSeccompLegacy(process_type);
-  }
-
-  return seccomp_legacy_started || seccomp_bpf_started;
-}
-
-}  // namespace content
diff --git a/content/common/sandbox_linux.cc b/content/common/sandbox_linux.cc
index ec443ec..c3e842b 100644
--- a/content/common/sandbox_linux.cc
+++ b/content/common/sandbox_linux.cc
@@ -10,6 +10,8 @@
 
 #include <limits>
 
+#include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/command_line.h"
 #include "base/file_util.h"
 #include "base/logging.h"
@@ -17,7 +19,6 @@
 #include "base/posix/eintr_wrapper.h"
 #include "base/time.h"
 #include "content/common/sandbox_linux.h"
-#include "content/common/seccomp_sandbox.h"
 #include "content/common/sandbox_seccomp_bpf_linux.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/common/sandbox_linux.h"
@@ -39,35 +40,6 @@
 #endif
 }
 
-// Implement the command line enabling logic for seccomp-legacy.
-bool IsSeccompLegacyDesired() {
-  CommandLine* command_line = CommandLine::ForCurrentProcess();
-  if (command_line->HasSwitch(switches::kNoSandbox)) {
-    return false;
-  }
-#if defined(SECCOMP_SANDBOX)
-#if defined(NDEBUG)
-  // Off by default. Allow turning on with a switch.
-  return command_line->HasSwitch(switches::kEnableSeccompSandbox);
-#else
-  // On by default. Allow turning off with a switch.
-  return !command_line->HasSwitch(switches::kDisableSeccompSandbox);
-#endif  // NDEBUG
-#endif  // SECCOMP_SANDBOX
-  return false;
-}
-
-// Our "policy" on whether or not to enable seccomp-legacy. Only renderers are
-// supported.
-bool ShouldEnableSeccompLegacy(const std::string& process_type) {
-  if (IsSeccompLegacyDesired() &&
-      process_type == switches::kRendererProcess) {
-    return true;
-  } else {
-    return false;
-  }
-}
-
 bool AddResourceLimit(int resource, rlim_t limit) {
   struct rlimit old_rlimit;
   if (getrlimit(resource, &old_rlimit))
@@ -89,7 +61,6 @@
     : proc_fd_(-1),
       seccomp_bpf_started_(false),
       pre_initialized_(false),
-      seccomp_legacy_supported_(false),
       seccomp_bpf_supported_(false),
       setuid_sandbox_client_(sandbox::SetuidSandboxClient::Create()) {
   if (setuid_sandbox_client_ == NULL) {
@@ -111,38 +82,22 @@
 extern "C" void __sanitizer_sandbox_on_notify(void *reserved);
 #endif
 
-void LinuxSandbox::PreinitializeSandboxBegin() {
+void LinuxSandbox::PreinitializeSandbox() {
   CHECK(!pre_initialized_);
-  seccomp_legacy_supported_ = false;
   seccomp_bpf_supported_ = false;
 #if defined(ADDRESS_SANITIZER) && defined(OS_LINUX)
   // ASan needs to open some resources before the sandbox is enabled.
   // This should not fork, not launch threads, not open a directory.
   __sanitizer_sandbox_on_notify(/*reserved*/NULL);
 #endif
-#if defined(SECCOMP_SANDBOX)
-  if (IsSeccompLegacyDesired()) {
-    proc_fd_ = open("/proc", O_DIRECTORY | O_RDONLY);
-    if (proc_fd_ < 0) {
-      LOG(ERROR) << "Cannot access \"/proc\". Disabling seccomp-legacy "
-                    "sandboxing.";
-      // Now is a good time to figure out if we can support seccomp sandboxing
-      // at all. We will call SupportsSeccompSandbox again later, when actually
-      // enabling it, but we allow the implementation to cache some information.
-      // This is the only place where we will log full lack of seccomp-legacy
-      // support.
-    } else if (!SupportsSeccompSandbox(proc_fd_)) {
-      VLOG(1) << "Lacking support for seccomp-legacy sandbox.";
-      CHECK_EQ(HANDLE_EINTR(close(proc_fd_)), 0);
-      proc_fd_ = -1;
-    } else {
-      seccomp_legacy_supported_ = true;
-    }
-  }
-#endif  // SECCOMP_SANDBOX
-  // Similarly, we "pre-warm" the code that detects supports for seccomp BPF.
-  // TODO(jln): Use proc_fd_ here too once we're comfortable it does not create
-  // an additional security risk.
+
+#if !defined(NDEBUG)
+  // Open proc_fd_ only in Debug mode so that forgetting to close it doesn't
+  // produce a sandbox escape in Release mode.
+  proc_fd_ = open("/proc", O_DIRECTORY | O_RDONLY);
+  CHECK(proc_fd_ >= 0);
+#endif  // !defined(NDEBUG)
+  // We "pre-warm" the code that detects supports for seccomp BPF.
   if (SandboxSeccompBpf::IsSeccompBpfDesired()) {
     if (!SandboxSeccompBpf::SupportsSandbox()) {
       VLOG(1) << "Lacking support for seccomp-bpf sandbox.";
@@ -153,27 +108,37 @@
   pre_initialized_ = true;
 }
 
-// Once we finally know our process type, we can cleanup proc_fd_
-// or pass it to seccomp-legacy.
-void LinuxSandbox::PreinitializeSandboxFinish(
-    const std::string& process_type) {
-  CHECK(pre_initialized_);
-  if (proc_fd_ >= 0) {
-    if (ShouldEnableSeccompLegacy(process_type)) {
-#if defined(SECCOMP_SANDBOX)
-      SeccompSandboxSetProcFd(proc_fd_);
-#endif
-    } else {
-      DCHECK_GE(proc_fd_, 0);
-      CHECK_EQ(HANDLE_EINTR(close(proc_fd_)), 0);
-    }
-    proc_fd_ = -1;
-  }
-}
+bool LinuxSandbox::InitializeSandbox() {
+  bool seccomp_bpf_started = false;
+  LinuxSandbox* linux_sandbox = LinuxSandbox::GetInstance();
+  // We need to make absolutely sure that our sandbox is "sealed" before
+  // InitializeSandbox does exit.
+  base::ScopedClosureRunner sandbox_sealer(
+      base::Bind(&LinuxSandbox::SealSandbox, base::Unretained(linux_sandbox)));
+  const std::string process_type =
+      CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
+          switches::kProcessType);
 
-void LinuxSandbox::PreinitializeSandbox(const std::string& process_type) {
-  PreinitializeSandboxBegin();
-  PreinitializeSandboxFinish(process_type);
+  // No matter what, it's always an error to call InitializeSandbox() after
+  // threads have been created.
+  if (!linux_sandbox->IsSingleThreaded()) {
+    std::string error_message = "InitializeSandbox() called with multiple "
+                                "threads in process " + process_type;
+    // The GPU process is allowed to call InitializeSandbox() with threads for
+    // now, because it loads third party libraries.
+    if (process_type != switches::kGpuProcess)
+      DCHECK(false) << error_message;
+    LOG(ERROR) << error_message;
+    return false;
+  }
+
+  // Attempt to limit the future size of the address space of the process.
+  linux_sandbox->LimitAddressSpace(process_type);
+
+  // First, try to enable seccomp-bpf.
+  seccomp_bpf_started = linux_sandbox->StartSeccompBpf(process_type);
+
+  return seccomp_bpf_started;
 }
 
 int LinuxSandbox::GetStatus() const {
@@ -194,28 +159,42 @@
     sandbox_flags |= kSandboxLinuxSeccompBpf;
   }
 
-  // We only try to enable seccomp-legacy when seccomp-bpf is not supported
-  // or not enabled.
-  if (!(sandbox_flags & kSandboxLinuxSeccompBpf) &&
-      seccomp_legacy_supported() &&
-      ShouldEnableSeccompLegacy(switches::kRendererProcess)) {
-    // Same here, what we report is what we will do for the renderer.
-    sandbox_flags |= kSandboxLinuxSeccompLegacy;
-  }
   return sandbox_flags;
 }
 
+// Threads are counted via /proc/self/task. This is a little hairy because of
+// PID namespaces and existing sandboxes, so "self" must really be used instead
+// of using the pid.
 bool LinuxSandbox::IsSingleThreaded() const {
-  // TODO(jln): re-implement this properly and use our proc_fd_ if available.
-  // Possibly racy, but it's ok because this is more of a debug check to catch
-  // new threaded situations arising during development.
-  int num_threads = file_util::CountFilesCreatedAfter(
-      base::FilePath("/proc/self/task"),
-      base::Time::UnixEpoch());
+  struct stat task_stat;
+  int fstat_ret;
+  if (proc_fd_ >= 0) {
+    // If a handle to /proc is available, use it. This allows to bypass file
+    // system restrictions.
+    fstat_ret = fstatat(proc_fd_, "self/task/", &task_stat, 0);
+  } else {
+    // Otherwise, make an attempt to access the file system directly.
+    fstat_ret = fstatat(AT_FDCWD, "/proc/self/task/", &task_stat, 0);
+  }
+  // In Debug mode, it's mandatory to be able to count threads to catch bugs.
+#if !defined(NDEBUG)
+  // Using DCHECK here would be incorrect. DCHECK can be enabled in non
+  // official release mode.
+  CHECK_EQ(0, fstat_ret) << "Could not count threads, the sandbox was not "
+                         << "pre-initialized properly.";
+#endif  // !defined(NDEBUG)
+  if (fstat_ret) {
+    // Pretend to be monothreaded if it can't be determined (for instance the
+    // setuid sandbox is already engaged but no proc_fd_ is available).
+    return true;
+  }
 
-  // We pass the test if we don't know ( == 0), because the setuid sandbox
-  // will prevent /proc access in some contexts.
-  return num_threads == 1 || num_threads == 0;
+  // At least "..", "." and the current thread should be present.
+  CHECK_LE(3UL, task_stat.st_nlink);
+  // Counting threads via /proc/self/task could be racy. For the purpose of
+  // determining if the current proces is monothreaded it works: if at any
+  // time it becomes monothreaded, it'll stay so.
+  return task_stat.st_nlink == 3;
 }
 
 bool LinuxSandbox::seccomp_bpf_started() const {
@@ -227,30 +206,11 @@
   return setuid_sandbox_client_.get();
 }
 
-// For seccomp-legacy, we implement the policy inline, here.
-bool LinuxSandbox::StartSeccompLegacy(const std::string& process_type) {
-  if (!pre_initialized_)
-    PreinitializeSandbox(process_type);
-  if (seccomp_legacy_supported() && ShouldEnableSeccompLegacy(process_type)) {
-    // SupportsSeccompSandbox() returns a cached result, as we already
-    // called it earlier in the PreinitializeSandbox(). Thus, it is OK for us
-    // to not pass in a file descriptor for "/proc".
-#if defined(SECCOMP_SANDBOX)
-    if (SupportsSeccompSandbox(-1)) {
-      StartSeccompSandbox();
-      LogSandboxStarted("seccomp-legacy");
-      return true;
-    }
-#endif
-  }
-  return false;
-}
-
 // For seccomp-bpf, we use the SandboxSeccompBpf class.
 bool LinuxSandbox::StartSeccompBpf(const std::string& process_type) {
   CHECK(!seccomp_bpf_started_);
   if (!pre_initialized_)
-    PreinitializeSandbox(process_type);
+    PreinitializeSandbox();
   if (seccomp_bpf_supported())
     seccomp_bpf_started_ = SandboxSeccompBpf::StartSandbox(process_type);
 
@@ -260,11 +220,6 @@
   return seccomp_bpf_started_;
 }
 
-bool LinuxSandbox::seccomp_legacy_supported() const {
-  CHECK(pre_initialized_);
-  return seccomp_legacy_supported_;
-}
-
 bool LinuxSandbox::seccomp_bpf_supported() const {
   CHECK(pre_initialized_);
   return seccomp_bpf_supported_;
@@ -307,5 +262,13 @@
 #endif  // !defined(ADDRESS_SANITIZER)
 }
 
+void LinuxSandbox::SealSandbox() {
+  if (proc_fd_ >= 0) {
+    int ret = HANDLE_EINTR(close(proc_fd_));
+    CHECK_EQ(0, ret);
+    proc_fd_ = -1;
+  }
+}
+
 }  // namespace content
 
diff --git a/content/common/sandbox_linux.h b/content/common/sandbox_linux.h
index 3df65ea..f8753c5 100644
--- a/content/common/sandbox_linux.h
+++ b/content/common/sandbox_linux.h
@@ -37,29 +37,25 @@
   static LinuxSandbox* GetInstance();
 
   // Do some initialization that can only be done before any of the sandboxes
-  // is enabled.
-  //
-  // There are two versions of this function. One takes a process_type
-  // as an argument, the other doesn't.
-  // It may be necessary to call PreinitializeSandboxBegin before knowing the
-  // process type (this is for instance the case with the Zygote).
-  // In that case, it is crucial that PreinitializeSandboxFinish() gets
-  // called for every child process.
-  // TODO(markus, jln) we know this is not always done at the moment
-  // (crbug.com/139877).
-  void PreinitializeSandbox(const std::string& process_type);
-  // These should be called together.
-  void PreinitializeSandboxBegin();
-  void PreinitializeSandboxFinish(const std::string& process_type);
+  // are enabled. If using the setuid sandbox, this should be called manually
+  // before the setuid sandbox is engaged.
+  void PreinitializeSandbox();
 
-  // Returns the Status of the sandbox. Can only be queried if we went through
-  // PreinitializeSandbox() or PreinitializeSandboxBegin(). This is a bitmask
-  // and uses the constants defined in "enum LinuxSandboxStatus".
-  // Since we need to provide the status before the sandboxes are actually
-  // started, this returns what will actually happen once the various Start*
-  // functions are called from inside a renderer.
+  // Initialize the sandbox with the given pre-built configuration. Currently
+  // seccomp-bpf and address space limitations (the setuid sandbox works
+  // differently and is set-up in the Zygote). This will instantiate the
+  // LinuxSandbox singleton if it doesn't already exist.
+  static bool InitializeSandbox();
+
+  // Returns the Status of the renderers' sandbox. Can only be queried after
+  // going through PreinitializeSandbox(). This is a bitmask and uses the
+  // constants defined in "enum LinuxSandboxStatus". Since the status needs to
+  // be provided before the sandboxes are actually started, this returns what
+  // will actually happen once the various Start* functions are called from
+  // inside a renderer.
   int GetStatus() const;
-  // Is the current process single threaded?
+  // Returns true if the current process is single-threaded or if the number
+  // of threads cannot be determined.
   bool IsSingleThreaded() const;
   // Did we start Seccomp BPF?
   bool seccomp_bpf_started() const;
@@ -70,10 +66,8 @@
   // be used directly.
   sandbox::SetuidSandboxClient* setuid_sandbox_client() const;
 
-  // Check the policy and eventually start the seccomp-legacy sandbox.
-  bool StartSeccompLegacy(const std::string& process_type);
   // Check the policy and eventually start the seccomp-bpf sandbox. This should
-  // never be called with threads started. If we detect that thread have
+  // never be called with threads started. If we detect that threads have
   // started we will crash.
   bool StartSeccompBpf(const std::string& process_type);
 
@@ -84,15 +78,19 @@
  private:
   friend struct DefaultSingletonTraits<LinuxSandbox>;
 
-  // We must have been pre_initialized_ before using either of these.
-  bool seccomp_legacy_supported() const;
+  // We must have been pre_initialized_ before using this.
   bool seccomp_bpf_supported() const;
+  // The last part of the initialization is to make sure any temporary "hole"
+  // in the sandbox is closed. For now, this consists of closing proc_fd_.
+  void SealSandbox();
 
+  // A file descriptor to /proc. It's dangerous to have it around as it could
+  // allow for sandbox bypasses. It needs to be closed before we consider
+  // ourselves sandboxed.
   int proc_fd_;
   bool seccomp_bpf_started_;
-  // Have we been through PreinitializeSandbox or PreinitializeSandboxBegin?
+  // Did PreinitializeSandbox() run?
   bool pre_initialized_;
-  bool seccomp_legacy_supported_;  // Accurate if pre_initialized_.
   bool seccomp_bpf_supported_;  // Accurate if pre_initialized_.
   scoped_ptr<sandbox::SetuidSandboxClient> setuid_sandbox_client_;
 
diff --git a/content/common/sandbox_mac.mm b/content/common/sandbox_mac.mm
index 6ae12c2..8265ff1 100644
--- a/content/common/sandbox_mac.mm
+++ b/content/common/sandbox_mac.mm
@@ -23,11 +23,11 @@
 #include "base/memory/scoped_nsobject.h"
 #include "base/rand_util.h"
 #include "base/string16.h"
-#include "base/string_piece.h"
 #include "base/string_util.h"
 #include "base/stringprintf.h"
+#include "base/strings/string_piece.h"
+#include "base/strings/sys_string_conversions.h"
 #include "base/sys_info.h"
-#include "base/sys_string_conversions.h"
 #include "base/utf_string_conversions.h"
 #include "content/public/common/content_client.h"
 #include "content/public/common/content_switches.h"
diff --git a/content/common/sandbox_mac_diraccess_unittest.mm b/content/common/sandbox_mac_diraccess_unittest.mm
index f3c8e97..ede6ba0 100644
--- a/content/common/sandbox_mac_diraccess_unittest.mm
+++ b/content/common/sandbox_mac_diraccess_unittest.mm
@@ -11,7 +11,7 @@
 
 #include "base/file_util.h"
 #include "base/files/file_path.h"
-#include "base/sys_string_conversions.h"
+#include "base/strings/sys_string_conversions.h"
 #include "base/test/multiprocess_test.h"
 #include "base/utf_string_conversions.h"
 #include "content/common/sandbox_mac.h"
diff --git a/content/common/sandbox_mac_fontloading_unittest.mm b/content/common/sandbox_mac_fontloading_unittest.mm
index 959af35..77b211f 100644
--- a/content/common/sandbox_mac_fontloading_unittest.mm
+++ b/content/common/sandbox_mac_fontloading_unittest.mm
@@ -44,7 +44,7 @@
   }
 
   font_shmem_.reset(new base::SharedMemory);
-  if (!font_shmem_.get()) {
+  if (!font_shmem_) {
     LOG(ERROR) << "Failed to create shared memory object.";
     return false;
   }
diff --git a/content/common/sandbox_mac_system_access_unittest.mm b/content/common/sandbox_mac_system_access_unittest.mm
index 6eb681a..1b4eea3 100644
--- a/content/common/sandbox_mac_system_access_unittest.mm
+++ b/content/common/sandbox_mac_system_access_unittest.mm
@@ -6,7 +6,7 @@
 
 #include "base/file_util.h"
 #include "base/logging.h"
-#include "base/sys_string_conversions.h"
+#include "base/strings/sys_string_conversions.h"
 #include "content/common/sandbox_mac.h"
 #include "content/common/sandbox_mac_unittest_helper.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/content/common/sandbox_mac_unittest_helper.mm b/content/common/sandbox_mac_unittest_helper.mm
index 6417e68..4c64b55 100644
--- a/content/common/sandbox_mac_unittest_helper.mm
+++ b/content/common/sandbox_mac_unittest_helper.mm
@@ -139,7 +139,7 @@
   // Find Test Function to run;
   scoped_ptr<MacSandboxTestCase>
       test_case(SandboxTestForName(sandbox_test_name));
-  if (!test_case.get()) {
+  if (!test_case) {
     LOG(ERROR) << "Invalid sandbox test name (" << sandbox_test_name << ")";
     return -1;
   }
diff --git a/content/common/sandbox_seccomp_bpf_linux.cc b/content/common/sandbox_seccomp_bpf_linux.cc
index 2f3f0ef..8f2e886 100644
--- a/content/common/sandbox_seccomp_bpf_linux.cc
+++ b/content/common/sandbox_seccomp_bpf_linux.cc
@@ -175,12 +175,15 @@
   return is_enabled;
 }
 
-intptr_t GpuOpenSIGSYS_Handler(const struct arch_seccomp_data& args,
-                               void* aux_broker_process) {
+intptr_t GpuSIGSYS_Handler(const struct arch_seccomp_data& args,
+                           void* aux_broker_process) {
   RAW_CHECK(aux_broker_process);
   BrokerProcess* broker_process =
       static_cast<BrokerProcess*>(aux_broker_process);
   switch(args.nr) {
+    case __NR_access:
+      return broker_process->Access(reinterpret_cast<const char*>(args.args[0]),
+                                    static_cast<int>(args.args[1]));
     case __NR_open:
       return broker_process->Open(reinterpret_cast<const char*>(args.args[0]),
                                   static_cast<int>(args.args[1]));
@@ -1269,11 +1272,11 @@
     // be denied gracefully right away.
     return sandbox->Trap(CrashSIGSYS_Handler, NULL);
   }
-  // In any other case crash the program with our SIGSYS handler
+  // In any other case crash the program with our SIGSYS handler.
   return sandbox->Trap(CrashSIGSYS_Handler, NULL);
 }
 
-// x86_64/i386 for now. Needs to be adapted and tested for ARM.
+// Main policy for x86_64/i386. Extended by ArmMaliGpuProcessPolicy.
 ErrorCode GpuProcessPolicy(Sandbox *sandbox, int sysno,
                            void *broker_process) {
   switch(sysno) {
@@ -1281,9 +1284,10 @@
     case __NR_sched_getaffinity:
     case __NR_sched_setaffinity:
       return ErrorCode(ErrorCode::ERR_ALLOWED);
+    case __NR_access:
     case __NR_open:
     case __NR_openat:
-        return sandbox->Trap(GpuOpenSIGSYS_Handler, broker_process);
+      return sandbox->Trap(GpuSIGSYS_Handler, broker_process);
     default:
 #if defined(__x86_64__) || defined(__arm__)
       if (IsSystemVSharedMemory(sysno))
@@ -1297,13 +1301,14 @@
   }
 }
 
-// x86_64/i386 for now. Needs to be adapted and tested for ARM.
+// x86_64/i386.
 // A GPU broker policy is the same as a GPU policy with open and
 // openat allowed.
 ErrorCode GpuBrokerProcessPolicy(Sandbox *sandbox, int sysno, void *aux) {
   // "aux" would typically be NULL, when called from
   // "EnableGpuBrokerPolicyCallBack"
   switch(sysno) {
+    case __NR_access:
     case __NR_open:
     case __NR_openat:
       return ErrorCode(ErrorCode::ERR_ALLOWED);
@@ -1312,6 +1317,48 @@
   }
 }
 
+// ARM Mali GPU process sandbox, inheriting from GpuProcessPolicy.
+ErrorCode ArmMaliGpuProcessPolicy(Sandbox *sandbox, int sysno,
+                                  void *broker_process) {
+  switch(sysno) {
+#if defined(__arm__)
+    // ARM GPU sandbox is started earlier so we need to allow networking
+    // in the sandbox.
+    // TODO(jorgelo): tighten this (crbug.com/235609).
+    case __NR_connect:
+    case __NR_getpeername:
+    case __NR_getsockname:
+    case __NR_socket:
+    case __NR_socketpair:
+    case __NR_sysinfo:
+    case __NR_uname:
+      return ErrorCode(ErrorCode::ERR_ALLOWED);
+#endif  // defined(__arm__)
+    default:
+      if (IsAdvancedScheduler(sysno))
+        return ErrorCode(ErrorCode::ERR_ALLOWED);
+
+      // Default to the generic GPU policy.
+      return GpuProcessPolicy(sandbox, sysno, broker_process);
+  }
+}
+
+// A GPU broker policy is the same as a GPU policy with open and
+// openat allowed.
+ErrorCode ArmMaliGpuBrokerProcessPolicy(Sandbox *sandbox,
+                                        int sysno, void *aux) {
+  // "aux" would typically be NULL, when called from
+  // "EnableGpuBrokerPolicyCallBack"
+  switch(sysno) {
+    case __NR_access:
+    case __NR_open:
+    case __NR_openat:
+      return ErrorCode(ErrorCode::ERR_ALLOWED);
+    default:
+      return ArmMaliGpuProcessPolicy(sandbox, sysno, aux);
+  }
+}
+
 // Allow clone for threads, crash if anything else is attempted.
 // Don't restrict on ASAN.
 ErrorCode RestrictCloneToThreads(Sandbox *sandbox) {
@@ -1453,28 +1500,79 @@
   }
 }
 
-bool EnableGpuBrokerPolicyCallBack() {
+bool EnableGpuBrokerPolicyCallback() {
   StartSandboxWithPolicy(GpuBrokerProcessPolicy, NULL);
   return true;
 }
 
+bool EnableArmMaliGpuBrokerPolicyCallback() {
+  StartSandboxWithPolicy(ArmMaliGpuBrokerProcessPolicy, NULL);
+  return true;
+}
+
+void AddArmMaliGpuWhitelist(std::vector<std::string>* read_whitelist,
+                            std::vector<std::string>* write_whitelist) {
+  // On ARM we're enabling the sandbox before the X connection is made,
+  // so we need to allow access to |.Xauthority|.
+  static const char kXAutorityPath[] = "/home/chronos/.Xauthority";
+
+  // Devices and files needed by the ARM GPU userspace.
+  static const char kMali0Path[] = "/dev/mali0";
+  static const char kLibGlesPath[] = "/usr/lib/libGLESv2.so.2";
+  static const char kLibEglPath[] = "/usr/lib/libEGL.so.1";
+
+  // Devices needed for video decode acceleration on ARM.
+  static const char kDevMfcDecPath[] = "/dev/mfc-dec";
+  static const char kDevGsc1Path[] = "/dev/gsc1";
+
+  read_whitelist->push_back(kXAutorityPath);
+  read_whitelist->push_back(kMali0Path);
+  read_whitelist->push_back(kLibGlesPath);
+  read_whitelist->push_back(kLibEglPath);
+  read_whitelist->push_back(kDevMfcDecPath);
+  read_whitelist->push_back(kDevGsc1Path);
+
+  write_whitelist->push_back(kMali0Path);
+  write_whitelist->push_back(kDevMfcDecPath);
+  write_whitelist->push_back(kDevGsc1Path);
+}
+
 // Start a broker process to handle open() inside the sandbox.
-void InitGpuBrokerProcess(BrokerProcess** broker_process) {
+void InitGpuBrokerProcess(Sandbox::EvaluateSyscall gpu_policy,
+                          BrokerProcess** broker_process) {
   static const char kDriRcPath[] = "/etc/drirc";
   static const char kDriCard0Path[] = "/dev/dri/card0";
 
   CHECK(broker_process);
   CHECK(*broker_process == NULL);
 
+  bool (*sandbox_callback)(void) = NULL;
+
+  // All GPU process policies need these files brokered out.
   std::vector<std::string> read_whitelist;
   read_whitelist.push_back(kDriCard0Path);
   read_whitelist.push_back(kDriRcPath);
+
   std::vector<std::string> write_whitelist;
   write_whitelist.push_back(kDriCard0Path);
 
+  if (gpu_policy == ArmMaliGpuProcessPolicy) {
+    // We shouldn't be using this policy on non-ARM architectures.
+    CHECK(IsArchitectureArm());
+
+    AddArmMaliGpuWhitelist(&read_whitelist, &write_whitelist);
+    sandbox_callback = EnableArmMaliGpuBrokerPolicyCallback;
+  } else if (gpu_policy == GpuProcessPolicy) {
+    sandbox_callback = EnableGpuBrokerPolicyCallback;
+  } else {
+    // We shouldn't be initializing a GPU broker process without a GPU process
+    // policy.
+    NOTREACHED();
+  }
+
   *broker_process = new BrokerProcess(read_whitelist, write_whitelist);
-  // Initialize the broker process and give it a sandbox call back.
-  CHECK((*broker_process)->Init(EnableGpuBrokerPolicyCallBack));
+  // Initialize the broker process and give it a sandbox callback.
+  CHECK((*broker_process)->Init(sandbox_callback));
 }
 
 // Warms up/preloads resources needed by the policies.
@@ -1482,10 +1580,10 @@
 void WarmupPolicy(Sandbox::EvaluateSyscall policy,
                   BrokerProcess** broker_process) {
   if (policy == GpuProcessPolicy) {
-    if (IsArchitectureX86_64() || IsArchitectureI386()) {
-      // Create a new broker process.
-      InitGpuBrokerProcess(broker_process);
+    // Create a new broker process.
+    InitGpuBrokerProcess(policy, broker_process);
 
+    if (IsArchitectureX86_64() || IsArchitectureI386()) {
       // Accelerated video decode dlopen()'s a shared object
       // inside the sandbox, so preload it now.
       if (IsAcceleratedVideoDecodeEnabled()) {
@@ -1500,6 +1598,9 @@
         dlopen(I965DrvVideoPath, RTLD_NOW|RTLD_GLOBAL|RTLD_NODELETE);
       }
     }
+  } else if (policy == ArmMaliGpuProcessPolicy) {
+    // Create a new broker process.
+    InitGpuBrokerProcess(policy, broker_process);
   }
 }
 
@@ -1507,12 +1608,9 @@
     const CommandLine& command_line,
     const std::string& process_type) {
   if (process_type == switches::kGpuProcess) {
-    // On Chrome OS, --enable-gpu-sandbox enables the more restrictive policy.
-    // However, we don't yet enable the more restrictive GPU process policy
-    // on ARM.
-    if (IsArchitectureArm() ||
-        (IsChromeOS() && !command_line.HasSwitch(switches::kEnableGpuSandbox)))
-      return BlacklistDebugAndNumaPolicy;
+    // On Chrome OS ARM, we need a specific GPU process policy.
+    if (IsChromeOS() && IsArchitectureArm())
+      return ArmMaliGpuProcessPolicy;
     else
       return GpuProcessPolicy;
   }
diff --git a/content/common/sandbox_win.cc b/content/common/sandbox_win.cc
index cc29215..e86d433 100644
--- a/content/common/sandbox_win.cc
+++ b/content/common/sandbox_win.cc
@@ -69,17 +69,6 @@
   L"npggNT.des",                  // GameGuard 2008.
   L"npggNT.dll",                  // GameGuard (older).
   L"oawatch.dll",                 // Online Armor.
-  L"owexplorer-10513.dll",        // Overwolf.
-  L"owexplorer-10514.dll",        // Overwolf.
-  L"owexplorer-10515.dll",        // Overwolf.
-  L"owexplorer-10516.dll",        // Overwolf.
-  L"owexplorer-10517.dll",        // Overwolf.
-  L"owexplorer-10518.dll",        // Overwolf.
-  L"owexplorer-10519.dll",        // Overwolf.
-  L"owexplorer-10520.dll",        // Overwolf.
-  L"owexplorer-10521.dll",        // Overwolf.
-  L"owexplorer-10522.dll",        // Overwolf.
-  L"owexplorer-10523.dll",        // Overwolf.
   L"pavhook.dll",                 // Panda Internet Security.
   L"pavlsphook.dll",              // Panda Antivirus.
   L"pavshook.dll",                // Panda Antivirus.
@@ -121,10 +110,8 @@
   if (!PathService::Get(path, &directory))
     return false;
 
-  if (sub_dir) {
-    directory = directory.Append(sub_dir);
-    file_util::AbsolutePath(&directory);
-  }
+  if (sub_dir)
+    directory = base::MakeAbsoluteFilePath(directory.Append(sub_dir));
 
   sandbox::ResultCode result;
   result = policy->AddRule(sandbox::TargetPolicy::SUBSYS_FILES, access,
diff --git a/content/common/seccomp_sandbox.h b/content/common/seccomp_sandbox.h
deleted file mode 100644
index 06cf9f8..0000000
--- a/content/common/seccomp_sandbox.h
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_COMMON_SECCOMP_SANDBOX_H_
-#define CONTENT_COMMON_SECCOMP_SANDBOX_H_
-
-// Seccomp enable/disable logic is centralized here.
-// - We define SECCOMP_SANDBOX if seccomp is compiled in at all: currently,
-//   on non-views (non-ChromeOS) non-ARM non-Clang Linux only.
-
-#include "build/build_config.h"
-
-#if defined(ARCH_CPU_X86_FAMILY) && !defined(CHROMIUM_SELINUX) && \
-  !defined(OS_CHROMEOS) && !defined(TOOLKIT_VIEWS) && !defined(OS_OPENBSD)
-#define SECCOMP_SANDBOX
-#include "sandbox/linux/seccomp-legacy/sandbox.h"
-#endif
-
-#endif  // CONTENT_COMMON_SECCOMP_SANDBOX_H_
diff --git a/content/common/socket_stream_dispatcher.cc b/content/common/socket_stream_dispatcher.cc
index 13a7ddf..0d35135 100644
--- a/content/common/socket_stream_dispatcher.cc
+++ b/content/common/socket_stream_dispatcher.cc
@@ -11,11 +11,14 @@
 #include "base/lazy_instance.h"
 #include "base/memory/ref_counted.h"
 #include "base/message_loop.h"
+#include "base/string16.h"
+#include "base/utf_string_conversions.h"
 #include "content/common/child_thread.h"
 #include "content/common/socket_stream.h"
 #include "content/common/socket_stream_handle_data.h"
 #include "content/common/socket_stream_messages.h"
 #include "googleurl/src/gurl.h"
+#include "net/base/net_errors.h"
 #include "webkit/glue/websocketstreamhandle_bridge.h"
 #include "webkit/glue/websocketstreamhandle_delegate.h"
 
@@ -48,18 +51,23 @@
   void OnSentData(int amount_sent);
   void OnReceivedData(const std::vector<char>& data);
   void OnClosed();
+  void OnFailed(int error_code, const char* error_msg);
 
  private:
   virtual ~IPCWebSocketStreamHandleBridge();
 
   void DoConnect(const GURL& url);
   void DoClose();
+
+  // The ID for this bridge and corresponding SocketStream instance in the
+  // browser process.
   int socket_id_;
 
   ChildThread* child_thread_;
   WebKit::WebSocketStreamHandle* handle_;
   webkit_glue::WebSocketStreamHandleDelegate* delegate_;
 
+  // Map from ID to bridge instance.
   static base::LazyInstance<IDMap<IPCWebSocketStreamHandleBridge> >::Leaky
       all_bridges;
 };
@@ -75,17 +83,20 @@
 }
 
 IPCWebSocketStreamHandleBridge::~IPCWebSocketStreamHandleBridge() {
-  DVLOG(1) << "IPCWebSocketStreamHandleBridge destructor socket_id="
-           << socket_id_;
-  if (socket_id_ != kNoSocketId) {
-    child_thread_->Send(new SocketStreamHostMsg_Close(socket_id_));
-    socket_id_ = kNoSocketId;
-  }
+  DVLOG(1) << "Bridge (" << this << ", socket_id_=" << socket_id_
+           << ") Destructor";
+
+  if (socket_id_ == kNoSocketId)
+    return;
+
+  child_thread_->Send(new SocketStreamHostMsg_Close(socket_id_));
+  socket_id_ = kNoSocketId;
 }
 
 void IPCWebSocketStreamHandleBridge::Connect(const GURL& url) {
   DCHECK(child_thread_);
-  DVLOG(1) << "Connect url=" << url;
+  DVLOG(1) << "Bridge (" << this << ") Connect (url=" << url << ")";
+
   child_thread_->message_loop()->PostTask(
       FROM_HERE,
       base::Bind(&IPCWebSocketStreamHandleBridge::DoConnect, this, url));
@@ -93,7 +104,9 @@
 
 bool IPCWebSocketStreamHandleBridge::Send(
     const std::vector<char>& data) {
-  DVLOG(1) << "Send data.size=" << data.size();
+  DVLOG(1) << "Bridge #" << socket_id_ << " Send (" << data.size()
+           << " bytes)";
+
   if (child_thread_->Send(
       new SocketStreamHostMsg_SendData(socket_id_, data))) {
     if (delegate_)
@@ -104,7 +117,8 @@
 }
 
 void IPCWebSocketStreamHandleBridge::Close() {
-  DVLOG(1) << "Close socket_id" << socket_id_;
+  DVLOG(1) << "Bridge #" << socket_id_ << " Close";
+
   AddRef();  // Released in DoClose().
   child_thread_->message_loop()->PostTask(
       FROM_HERE,
@@ -112,25 +126,33 @@
 }
 
 void IPCWebSocketStreamHandleBridge::OnConnected(int max_pending_send_allowed) {
-  DVLOG(1) << "IPCWebSocketStreamHandleBridge::OnConnected socket_id="
-           << socket_id_;
+  DVLOG(1) << "Bridge #" << socket_id_
+           << " OnConnected (max_pending_send_allowed="
+           << max_pending_send_allowed << ")";
+
   if (delegate_)
     delegate_->DidOpenStream(handle_, max_pending_send_allowed);
 }
 
 void IPCWebSocketStreamHandleBridge::OnSentData(int amount_sent) {
+  DVLOG(1) << "Bridge #" << socket_id_ << " OnSentData (" << amount_sent
+           << " bytes)";
+
   if (delegate_)
     delegate_->DidSendData(handle_, amount_sent);
 }
 
 void IPCWebSocketStreamHandleBridge::OnReceivedData(
     const std::vector<char>& data) {
+  DVLOG(1) << "Bridge #" << socket_id_ << " OnReceiveData (" << data.size()
+           << " bytes)";
   if (delegate_)
     delegate_->DidReceiveData(handle_, &data[0], data.size());
 }
 
 void IPCWebSocketStreamHandleBridge::OnClosed() {
-  DVLOG(1) << "IPCWebSocketStreamHandleBridge::OnClosed";
+  DVLOG(1) << "Bridge #" << socket_id_ << " OnClosed";
+
   if (socket_id_ != kNoSocketId) {
     all_bridges.Get().Remove(socket_id_);
     socket_id_ = kNoSocketId;
@@ -141,6 +163,14 @@
   Release();
 }
 
+void IPCWebSocketStreamHandleBridge::OnFailed(int error_code,
+                                              const char* error_msg) {
+  DVLOG(1) << "Bridge #" << socket_id_ << " OnFailed (error_code=" << error_code
+           << ")";
+  if (delegate_)
+    delegate_->DidFail(handle_, error_code, ASCIIToUTF16(error_msg));
+}
+
 void IPCWebSocketStreamHandleBridge::DoConnect(const GURL& url) {
   DCHECK(child_thread_);
   DCHECK_EQ(socket_id_, kNoSocketId);
@@ -157,10 +187,10 @@
   AddRef();  // Released in OnClosed().
   if (child_thread_->Send(
       new SocketStreamHostMsg_Connect(render_view_id, url, socket_id_))) {
-    DVLOG(1) << "Connect socket_id=" << socket_id_;
+    DVLOG(1) << "Bridge #" << socket_id_ << " sent IPC Connect";
     // TODO(ukai): timeout to OnConnected.
   } else {
-    DLOG(ERROR) << "IPC SocketStream_Connect failed.";
+    DLOG(ERROR) << "Bridge #" << socket_id_ << " failed to send IPC Connect";
     OnClosed();
   }
 }
@@ -189,6 +219,7 @@
     IPC_MESSAGE_HANDLER(SocketStreamMsg_SentData, OnSentData)
     IPC_MESSAGE_HANDLER(SocketStreamMsg_ReceivedData, OnReceivedData)
     IPC_MESSAGE_HANDLER(SocketStreamMsg_Closed, OnClosed)
+    IPC_MESSAGE_HANDLER(SocketStreamMsg_Failed, OnFailed)
     IPC_MESSAGE_UNHANDLED(handled = false)
   IPC_END_MESSAGE_MAP()
   return handled;
@@ -196,42 +227,60 @@
 
 void SocketStreamDispatcher::OnConnected(int socket_id,
                                          int max_pending_send_allowed) {
-  DVLOG(1) << "SocketStreamDispatcher::OnConnected socket_id=" << socket_id
-           << " max_pending_send_allowed=" << max_pending_send_allowed;
+  DVLOG(1) << "SocketStreamDispatcher::OnConnected (max_pending_send_allowed="
+           << max_pending_send_allowed << ") to socket_id=" << socket_id;
+
   IPCWebSocketStreamHandleBridge* bridge =
       IPCWebSocketStreamHandleBridge::FromSocketId(socket_id);
   if (bridge)
     bridge->OnConnected(max_pending_send_allowed);
   else
-    DLOG(ERROR) << "No SocketStreamHandleBridge for socket_id=" << socket_id;
+    DLOG(ERROR) << "No bridge for socket_id=" << socket_id;
 }
 
 void SocketStreamDispatcher::OnSentData(int socket_id, int amount_sent) {
+  DVLOG(1) << "SocketStreamDispatcher::OnSentData (" << amount_sent
+           << " bytes) to socket_id=" << socket_id;
+
   IPCWebSocketStreamHandleBridge* bridge =
       IPCWebSocketStreamHandleBridge::FromSocketId(socket_id);
   if (bridge)
     bridge->OnSentData(amount_sent);
   else
-    DLOG(ERROR) << "No SocketStreamHandleBridge for socket_id=" << socket_id;
+    DLOG(ERROR) << "No bridge for socket_id=" << socket_id;
 }
 
 void SocketStreamDispatcher::OnReceivedData(
     int socket_id, const std::vector<char>& data) {
+  DVLOG(1) << "SocketStreamDispatcher::OnReceivedData (" << data.size()
+           << " bytes) to socket_id=" << socket_id;
+
   IPCWebSocketStreamHandleBridge* bridge =
       IPCWebSocketStreamHandleBridge::FromSocketId(socket_id);
   if (bridge)
     bridge->OnReceivedData(data);
   else
-    DLOG(ERROR) << "No SocketStreamHandleBridge for socket_id=" << socket_id;
+    DLOG(ERROR) << "No bridge for socket_id=" << socket_id;
 }
 
 void SocketStreamDispatcher::OnClosed(int socket_id) {
+  DVLOG(1) << "SocketStreamDispatcher::OnClosed to socket_id=" << socket_id;
+
   IPCWebSocketStreamHandleBridge* bridge =
       IPCWebSocketStreamHandleBridge::FromSocketId(socket_id);
   if (bridge)
     bridge->OnClosed();
   else
-    DLOG(ERROR) << "No SocketStreamHandleBridge for socket_id=" << socket_id;
+    DLOG(ERROR) << "No bridge for socket_id=" << socket_id;
+}
+
+void SocketStreamDispatcher::OnFailed(int socket_id, int error_code) {
+  IPCWebSocketStreamHandleBridge* bridge =
+      IPCWebSocketStreamHandleBridge::FromSocketId(socket_id);
+  if (bridge)
+    bridge->OnFailed(error_code, net::ErrorToString(error_code));
+  else
+    DLOG(ERROR) << "No bridge for socket_id=" << socket_id;
 }
 
 }  // namespace content
diff --git a/content/common/socket_stream_dispatcher.h b/content/common/socket_stream_dispatcher.h
index 2a67f73..b619623 100644
--- a/content/common/socket_stream_dispatcher.h
+++ b/content/common/socket_stream_dispatcher.h
@@ -43,6 +43,7 @@
   void OnSentData(int socket_id, int amount_sent);
   void OnReceivedData(int socket_id, const std::vector<char>& data);
   void OnClosed(int socket_id);
+  void OnFailed(int socket_id, int error_code);
 
   DISALLOW_COPY_AND_ASSIGN(SocketStreamDispatcher);
 };
diff --git a/content/common/socket_stream_messages.h b/content/common/socket_stream_messages.h
index 020796d..47eea33 100644
--- a/content/common/socket_stream_messages.h
+++ b/content/common/socket_stream_messages.h
@@ -73,3 +73,8 @@
 // The Socket Stream is closed.
 IPC_MESSAGE_CONTROL1(SocketStreamMsg_Closed,
                      int /* socket_id */)
+
+// The Socket Stream is failed.
+IPC_MESSAGE_CONTROL2(SocketStreamMsg_Failed,
+                     int /* socket_id */,
+                     int /* error_code */)
diff --git a/content/common/ssl_status_serialization.h b/content/common/ssl_status_serialization.h
index d913453..e3db1a2 100644
--- a/content/common/ssl_status_serialization.h
+++ b/content/common/ssl_status_serialization.h
@@ -7,7 +7,7 @@
 
 #include <string>
 
-#include "net/base/cert_status_flags.h"
+#include "net/cert/cert_status_flags.h"
 
 namespace content {
 
diff --git a/content/common/swapped_out_messages.cc b/content/common/swapped_out_messages.cc
index d94f0b9..5fe91cb 100644
--- a/content/common/swapped_out_messages.cc
+++ b/content/common/swapped_out_messages.cc
@@ -5,6 +5,7 @@
 #include "content/common/swapped_out_messages.h"
 
 #include "content/common/accessibility_messages.h"
+#include "content/common/input_messages.h"
 #include "content/common/view_messages.h"
 #include "content/public/common/content_client.h"
 
@@ -16,7 +17,7 @@
   // consistent in case we later return to the same renderer.
   switch (msg->type()) {
     // Handled by RenderWidget.
-    case ViewHostMsg_HandleInputEvent_ACK::ID:
+    case InputHostMsg_HandleInputEvent_ACK::ID:
     case ViewHostMsg_PaintAtSize_ACK::ID:
     case ViewHostMsg_UpdateRect::ID:
     // Allow targeted navigations while swapped out.
diff --git a/content/common/view_messages.h b/content/common/view_messages.h
index c87ff49..2f3756e 100644
--- a/content/common/view_messages.h
+++ b/content/common/view_messages.h
@@ -12,13 +12,13 @@
 #include "cc/output/compositor_frame_ack.h"
 #include "content/common/content_export.h"
 #include "content/common/content_param_traits.h"
-#include "content/common/edit_command.h"
 #include "content/common/navigation_gesture.h"
 #include "content/common/pepper_renderer_instance_data.h"
 #include "content/common/view_message_enums.h"
 #include "content/port/common/input_event_ack_state.h"
 #include "content/public/common/common_param_traits.h"
 #include "content/public/common/context_menu_params.h"
+#include "content/public/common/favicon_url.h"
 #include "content/public/common/file_chooser_params.h"
 #include "content/public/common/frame_navigate_params.h"
 #include "content/public/common/javascript_message_type.h"
@@ -38,7 +38,6 @@
 #include "third_party/WebKit/Source/Platform/chromium/public/WebFloatRect.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/WebInputEvent.h"
 #include "third_party/WebKit/Source/WebKit/chromium/public/WebMediaPlayerAction.h"
 #include "third_party/WebKit/Source/WebKit/chromium/public/WebPluginAction.h"
 #include "third_party/WebKit/Source/WebKit/chromium/public/WebPopupType.h"
@@ -74,8 +73,8 @@
 IPC_ENUM_TRAITS(WebKit::WebTextDirection)
 IPC_ENUM_TRAITS(WebMenuItem::Type)
 IPC_ENUM_TRAITS(WindowContainerType)
+IPC_ENUM_TRAITS(content::FaviconURL::IconType)
 IPC_ENUM_TRAITS(content::FileChooserParams::Mode)
-IPC_ENUM_TRAITS(content::InputEventAckState)
 IPC_ENUM_TRAITS(content::JavaScriptMessageType)
 IPC_ENUM_TRAITS(content::NavigationGesture)
 IPC_ENUM_TRAITS(content::PageZoom)
@@ -193,9 +192,9 @@
   IPC_STRUCT_TRAITS_MEMBER(render_widget_id)
 IPC_STRUCT_TRAITS_END()
 
-IPC_STRUCT_TRAITS_BEGIN(content::EditCommand)
-  IPC_STRUCT_TRAITS_MEMBER(name)
-  IPC_STRUCT_TRAITS_MEMBER(value)
+IPC_STRUCT_TRAITS_BEGIN(content::FaviconURL)
+  IPC_STRUCT_TRAITS_MEMBER(icon_url)
+  IPC_STRUCT_TRAITS_MEMBER(icon_type)
 IPC_STRUCT_TRAITS_END()
 
 IPC_STRUCT_TRAITS_BEGIN(content::FileChooserParams)
@@ -422,6 +421,10 @@
 
   // User agent override used to navigate.
   IPC_STRUCT_MEMBER(bool, is_overriding_user_agent)
+
+  // Notifies the browser that for this navigation, the session history was
+  // successfully cleared.
+  IPC_STRUCT_MEMBER(bool, history_list_was_cleared)
 IPC_STRUCT_END()
 
 IPC_STRUCT_BEGIN(ViewHostMsg_OpenURL_Params)
@@ -573,6 +576,11 @@
   IPC_STRUCT_MEMBER(int, current_history_list_offset)
   IPC_STRUCT_MEMBER(int, current_history_list_length)
 
+  // Informs the RenderView the session history should be cleared. In that
+  // case, the RenderView needs to notify the browser that the clearing was
+  // succesful when the navigation commits.
+  IPC_STRUCT_MEMBER(bool, should_clear_history_list)
+
   // The URL to load.
   IPC_STRUCT_MEMBER(GURL, url)
 
@@ -629,6 +637,9 @@
 
   // If not empty, which frame to navigate.
   IPC_STRUCT_MEMBER(std::string, frame_to_navigate)
+
+  // The navigationStart time to expose to JS for this navigation.
+  IPC_STRUCT_MEMBER(base::TimeTicks, browser_navigation_start)
 IPC_STRUCT_END()
 
 IPC_STRUCT_BEGIN(ViewMsg_New_Params)
@@ -636,7 +647,7 @@
   IPC_STRUCT_MEMBER(content::RendererPreferences, renderer_preferences)
 
   // Preferences for this view.
-  IPC_STRUCT_MEMBER(webkit_glue::WebPreferences, web_preferences)
+  IPC_STRUCT_MEMBER(WebPreferences, web_preferences)
 
   // The ID of the view to be created.
   IPC_STRUCT_MEMBER(int32, view_id)
@@ -682,14 +693,6 @@
   // the source process.  The browser replaces it with the routing ID of the
   // equivalent (swapped out) frame in the destination process.
   IPC_STRUCT_MEMBER(int, source_routing_id)
-  // The identifier of the source frame in the source process.
-  IPC_STRUCT_MEMBER(int, source_frame_id)
-
-  // The full set of identifiers to uniquely describe the target frame. See
-  // the comment on ViewMsg_FrameTreeUpdated for details.
-  IPC_STRUCT_MEMBER(int, target_process_id)
-  IPC_STRUCT_MEMBER(int, target_routing_id)
-  IPC_STRUCT_MEMBER(int, target_frame_id)
 
   // The origin of the source frame.
   IPC_STRUCT_MEMBER(string16, source_origin)
@@ -750,7 +753,7 @@
 IPC_MESSAGE_ROUTED1(ViewMsg_OrientationChangeEvent,
                     int /* orientation */)
 
-// Sent by the renderer when the parameters for vsync alignment have changed.
+// Sent by the browser when the parameters for vsync alignment have changed.
 IPC_MESSAGE_ROUTED2(ViewMsg_UpdateVSyncParameters,
                     base::TimeTicks /* timebase */,
                     base::TimeDelta /* interval */)
@@ -790,7 +793,7 @@
 
 // This passes a set of webkit preferences down to the renderer.
 IPC_MESSAGE_ROUTED1(ViewMsg_UpdateWebPreferences,
-                    webkit_glue::WebPreferences)
+                    WebPreferences)
 
 // Informs the renderer that the timezone has changed.
 IPC_MESSAGE_ROUTED0(ViewMsg_TimezoneChange)
@@ -856,50 +859,14 @@
 // compositor path.
 IPC_MESSAGE_ROUTED0(ViewMsg_SwapBuffers_ACK)
 
-// Sends an input event to the render widget.
-IPC_MESSAGE_ROUTED2(ViewMsg_HandleInputEvent,
-                    IPC::WebInputEventPointer /* event */,
-                    bool /* is_keyboard_shortcut */)
-
 // Tells the render widget that a smooth scroll completed.
-IPC_MESSAGE_ROUTED1(ViewMsg_SmoothScrollCompleted,
-                    int /* gesture_id */)
-
-// This message notifies the renderer that the next key event is bound to one
-// or more pre-defined edit commands. If the next key event is not handled
-// by webkit, the specified edit commands shall be executed against current
-// focused frame.
-// Parameters
-// * edit_commands (see chrome/common/edit_command_types.h)
-//   Contains one or more edit commands.
-// 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.
-IPC_MESSAGE_ROUTED1(ViewMsg_SetEditCommandsForNextKeyEvent,
-                    std::vector<content::EditCommand> /* edit_commands */)
-
-// Message payload is the name/value of a WebCore edit command to execute.
-IPC_MESSAGE_ROUTED2(ViewMsg_ExecuteEditCommand,
-                    std::string, /* name */
-                    std::string /* value */)
-
-IPC_MESSAGE_ROUTED0(ViewMsg_MouseCaptureLost)
-
-// TODO(darin): figure out how this meshes with RestoreFocus
-IPC_MESSAGE_ROUTED1(ViewMsg_SetFocus,
-                    bool /* enable */)
+IPC_MESSAGE_ROUTED0(ViewMsg_SmoothScrollCompleted)
 
 // Tells the renderer to focus the first (last if reverse is true) focusable
 // node.
 IPC_MESSAGE_ROUTED1(ViewMsg_SetInitialFocus,
                     bool /* reverse */)
 
-// Tells the renderer to scroll the currently focused node into rect only if
-// the currently focused node is a Text node (textfield, text area or content
-// editable divs).
-IPC_MESSAGE_ROUTED1(ViewMsg_ScrollFocusedEditableNodeIntoRect, gfx::Rect)
-
 // Executes custom context menu action that was provided from WebKit.
 IPC_MESSAGE_ROUTED2(ViewMsg_CustomContextMenuAction,
                     content::CustomContextMenuContext /* custom_context */,
@@ -910,6 +877,9 @@
 IPC_MESSAGE_ROUTED1(ViewMsg_ContextMenuClosed,
                     content::CustomContextMenuContext /* custom_context */)
 
+// Sent to inform the renderer to invoke a context menu.
+IPC_MESSAGE_ROUTED0(ViewMsg_ShowContextMenu)
+
 // Tells the renderer to perform the specified navigation, interrupting any
 // existing navigation.
 IPC_MESSAGE_ROUTED1(ViewMsg_Navigate, ViewMsg_Navigate_Params)
@@ -930,44 +900,10 @@
 IPC_MESSAGE_ROUTED1(ViewMsg_StopFinding,
                     content::StopFindAction /* action */)
 
-// These messages are typically generated from context menus and request the
-// renderer to apply the specified operation to the current selection.
-IPC_MESSAGE_ROUTED0(ViewMsg_Undo)
-IPC_MESSAGE_ROUTED0(ViewMsg_Redo)
-IPC_MESSAGE_ROUTED0(ViewMsg_Cut)
-IPC_MESSAGE_ROUTED0(ViewMsg_Copy)
-#if defined(OS_MACOSX)
-IPC_MESSAGE_ROUTED0(ViewMsg_CopyToFindPboard)
-#endif
-IPC_MESSAGE_ROUTED0(ViewMsg_Paste)
-IPC_MESSAGE_ROUTED0(ViewMsg_PasteAndMatchStyle)
-// Replaces the selected region or a word around the cursor with the
-// specified string.
-IPC_MESSAGE_ROUTED1(ViewMsg_Replace,
-                    string16)
-// Replaces the misspelling in the selected region with the specified string.
-IPC_MESSAGE_ROUTED1(ViewMsg_ReplaceMisspelling,
-                    string16)
-IPC_MESSAGE_ROUTED0(ViewMsg_Delete)
-IPC_MESSAGE_ROUTED0(ViewMsg_SelectAll)
-
 // Replaces a date time input field.
 IPC_MESSAGE_ROUTED1(ViewMsg_ReplaceDateTime,
                     ViewHostMsg_DateTimeDialogValue_Params /* value */)
 
-IPC_MESSAGE_ROUTED0(ViewMsg_Unselect)
-
-// Requests the renderer to select the region between two points.
-// Expects a SelectRange_ACK message when finished.
-IPC_MESSAGE_ROUTED2(ViewMsg_SelectRange,
-                    gfx::Point /* start */,
-                    gfx::Point /* end */)
-
-// Requests the renderer to move the caret selection toward the point.
-// Expects a MoveCaret_ACK message when finished.
-IPC_MESSAGE_ROUTED1(ViewMsg_MoveCaret,
-                    gfx::Point /* location */)
-
 // Copies the image at location x, y to the clipboard (if there indeed is an
 // image at that location).
 IPC_MESSAGE_ROUTED2(ViewMsg_CopyImageAt,
@@ -1022,16 +958,6 @@
 // Requests that the RenderView's main frame sets its opener to null.
 IPC_MESSAGE_ROUTED0(ViewMsg_DisownOpener)
 
-// Sends a JSON serialized frame tree to RenderView along with the process id
-// and route id of the source renderer.
-//
-// This message must be sent to swapped out RenderViews every time the browser
-// receives a ViewHostMsg_FrameTreeUpdated message.
-IPC_MESSAGE_ROUTED3(ViewMsg_UpdateFrameTree,
-                    int, /* the child process id of the active renderer */
-                    int, /* route_id of the active renderer */
-                    std::string /* json encoded frame tree */)
-
 // Request for the renderer to evaluate an xpath to a frame and insert css
 // into that frame's document. See ViewMsg_ScriptEvalRequest for details on
 // allowed xpath expressions.
@@ -1245,9 +1171,6 @@
 IPC_MESSAGE_ROUTED1(ViewMsg_SetActive,
                     bool /* active */)
 
-IPC_MESSAGE_ROUTED1(ViewMsg_SetNavigationStartTime,
-                    base::TimeTicks /* browser_navigation_start */)
-
 // Response message to ViewHostMsg_CreateShared/DedicatedWorker.
 // Sent when the worker has started.
 IPC_MESSAGE_ROUTED0(ViewMsg_WorkerCreated)
@@ -1319,13 +1242,6 @@
                      bool /* suspend */)
 
 #if defined(OS_ANDROID)
-// Sent when the user clicks on the find result bar to activate a find result.
-// The point (x,y) is in fractions of the content document's width and height.
-IPC_MESSAGE_ROUTED3(ViewMsg_ActivateNearestFindResult,
-                    int /* request_id */,
-                    float /* x */,
-                    float /* y */)
-
 // Sent when the browser wants the bounding boxes of the current find matches.
 //
 // If match rects are already cached on the browser side, |current_version|
@@ -1352,12 +1268,20 @@
 IPC_MESSAGE_ROUTED1(ViewMsg_ImeBatchStateChanged,
     bool /* is_begin */)
 
-// Notifies the renderer whether hiding the top controls is enabled.
-IPC_MESSAGE_ROUTED1(ViewMsg_EnableHidingTopControls,
-                    bool /* enable */)
+// Notifies the renderer whether hiding/showing the top controls is enabled
+// and whether or not to animate to the proper state.
+IPC_MESSAGE_ROUTED3(ViewMsg_UpdateTopControlsState,
+                    bool /* enable_hiding */,
+                    bool /* enable_showing */,
+                    bool /* animate */)
 
 IPC_MESSAGE_ROUTED0(ViewMsg_ShowImeIfNeeded)
 
+// Sent by the browser when the display vsync signal was triggered and the
+// renderer should generate a new frame.
+IPC_MESSAGE_ROUTED1(ViewMsg_DidVSync,
+                    base::TimeTicks /* frame_time */)
+
 #elif defined(OS_MACOSX)
 // Let the RenderView know its window has changed visibility.
 IPC_MESSAGE_ROUTED1(ViewMsg_SetWindowVisibility,
@@ -1387,13 +1311,9 @@
 IPC_MESSAGE_ROUTED1(ViewMsg_SwapCompositorFrameAck,
                     cc::CompositorFrameAck /* ack */)
 
-// Sent from the browser to ask the renderer for a snapshot of the current view.
-// The renderer replies with whether the snapshot succeeded and the SkBitmap.
+// Sent by the browser to ask the renderer for a snapshot of the current view.
 IPC_MESSAGE_ROUTED1(ViewMsg_Snapshot,
                     gfx::Rect /* src_subrect */)
-IPC_MESSAGE_ROUTED2(ViewHostMsg_Snapshot,
-                    bool, /* success */
-                    SkBitmap /* bitmap */)
 
 // -----------------------------------------------------------------------------
 // Messages sent from the renderer to the browser.
@@ -1679,11 +1599,6 @@
 IPC_MESSAGE_ROUTED1(ViewHostMsg_DidActivateAcceleratedCompositing,
                     bool /* true if the accelerated compositor is actve */)
 
-// Acknowledges receipt of a ViewMsg_HandleInputEvent message.
-IPC_MESSAGE_ROUTED2(ViewHostMsg_HandleInputEvent_ACK,
-                    WebKit::WebInputEvent::Type,
-                    content::InputEventAckState /* ack_result */)
-
 IPC_STRUCT_BEGIN(ViewHostMsg_BeginSmoothScroll_Params)
   IPC_STRUCT_MEMBER(bool, scroll_down)
   IPC_STRUCT_MEMBER(int, pixels_to_scroll)
@@ -1691,8 +1606,7 @@
   IPC_STRUCT_MEMBER(int, mouse_event_y)
 IPC_STRUCT_END()
 
-IPC_MESSAGE_ROUTED2(ViewHostMsg_BeginSmoothScroll,
-                    int /* gesture_id */,
+IPC_MESSAGE_ROUTED1(ViewHostMsg_BeginSmoothScroll,
                     ViewHostMsg_BeginSmoothScroll_Params /* params */)
 
 IPC_MESSAGE_ROUTED0(ViewHostMsg_Focus)
@@ -2122,6 +2036,12 @@
                     int /* flags */,
                     int /* message_id */)
 
+// Reply to a snapshot request containing whether snapshotting succeeded and the
+// SkBitmap if it succeeded.
+IPC_MESSAGE_ROUTED2(ViewHostMsg_Snapshot,
+                    bool, /* success */
+                    SkBitmap /* bitmap */)
+
 //---------------------------------------------------------------------------
 // Request for cryptographic operation messages:
 // These are messages from the renderer to the browser to perform a
@@ -2193,8 +2113,8 @@
                     int32 /* complete status */)
 
 // Notifies the browser of an event occurring in the media pipeline.
-IPC_MESSAGE_CONTROL1(ViewHostMsg_MediaLogEvent,
-                     media::MediaLogEvent /* event */)
+IPC_MESSAGE_CONTROL1(ViewHostMsg_MediaLogEvents,
+                     std::vector<media::MediaLogEvent> /* events */)
 
 // Requests to lock the mouse. Will result in a ViewMsg_LockMouse_ACK message
 // being sent back.
@@ -2229,37 +2149,6 @@
                     base::FilePath /* path */,
                     bool /* is_hung */)
 
-// Chrome allows JavaScript calls to be routed across process boundaries. To
-// achieve this, each active RenderView in the source process has a swapped out
-// "mirror" in the target process. The active RenderView and its mirror
-// need to have identical frame tree structure, so calls originating in and
-// targeting subframes can be routed properly. This is achieved by each active
-// RenderView sending a ViewHostMsg_FrameTreeUpdated message to the browser,
-// which in turn sends the update to the corresponding mirror RenderView(s)
-// through the ViewMsg_UpdateFrameTree. We use best effort to keep these
-// trees synchronized across processes.
-//
-// When routing JavaScript calls across processes, the target information
-// is kept in the renderer process instead of the browser process. This design
-// was chosen because frame ids are allocated by the renderer process. If the
-// browser was to keep a mapping of the frame ids across processes, it would
-// require an extra IPC message with the newly allocated frame ids, as a
-// response to this particular message.
-//
-// The frame tree for a RenderView is serialized to JSON, so it can be sent to
-// the browser process. Each node in the tree is an object with three
-// properties:
-// * id - (integer) the frame identifier in this RenderView
-// * name - (string) the name of the frame, if one has been assigned
-// * subtree - an array of the same type of objects for each frame that is a
-//     direct child of the current frame. This property can be omitted if
-//     there are no direct child frames, so less data is transferred.
-//
-// This message must be sent on any events that modify the tree structure or
-// the names of any frames.
-IPC_MESSAGE_ROUTED1(ViewHostMsg_FrameTreeUpdated,
-                    std::string /* json encoded frame tree */)
-
 // Notifies that multiple touch targets may have been pressed, and to show
 // the disambiguation popup.
 IPC_MESSAGE_ROUTED3(ViewHostMsg_ShowDisambiguationPopup,
@@ -2292,6 +2181,16 @@
 // first paint.
 IPC_MESSAGE_ROUTED0(ViewHostMsg_WillInsertBody)
 
+// Notification that the urls for the favicon of a site has been determined.
+IPC_MESSAGE_ROUTED2(ViewHostMsg_UpdateFaviconURL,
+                    int32 /* page_id */,
+                    std::vector<content::FaviconURL> /* candidates */)
+
+// Sent once a paint happens after the first non empty layout. In other words
+// after the page has painted something.
+IPC_MESSAGE_ROUTED1(ViewHostMsg_DidFirstVisuallyNonEmptyPaint,
+                    int /* page_id */)
+
 #if defined(OS_ANDROID)
 // Response to ViewMsg_FindMatchRects.
 //
@@ -2321,20 +2220,23 @@
 IPC_MESSAGE_ROUTED1(ViewHostMsg_DidChangeBodyBackgroundColor,
                     uint32  /* bg_color */)
 
-// Information about current document scroll, scale and size. Sent on a
-// best-effort basis.
-IPC_MESSAGE_ROUTED5(ViewHostMsg_UpdateFrameInfo,
-                    gfx::Vector2d /* scroll_offset */,
-                    float /* page_scale_factor */,
-                    float /* min_page_scale_factor */,
-                    float /* max_page_scale_factor */,
-                    gfx::Size /* content_size */)
-
 // This message is an ACK that the batch state change has been received by
 // the renderer and all IME related messages should be processed accordingly.
 IPC_MESSAGE_ROUTED1(ViewHostMsg_ImeBatchStateChanged_ACK,
                     bool /* is_begin */)
 
+// This message runs the MediaCodec for decoding audio for webaudio.
+IPC_MESSAGE_CONTROL3(ViewHostMsg_RunWebAudioMediaCodec,
+                     base::SharedMemoryHandle /* encoded_data_handle */,
+                     base::FileDescriptor /* pcm_output */,
+                     size_t /* data_size*/)
+
+// Sent by renderer to request a ViewMsg_VSync message for upcoming display
+// vsync events. If |enabled| is true, the vsync message will continue to be be
+// delivered until the notification is disabled.
+IPC_MESSAGE_ROUTED1(ViewHostMsg_SetVSyncNotificationEnabled,
+                    bool /* enabled */)
+
 #elif defined(OS_MACOSX)
 // Request that the browser load a font into shared memory for us.
 IPC_SYNC_MESSAGE_CONTROL1_3(ViewHostMsg_LoadFont,
diff --git a/content/common/webkitplatformsupport_impl.cc b/content/common/webkitplatformsupport_impl.cc
index 1af22f8..b6c0728 100644
--- a/content/common/webkitplatformsupport_impl.cc
+++ b/content/common/webkitplatformsupport_impl.cc
@@ -9,6 +9,25 @@
 #include "content/public/common/content_client.h"
 #include "googleurl/src/gurl.h"
 
+#if defined(OS_ANDROID)
+#include "base/file_descriptor_posix.h"
+#include "base/shared_memory.h"
+#include "content/common/view_messages.h"
+
+namespace {
+void RunWebAudioMediaCodec(
+    base::SharedMemoryHandle encoded_data_handle,
+    base::FileDescriptor pcm_output,
+    size_t data_size) {
+  content::ChildThread::current()->Send(
+      new ViewHostMsg_RunWebAudioMediaCodec(encoded_data_handle,
+                                            pcm_output,
+                                            data_size));
+}
+
+} // anonymous namespace
+#endif
+
 namespace content {
 
 WebKitPlatformSupportImpl::WebKitPlatformSupportImpl() {
@@ -49,4 +68,11 @@
   return dispatcher->CreateBridge(handle, delegate);
 }
 
+#if defined(OS_ANDROID)
+webkit_media::WebAudioMediaCodecRunner
+WebKitPlatformSupportImpl::GetWebAudioMediaCodecRunner() {
+  return base::Bind(&RunWebAudioMediaCodec);
+}
+#endif
+
 }  // namespace content
diff --git a/content/common/webkitplatformsupport_impl.h b/content/common/webkitplatformsupport_impl.h
index de778a2..c56ed05 100644
--- a/content/common/webkitplatformsupport_impl.h
+++ b/content/common/webkitplatformsupport_impl.h
@@ -34,6 +34,10 @@
   virtual webkit_glue::WebSocketStreamHandleBridge* CreateWebSocketBridge(
       WebKit::WebSocketStreamHandle* handle,
       webkit_glue::WebSocketStreamHandleDelegate* delegate) OVERRIDE;
+#if defined(OS_ANDROID)
+  virtual webkit_media::WebAudioMediaCodecRunner GetWebAudioMediaCodecRunner()
+      OVERRIDE;
+#endif
 };
 
 }  // namespace content
diff --git a/content/common/webmessageportchannel_impl.cc b/content/common/webmessageportchannel_impl.cc
index 1833ec1..93e0232 100644
--- a/content/common/webmessageportchannel_impl.cc
+++ b/content/common/webmessageportchannel_impl.cc
@@ -80,11 +80,11 @@
 void WebMessagePortChannelImpl::postMessage(
     const WebString& message,
     WebMessagePortChannelArray* channels) {
-  if (MessageLoop::current() != ChildThread::current()->message_loop()) {
+  if (base::MessageLoop::current() != ChildThread::current()->message_loop()) {
     ChildThread::current()->message_loop()->PostTask(
         FROM_HERE,
-        base::Bind(&WebMessagePortChannelImpl::postMessage, this,
-                   message, channels));
+        base::Bind(
+            &WebMessagePortChannelImpl::postMessage, this, message, channels));
     return;
   }
 
@@ -127,10 +127,9 @@
 }
 
 void WebMessagePortChannelImpl::Init() {
-  if (MessageLoop::current() != ChildThread::current()->message_loop()) {
+  if (base::MessageLoop::current() != ChildThread::current()->message_loop()) {
     ChildThread::current()->message_loop()->PostTask(
-        FROM_HERE,
-        base::Bind(&WebMessagePortChannelImpl::Init, this));
+        FROM_HERE, base::Bind(&WebMessagePortChannelImpl::Init, this));
     return;
   }
 
@@ -145,7 +144,7 @@
 
 void WebMessagePortChannelImpl::Entangle(
     scoped_refptr<WebMessagePortChannelImpl> channel) {
-  if (MessageLoop::current() != ChildThread::current()->message_loop()) {
+  if (base::MessageLoop::current() != ChildThread::current()->message_loop()) {
     ChildThread::current()->message_loop()->PostTask(
         FROM_HERE,
         base::Bind(&WebMessagePortChannelImpl::Entangle, this, channel));
@@ -157,10 +156,9 @@
 }
 
 void WebMessagePortChannelImpl::QueueMessages() {
-  if (MessageLoop::current() != ChildThread::current()->message_loop()) {
+  if (base::MessageLoop::current() != ChildThread::current()->message_loop()) {
     ChildThread::current()->message_loop()->PostTask(
-        FROM_HERE,
-        base::Bind(&WebMessagePortChannelImpl::QueueMessages, this));
+        FROM_HERE, base::Bind(&WebMessagePortChannelImpl::QueueMessages, this));
     return;
   }
   // This message port is being sent elsewhere (perhaps to another process).
@@ -177,7 +175,7 @@
 }
 
 void WebMessagePortChannelImpl::Send(IPC::Message* message) {
-  if (MessageLoop::current() != ChildThread::current()->message_loop()) {
+  if (base::MessageLoop::current() != ChildThread::current()->message_loop()) {
     DCHECK(!message->is_sync());
     ChildThread::current()->message_loop()->PostTask(
         FROM_HERE,
diff --git a/content/common_aidl.target.darwin-arm.mk b/content/common_aidl.target.darwin-arm.mk
new file mode 100644
index 0000000..a4ade8f
--- /dev/null
+++ b/content/common_aidl.target.darwin-arm.mk
@@ -0,0 +1,153 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := content_common_aidl_gyp
+LOCAL_MODULE_STEM := common_aidl
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+
+### Generated for rule "content_content_gyp_common_aidl_target_compile_aidl":
+# "{'inputs': ['$(GYP_ABS_ANDROID_TOP_DIR)/prebuilts/sdk/17/framework.aidl', 'public/android/java/src/org/chromium/content/common/common.aidl'], 'extension': 'aidl', 'rule_sources': ['public/android/java/src/org/chromium/content/common/IChildProcessCallback.aidl', 'public/android/java/src/org/chromium/content/common/IChildProcessService.aidl'], 'rule_name': 'compile_aidl', 'outputs': ['$(gyp_shared_intermediate_dir)/common_aidl/aidl/%(INPUT_ROOT)s.java'], 'action': ['$(GYP_ABS_ANDROID_TOP_DIR)/prebuilts/sdk/tools/darwin/aidl', '-p$(GYP_ABS_ANDROID_TOP_DIR)/prebuilts/sdk/17/framework.aidl', '-ppublic/android/java/src/org/chromium/content/common/common.aidl', '$(RULE_SOURCES)', '$(gyp_shared_intermediate_dir)/common_aidl/aidl/%(INPUT_ROOT)s.java']}":
+$(gyp_shared_intermediate_dir)/common_aidl/aidl/IChildProcessCallback.java: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/common_aidl/aidl/IChildProcessCallback.java: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
+$(gyp_shared_intermediate_dir)/common_aidl/aidl/IChildProcessCallback.java: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
+$(gyp_shared_intermediate_dir)/common_aidl/aidl/IChildProcessCallback.java: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/common_aidl/aidl/IChildProcessCallback.java: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/common/IChildProcessCallback.aidl $(GYP_ABS_ANDROID_TOP_DIR)/prebuilts/sdk/17/framework.aidl $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/common/common.aidl $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/common_aidl/aidl; cd $(gyp_local_path)/content; "$(GYP_ABS_ANDROID_TOP_DIR)/prebuilts/sdk/tools/darwin/aidl" "-p$(GYP_ABS_ANDROID_TOP_DIR)/prebuilts/sdk/17/framework.aidl" -ppublic/android/java/src/org/chromium/content/common/common.aidl public/android/java/src/org/chromium/content/common/IChildProcessCallback.aidl "$(gyp_shared_intermediate_dir)/common_aidl/aidl/IChildProcessCallback.java"
+
+.PHONY: content_common_aidl_gyp_rule_trigger
+content_common_aidl_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/common_aidl/aidl/IChildProcessCallback.java
+
+$(gyp_shared_intermediate_dir)/common_aidl/aidl/IChildProcessService.java: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/common_aidl/aidl/IChildProcessService.java: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
+$(gyp_shared_intermediate_dir)/common_aidl/aidl/IChildProcessService.java: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
+$(gyp_shared_intermediate_dir)/common_aidl/aidl/IChildProcessService.java: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/common_aidl/aidl/IChildProcessService.java: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/common/IChildProcessService.aidl $(GYP_ABS_ANDROID_TOP_DIR)/prebuilts/sdk/17/framework.aidl $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/common/common.aidl $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/common_aidl/aidl; cd $(gyp_local_path)/content; "$(GYP_ABS_ANDROID_TOP_DIR)/prebuilts/sdk/tools/darwin/aidl" "-p$(GYP_ABS_ANDROID_TOP_DIR)/prebuilts/sdk/17/framework.aidl" -ppublic/android/java/src/org/chromium/content/common/common.aidl public/android/java/src/org/chromium/content/common/IChildProcessService.aidl "$(gyp_shared_intermediate_dir)/common_aidl/aidl/IChildProcessService.java"
+
+.PHONY: content_common_aidl_gyp_rule_trigger
+content_common_aidl_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/common_aidl/aidl/IChildProcessService.java
+
+### Finished generating for all rules
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/common_aidl/aidl/IChildProcessCallback.java \
+	$(gyp_shared_intermediate_dir)/common_aidl/aidl/IChildProcessService.java
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES := \
+	content_common_aidl_gyp_rule_trigger
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-fno-tree-sra \
+	-fuse-ld=gold \
+	-Wno-psabi \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections
+
+MY_CFLAGS_C :=
+
+MY_DEFS := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DUSE_LINUX_BREAKPAD' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_GPU=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DENABLE_LANGUAGE_DETECTION=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+LOCAL_CFLAGS := $(MY_CFLAGS_C) $(MY_CFLAGS) $(MY_DEFS)
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES := \
+	$(GYP_ABS_ANDROID_TOP_DIR)/frameworks/wilhelm/include \
+	$(GYP_ABS_ANDROID_TOP_DIR)/bionic \
+	$(GYP_ABS_ANDROID_TOP_DIR)/external/stlport/stlport
+
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES)
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-abi \
+	-Wno-error=c++0x-compat \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_common_aidl_gyp
+
+# Alias gyp target name.
+.PHONY: common_aidl
+common_aidl: content_common_aidl_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/content/common_aidl.target.darwin-x86.mk b/content/common_aidl.target.darwin-x86.mk
new file mode 100644
index 0000000..6ed321b
--- /dev/null
+++ b/content/common_aidl.target.darwin-x86.mk
@@ -0,0 +1,154 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := content_common_aidl_gyp
+LOCAL_MODULE_STEM := common_aidl
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+
+### Generated for rule "content_content_gyp_common_aidl_target_compile_aidl":
+# "{'inputs': ['$(GYP_ABS_ANDROID_TOP_DIR)/prebuilts/sdk/17/framework.aidl', 'public/android/java/src/org/chromium/content/common/common.aidl'], 'extension': 'aidl', 'rule_sources': ['public/android/java/src/org/chromium/content/common/IChildProcessCallback.aidl', 'public/android/java/src/org/chromium/content/common/IChildProcessService.aidl'], 'rule_name': 'compile_aidl', 'outputs': ['$(gyp_shared_intermediate_dir)/common_aidl/aidl/%(INPUT_ROOT)s.java'], 'action': ['$(GYP_ABS_ANDROID_TOP_DIR)/prebuilts/sdk/tools/darwin/aidl', '-p$(GYP_ABS_ANDROID_TOP_DIR)/prebuilts/sdk/17/framework.aidl', '-ppublic/android/java/src/org/chromium/content/common/common.aidl', '$(RULE_SOURCES)', '$(gyp_shared_intermediate_dir)/common_aidl/aidl/%(INPUT_ROOT)s.java']}":
+$(gyp_shared_intermediate_dir)/common_aidl/aidl/IChildProcessCallback.java: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/common_aidl/aidl/IChildProcessCallback.java: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
+$(gyp_shared_intermediate_dir)/common_aidl/aidl/IChildProcessCallback.java: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
+$(gyp_shared_intermediate_dir)/common_aidl/aidl/IChildProcessCallback.java: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/common_aidl/aidl/IChildProcessCallback.java: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/common/IChildProcessCallback.aidl $(GYP_ABS_ANDROID_TOP_DIR)/prebuilts/sdk/17/framework.aidl $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/common/common.aidl $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/common_aidl/aidl; cd $(gyp_local_path)/content; "$(GYP_ABS_ANDROID_TOP_DIR)/prebuilts/sdk/tools/darwin/aidl" "-p$(GYP_ABS_ANDROID_TOP_DIR)/prebuilts/sdk/17/framework.aidl" -ppublic/android/java/src/org/chromium/content/common/common.aidl public/android/java/src/org/chromium/content/common/IChildProcessCallback.aidl "$(gyp_shared_intermediate_dir)/common_aidl/aidl/IChildProcessCallback.java"
+
+.PHONY: content_common_aidl_gyp_rule_trigger
+content_common_aidl_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/common_aidl/aidl/IChildProcessCallback.java
+
+$(gyp_shared_intermediate_dir)/common_aidl/aidl/IChildProcessService.java: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/common_aidl/aidl/IChildProcessService.java: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
+$(gyp_shared_intermediate_dir)/common_aidl/aidl/IChildProcessService.java: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
+$(gyp_shared_intermediate_dir)/common_aidl/aidl/IChildProcessService.java: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/common_aidl/aidl/IChildProcessService.java: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/common/IChildProcessService.aidl $(GYP_ABS_ANDROID_TOP_DIR)/prebuilts/sdk/17/framework.aidl $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/common/common.aidl $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/common_aidl/aidl; cd $(gyp_local_path)/content; "$(GYP_ABS_ANDROID_TOP_DIR)/prebuilts/sdk/tools/darwin/aidl" "-p$(GYP_ABS_ANDROID_TOP_DIR)/prebuilts/sdk/17/framework.aidl" -ppublic/android/java/src/org/chromium/content/common/common.aidl public/android/java/src/org/chromium/content/common/IChildProcessService.aidl "$(gyp_shared_intermediate_dir)/common_aidl/aidl/IChildProcessService.java"
+
+.PHONY: content_common_aidl_gyp_rule_trigger
+content_common_aidl_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/common_aidl/aidl/IChildProcessService.java
+
+### Finished generating for all rules
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/common_aidl/aidl/IChildProcessCallback.java \
+	$(gyp_shared_intermediate_dir)/common_aidl/aidl/IChildProcessService.java
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES := \
+	content_common_aidl_gyp_rule_trigger
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS := \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-m32 \
+	-mmmx \
+	-march=pentium4 \
+	-msse2 \
+	-mfpmath=sse \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-fno-stack-protector \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections
+
+MY_CFLAGS_C :=
+
+MY_DEFS := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DUSE_LINUX_BREAKPAD' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_GPU=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DENABLE_LANGUAGE_DETECTION=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+LOCAL_CFLAGS := $(MY_CFLAGS_C) $(MY_CFLAGS) $(MY_DEFS)
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES := \
+	$(GYP_ABS_ANDROID_TOP_DIR)/frameworks/wilhelm/include \
+	$(GYP_ABS_ANDROID_TOP_DIR)/bionic \
+	$(GYP_ABS_ANDROID_TOP_DIR)/external/stlport/stlport
+
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES)
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-error=c++0x-compat \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_common_aidl_gyp
+
+# Alias gyp target name.
+.PHONY: common_aidl
+common_aidl: content_common_aidl_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/content/common_aidl.target.linux-arm.mk b/content/common_aidl.target.linux-arm.mk
index 8eb0fd7..28907e6 100644
--- a/content/common_aidl.target.linux-arm.mk
+++ b/content/common_aidl.target.linux-arm.mk
@@ -90,7 +90,6 @@
 
 MY_DEFS := \
 	'-DCONTENT_IMPLEMENTATION' \
-	'-DUSE_SKIA' \
 	'-D_FILE_OFFSET_BITS=64' \
 	'-DUSE_LINUX_BREAKPAD' \
 	'-DNO_TCMALLOC' \
@@ -98,7 +97,6 @@
 	'-DCHROMIUM_BUILD' \
 	'-DUSE_LIBJPEG_TURBO=1' \
 	'-DUSE_PROPRIETARY_CODECS' \
-	'-DENABLE_PEPPER_THREADING' \
 	'-DENABLE_GPU=1' \
 	'-DUSE_OPENSSL=1' \
 	'-DENABLE_EGLIMAGE=1' \
diff --git a/content/common_aidl.target.linux-x86.mk b/content/common_aidl.target.linux-x86.mk
index 2e8a975..aed9897 100644
--- a/content/common_aidl.target.linux-x86.mk
+++ b/content/common_aidl.target.linux-x86.mk
@@ -70,6 +70,7 @@
 	-march=pentium4 \
 	-msse2 \
 	-mfpmath=sse \
+	-fuse-ld=gold \
 	-ffunction-sections \
 	-funwind-tables \
 	-g \
@@ -91,7 +92,6 @@
 
 MY_DEFS := \
 	'-DCONTENT_IMPLEMENTATION' \
-	'-DUSE_SKIA' \
 	'-D_FILE_OFFSET_BITS=64' \
 	'-DUSE_LINUX_BREAKPAD' \
 	'-DNO_TCMALLOC' \
@@ -99,7 +99,6 @@
 	'-DCHROMIUM_BUILD' \
 	'-DUSE_LIBJPEG_TURBO=1' \
 	'-DUSE_PROPRIETARY_CODECS' \
-	'-DENABLE_PEPPER_THREADING' \
 	'-DENABLE_GPU=1' \
 	'-DUSE_OPENSSL=1' \
 	'-DENABLE_EGLIMAGE=1' \
diff --git a/content/content.gyp b/content/content.gyp
index 1068b7e..f790279 100644
--- a/content/content.gyp
+++ b/content/content.gyp
@@ -301,6 +301,21 @@
           'includes': [ '../build/java_aidl.gypi' ],
         },
         {
+          'target_name': 'content_native_libraries_gen',
+          'type': 'none',
+          'sources': [
+            'public/android/java/templates/NativeLibraries.template',
+          ],
+          'variables': {
+            'package_name': 'org/chromium/content/app',
+            'include_path': 'public/android/java/templates',
+            'template_deps': [
+              'public/android/java/templates/native_libraries_array.h'
+            ],
+          },
+          'includes': [ '../build/android/java_cpp_template.gypi' ],
+        },
+        {
           'target_name': 'content_java',
           'type': 'none',
           'dependencies': [
@@ -312,9 +327,11 @@
             'content_common',
             'page_transition_types_java',
             'result_codes_java',
+            'content_native_libraries_gen',
           ],
           'variables': {
             'java_in_dir': '../content/public/android/java',
+            'jar_excluded_classes': [ '*/NativeLibraries.class' ],
             'has_java_resources': 1,
             'R_package': 'org.chromium.content',
             'R_package_relpath': 'org/chromium/content',
@@ -355,24 +372,6 @@
           'includes': [ '../build/android/java_cpp_template.gypi' ],
         },
         {
-          'target_name': 'surface_texture_jni_headers',
-          'type': 'none',
-          'variables': {
-            'jni_gen_package': 'content',
-            'input_java_class': 'android/graphics/SurfaceTexture.class',
-          },
-          'includes': [ '../build/jar_file_jni_generator.gypi' ],
-        },
-        {
-          'target_name': 'surface_jni_headers',
-          'type': 'none',
-          'variables': {
-            'jni_gen_package': 'content',
-            'input_java_class': 'android/view/Surface.class',
-          },
-          'includes': [ '../build/jar_file_jni_generator.gypi' ],
-        },
-        {
           'target_name': 'java_set_jni_headers',
           'type': 'none',
           'variables': {
@@ -387,8 +386,6 @@
           'type': 'none',
           'dependencies': [
             'java_set_jni_headers',
-            'surface_texture_jni_headers',
-            'surface_jni_headers',
           ],
           'direct_dependent_settings': {
             'include_dirs': [
diff --git a/content/content.target.darwin-arm.mk b/content/content.target.darwin-arm.mk
new file mode 100644
index 0000000..7426d36
--- /dev/null
+++ b/content/content.target.darwin-arm.mk
@@ -0,0 +1,47 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := content_content_gyp
+LOCAL_MODULE_STEM := content
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,content_content_app_gyp)/content_content_app_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,content_content_browser_gyp)/content_content_browser_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,content_content_common_gyp)/content_content_common_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,content_content_gpu_gyp)/content_content_gpu_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,content_content_plugin_gyp)/content_content_plugin_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,content_content_ppapi_plugin_gyp)/content_content_ppapi_plugin_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,content_content_renderer_gyp)/content_content_renderer_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,content_content_utility_gyp)/content_content_utility_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,content_content_worker_gyp)/content_content_worker_gyp.a
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_content_gyp
+
+# Alias gyp target name.
+.PHONY: content
+content: content_content_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/content/content.target.darwin-x86.mk b/content/content.target.darwin-x86.mk
new file mode 100644
index 0000000..7426d36
--- /dev/null
+++ b/content/content.target.darwin-x86.mk
@@ -0,0 +1,47 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := content_content_gyp
+LOCAL_MODULE_STEM := content
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,content_content_app_gyp)/content_content_app_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,content_content_browser_gyp)/content_content_browser_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,content_content_common_gyp)/content_content_common_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,content_content_gpu_gyp)/content_content_gpu_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,content_content_plugin_gyp)/content_content_plugin_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,content_content_ppapi_plugin_gyp)/content_content_ppapi_plugin_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,content_content_renderer_gyp)/content_content_renderer_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,content_content_utility_gyp)/content_content_utility_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,content_content_worker_gyp)/content_content_worker_gyp.a
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_content_gyp
+
+# Alias gyp target name.
+.PHONY: content
+content: content_content_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/content/content_app.target.darwin-arm.mk b/content/content_app.target.darwin-arm.mk
new file mode 100644
index 0000000..a20d349
--- /dev/null
+++ b/content/content_app.target.darwin-arm.mk
@@ -0,0 +1,187 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := content_content_app_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_ui_gyp)/ui_ui_gyp.a \
+	$(call intermediates-dir-for,GYP,content_content_jni_headers_gyp)/content_jni_headers.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_gyp)/skia_skia_gyp.a
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	content/app/android/app_jni_registrar.cc \
+	content/app/android/child_process_service.cc \
+	content/app/android/content_main.cc \
+	content/app/android/library_loader_hooks.cc \
+	content/app/content_main_runner.cc \
+	content/public/app/content_main_delegate.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-fno-tree-sra \
+	-fuse-ld=gold \
+	-Wno-psabi \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections
+
+MY_CFLAGS_C :=
+
+MY_DEFS := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DUSE_LINUX_BREAKPAD' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_GPU=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DENABLE_LANGUAGE_DETECTION=1' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DSK_BUILD_NO_IMAGE_ENCODE' \
+	'-DSK_DEFERRED_CANVAS_USES_GPIPE=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DGR_AGGRESSIVE_SHADER_OPTS=1' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_BUILD_FOR_ANDROID_NDK' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+LOCAL_CFLAGS := $(MY_CFLAGS_C) $(MY_CFLAGS) $(MY_DEFS)
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES := \
+	$(LOCAL_PATH) \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(GYP_ABS_ANDROID_TOP_DIR)/external/icu4c/common \
+	$(GYP_ABS_ANDROID_TOP_DIR)/external/icu4c/i18n \
+	$(gyp_shared_intermediate_dir)/content \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/config \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/gpu/gl \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(GYP_ABS_ANDROID_TOP_DIR)/frameworks/wilhelm/include \
+	$(GYP_ABS_ANDROID_TOP_DIR)/bionic \
+	$(GYP_ABS_ANDROID_TOP_DIR)/external/stlport/stlport
+
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES)
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-abi \
+	-Wno-error=c++0x-compat \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+### Rules for final target.
+
+LOCAL_LDFLAGS := \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-Wl,-z,relro \
+	-Wl,-z,now \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--icf=safe \
+	-Wl,--gc-sections \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_STATIC_LIBRARIES := \
+	cpufeatures \
+	ui_ui_gyp \
+	skia_skia_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_content_app_gyp
+
+# Alias gyp target name.
+.PHONY: content_app
+content_app: content_content_app_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/content/content_app.target.darwin-x86.mk b/content/content_app.target.darwin-x86.mk
new file mode 100644
index 0000000..911a3e8
--- /dev/null
+++ b/content/content_app.target.darwin-x86.mk
@@ -0,0 +1,185 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := content_content_app_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_ui_gyp)/ui_ui_gyp.a \
+	$(call intermediates-dir-for,GYP,content_content_jni_headers_gyp)/content_jni_headers.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_gyp)/skia_skia_gyp.a
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	content/app/android/app_jni_registrar.cc \
+	content/app/android/child_process_service.cc \
+	content/app/android/content_main.cc \
+	content/app/android/library_loader_hooks.cc \
+	content/app/content_main_runner.cc \
+	content/public/app/content_main_delegate.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS := \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-m32 \
+	-mmmx \
+	-march=pentium4 \
+	-msse2 \
+	-mfpmath=sse \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-fno-stack-protector \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections
+
+MY_CFLAGS_C :=
+
+MY_DEFS := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DUSE_LINUX_BREAKPAD' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_GPU=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DENABLE_LANGUAGE_DETECTION=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DSK_BUILD_NO_IMAGE_ENCODE' \
+	'-DSK_DEFERRED_CANVAS_USES_GPIPE=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DGR_AGGRESSIVE_SHADER_OPTS=1' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_BUILD_FOR_ANDROID_NDK' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+LOCAL_CFLAGS := $(MY_CFLAGS_C) $(MY_CFLAGS) $(MY_DEFS)
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES := \
+	$(LOCAL_PATH) \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(GYP_ABS_ANDROID_TOP_DIR)/external/icu4c/common \
+	$(GYP_ABS_ANDROID_TOP_DIR)/external/icu4c/i18n \
+	$(gyp_shared_intermediate_dir)/content \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/config \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/gpu/gl \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(GYP_ABS_ANDROID_TOP_DIR)/frameworks/wilhelm/include \
+	$(GYP_ABS_ANDROID_TOP_DIR)/bionic \
+	$(GYP_ABS_ANDROID_TOP_DIR)/external/stlport/stlport
+
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES)
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-error=c++0x-compat \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+### Rules for final target.
+
+LOCAL_LDFLAGS := \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m32 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_STATIC_LIBRARIES := \
+	cpufeatures \
+	ui_ui_gyp \
+	skia_skia_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_content_app_gyp
+
+# Alias gyp target name.
+.PHONY: content_app
+content_app: content_content_app_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/content/content_app.target.linux-arm.mk b/content/content_app.target.linux-arm.mk
index dfbd8db..a20d349 100644
--- a/content/content_app.target.linux-arm.mk
+++ b/content/content_app.target.linux-arm.mk
@@ -11,6 +11,7 @@
 
 # Make sure our deps are built first.
 GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_ui_gyp)/ui_ui_gyp.a \
 	$(call intermediates-dir-for,GYP,content_content_jni_headers_gyp)/content_jni_headers.stamp \
 	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_gyp)/skia_skia_gyp.a
 
@@ -70,7 +71,6 @@
 
 MY_DEFS := \
 	'-DCONTENT_IMPLEMENTATION' \
-	'-DUSE_SKIA' \
 	'-D_FILE_OFFSET_BITS=64' \
 	'-DUSE_LINUX_BREAKPAD' \
 	'-DNO_TCMALLOC' \
@@ -78,7 +78,6 @@
 	'-DCHROMIUM_BUILD' \
 	'-DUSE_LIBJPEG_TURBO=1' \
 	'-DUSE_PROPRIETARY_CODECS' \
-	'-DENABLE_PEPPER_THREADING' \
 	'-DENABLE_GPU=1' \
 	'-DUSE_OPENSSL=1' \
 	'-DENABLE_EGLIMAGE=1' \
@@ -107,9 +106,10 @@
 
 # Include paths placed before CFLAGS/CPPFLAGS
 LOCAL_C_INCLUDES := \
+	$(LOCAL_PATH) \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
 	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
 	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
-	$(LOCAL_PATH) \
 	$(LOCAL_PATH)/third_party/khronos \
 	$(LOCAL_PATH)/gpu \
 	$(GYP_ABS_ANDROID_TOP_DIR)/external/icu4c/common \
@@ -123,6 +123,7 @@
 	$(LOCAL_PATH)/third_party/skia/include/pdf \
 	$(LOCAL_PATH)/third_party/skia/include/gpu \
 	$(LOCAL_PATH)/third_party/skia/include/gpu/gl \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
 	$(LOCAL_PATH)/third_party/skia/include/pipe \
 	$(LOCAL_PATH)/third_party/skia/include/ports \
 	$(LOCAL_PATH)/third_party/skia/include/utils \
@@ -158,13 +159,14 @@
 	-Wl,--no-undefined \
 	-Wl,--exclude-libs=ALL \
 	-Wl,--icf=safe \
+	-Wl,--gc-sections \
 	-Wl,-O1 \
-	-Wl,--as-needed \
-	-Wl,--gc-sections
+	-Wl,--as-needed
 
 
 LOCAL_STATIC_LIBRARIES := \
 	cpufeatures \
+	ui_ui_gyp \
 	skia_skia_gyp
 
 # Enable grouping to fix circular references
diff --git a/content/content_app.target.linux-x86.mk b/content/content_app.target.linux-x86.mk
index 251d86c..911a3e8 100644
--- a/content/content_app.target.linux-x86.mk
+++ b/content/content_app.target.linux-x86.mk
@@ -11,6 +11,7 @@
 
 # Make sure our deps are built first.
 GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_ui_gyp)/ui_ui_gyp.a \
 	$(call intermediates-dir-for,GYP,content_content_jni_headers_gyp)/content_jni_headers.stamp \
 	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_gyp)/skia_skia_gyp.a
 
@@ -50,6 +51,7 @@
 	-march=pentium4 \
 	-msse2 \
 	-mfpmath=sse \
+	-fuse-ld=gold \
 	-ffunction-sections \
 	-funwind-tables \
 	-g \
@@ -71,7 +73,6 @@
 
 MY_DEFS := \
 	'-DCONTENT_IMPLEMENTATION' \
-	'-DUSE_SKIA' \
 	'-D_FILE_OFFSET_BITS=64' \
 	'-DUSE_LINUX_BREAKPAD' \
 	'-DNO_TCMALLOC' \
@@ -79,7 +80,6 @@
 	'-DCHROMIUM_BUILD' \
 	'-DUSE_LIBJPEG_TURBO=1' \
 	'-DUSE_PROPRIETARY_CODECS' \
-	'-DENABLE_PEPPER_THREADING' \
 	'-DENABLE_GPU=1' \
 	'-DUSE_OPENSSL=1' \
 	'-DENABLE_EGLIMAGE=1' \
@@ -107,9 +107,10 @@
 
 # Include paths placed before CFLAGS/CPPFLAGS
 LOCAL_C_INCLUDES := \
+	$(LOCAL_PATH) \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
 	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
 	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
-	$(LOCAL_PATH) \
 	$(LOCAL_PATH)/third_party/khronos \
 	$(LOCAL_PATH)/gpu \
 	$(GYP_ABS_ANDROID_TOP_DIR)/external/icu4c/common \
@@ -123,6 +124,7 @@
 	$(LOCAL_PATH)/third_party/skia/include/pdf \
 	$(LOCAL_PATH)/third_party/skia/include/gpu \
 	$(LOCAL_PATH)/third_party/skia/include/gpu/gl \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
 	$(LOCAL_PATH)/third_party/skia/include/pipe \
 	$(LOCAL_PATH)/third_party/skia/include/ports \
 	$(LOCAL_PATH)/third_party/skia/include/utils \
@@ -151,16 +153,18 @@
 	-Wl,-z,noexecstack \
 	-fPIC \
 	-m32 \
+	-fuse-ld=gold \
 	-nostdlib \
 	-Wl,--no-undefined \
 	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
 	-Wl,-O1 \
-	-Wl,--as-needed \
-	-Wl,--gc-sections
+	-Wl,--as-needed
 
 
 LOCAL_STATIC_LIBRARIES := \
 	cpufeatures \
+	ui_ui_gyp \
 	skia_skia_gyp
 
 # Enable grouping to fix circular references
diff --git a/content/content_browser.gypi b/content/content_browser.gypi
index d70e151..8fcfbc3 100644
--- a/content/content_browser.gypi
+++ b/content/content_browser.gypi
@@ -10,7 +10,9 @@
     '../google_apis/google_apis.gyp:google_apis',
     '../net/net.gyp:net',
     '../skia/skia.gyp:skia',
+    '../sql/sql.gyp:sql',
     '../third_party/re2/re2.gyp:re2',
+    '../third_party/zlib/zlib.gyp:zip',
     '../third_party/zlib/zlib.gyp:zlib',
     '../ui/snapshot/snapshot.gyp:snapshot',
     '../ui/ui.gyp:ui',
@@ -58,8 +60,11 @@
     'public/browser/compositor_util.h',
     'public/browser/content_browser_client.cc',
     'public/browser/content_browser_client.h',
+    'public/browser/cookie_store_factory.h',
     'public/browser/devtools_agent_host.h',
     'public/browser/devtools_client_host.h',
+    'public/browser/devtools_external_agent_proxy.h',
+    'public/browser/devtools_external_agent_proxy_delegate.h',
     'public/browser/download_danger_type.h',
     'public/browser/download_id.h',
     'public/browser/devtools_frontend_host_delegate.h',
@@ -91,6 +96,8 @@
     'public/browser/histogram_fetcher.h',
     'public/browser/host_zoom_map.h',
     'public/browser/indexed_db_context.h',
+    'public/browser/indexed_db_info.cc',
+    'public/browser/indexed_db_info.h',
     'public/browser/interstitial_page.h',
     'public/browser/invalidate_type.h',
     'public/browser/javascript_dialog_manager.cc',
@@ -238,8 +245,8 @@
     'browser/android/interstitial_page_delegate_android.h',
     'browser/android/load_url_params.cc',
     'browser/android/load_url_params.h',
-    'browser/android/media_player_manager_android.cc',
-    'browser/android/media_player_manager_android.h',
+    'browser/android/media_player_manager_impl.cc',
+    'browser/android/media_player_manager_impl.h',
     'browser/android/media_resource_getter_impl.cc',
     'browser/android/media_resource_getter_impl.h',
     'browser/android/surface_texture_peer_browser_impl.cc',
@@ -304,6 +311,8 @@
     'browser/devtools/devtools_agent_host_impl.h',
     'browser/devtools/devtools_browser_target.cc',
     'browser/devtools/devtools_browser_target.h',
+    'browser/devtools/devtools_external_agent_proxy_impl.cc',
+    'browser/devtools/devtools_external_agent_proxy_impl.h',
     'browser/devtools/devtools_frontend_host.cc',
     'browser/devtools/devtools_frontend_host.h',
     'browser/devtools/devtools_http_handler_impl.cc',
@@ -318,10 +327,14 @@
     'browser/devtools/devtools_protocol_constants.h',
     'browser/devtools/devtools_tracing_handler.h',
     'browser/devtools/devtools_tracing_handler.cc',
+    'browser/devtools/ipc_devtools_agent_host.cc',
+    'browser/devtools/ipc_devtools_agent_host.h',
     'browser/devtools/render_view_devtools_agent_host.cc',
     'browser/devtools/render_view_devtools_agent_host.h',
     'browser/devtools/renderer_overrides_handler.cc',
     'browser/devtools/renderer_overrides_handler.h',
+    'browser/devtools/tethering_handler.h',
+    'browser/devtools/tethering_handler.cc',
     'browser/devtools/worker_devtools_manager.cc',
     'browser/devtools/worker_devtools_manager.h',
     'browser/devtools/worker_devtools_message_filter.cc',
@@ -335,6 +348,8 @@
     'browser/device_orientation/data_fetcher.h',
     'browser/device_orientation/data_fetcher_impl_android.cc',
     'browser/device_orientation/data_fetcher_impl_android.h',
+    'browser/device_orientation/data_fetcher_impl_win.cc',
+    'browser/device_orientation/data_fetcher_impl_win.h',
     'browser/device_orientation/device_data.h',
     'browser/device_orientation/message_filter.cc',
     'browser/device_orientation/message_filter.h',
@@ -522,16 +537,18 @@
     'browser/in_process_webkit/browser_webkitplatformsupport_impl.h',
     'browser/in_process_webkit/indexed_db_callbacks.cc',
     'browser/in_process_webkit/indexed_db_callbacks.h',
-    'browser/in_process_webkit/indexed_db_context_impl.cc',
-    'browser/in_process_webkit/indexed_db_context_impl.h',
     'browser/in_process_webkit/indexed_db_database_callbacks.cc',
     'browser/in_process_webkit/indexed_db_database_callbacks.h',
     'browser/in_process_webkit/indexed_db_dispatcher_host.cc',
     'browser/in_process_webkit/indexed_db_dispatcher_host.h',
-    'browser/in_process_webkit/indexed_db_quota_client.cc',
-    'browser/in_process_webkit/indexed_db_quota_client.h',
     'browser/in_process_webkit/webkit_thread.cc',
     'browser/in_process_webkit/webkit_thread.h',
+    'browser/indexed_db/indexed_db_context_impl.cc',
+    'browser/indexed_db/indexed_db_context_impl.h',
+    'browser/indexed_db/indexed_db_internals_ui.cc',
+    'browser/indexed_db/indexed_db_internals_ui.h',
+    'browser/indexed_db/indexed_db_quota_client.cc',
+    'browser/indexed_db/indexed_db_quota_client.h',
     'browser/loader/async_resource_handler.cc',
     'browser/loader/async_resource_handler.h',
     'browser/loader/buffered_resource_handler.cc',
@@ -542,8 +559,11 @@
     'browser/loader/cross_site_resource_handler.h',
     'browser/loader/doomed_resource_handler.cc',
     'browser/loader/doomed_resource_handler.h',
+    'browser/loader/global_routing_id.h',
     'browser/loader/layered_resource_handler.cc',
     'browser/loader/layered_resource_handler.h',
+    'browser/loader/offline_policy.cc',
+    'browser/loader/offline_policy.h',
     'browser/loader/power_save_block_resource_throttle.cc',
     'browser/loader/power_save_block_resource_throttle.h',
     'browser/loader/redirect_to_file_resource_handler.cc',
@@ -577,7 +597,7 @@
     'browser/loader/throttling_resource_handler.h',
     'browser/loader/transfer_navigation_resource_throttle.cc',
     'browser/loader/transfer_navigation_resource_throttle.h',
-    'browser/mach_broker_mac.cc',
+    'browser/mach_broker_mac.mm',
     'browser/mach_broker_mac.h',
     'browser/media_devices_monitor.cc',
     'browser/media/media_internals.cc',
@@ -599,6 +619,8 @@
     'browser/mime_registry_message_filter.h',
     'browser/net/browser_online_state_observer.cc',
     'browser/net/browser_online_state_observer.h',
+    'browser/net/sqlite_persistent_cookie_store.cc',
+    'browser/net/sqlite_persistent_cookie_store.h',
     'browser/net/view_blob_internals_job_factory.cc',
     'browser/net/view_blob_internals_job_factory.h',
     'browser/net/view_http_cache_job_factory.cc',
@@ -620,9 +642,9 @@
     'browser/power_save_blocker_chromeos.cc',
     'browser/power_save_blocker_impl.cc',
     'browser/power_save_blocker_impl.h',
-    'browser/power_save_blocker_linux.cc',
     'browser/power_save_blocker_mac.cc',
     'browser/power_save_blocker_win.cc',
+    'browser/power_save_blocker_x11.cc',
     'browser/ppapi_plugin_process_host.cc',
     'browser/ppapi_plugin_process_host.h',
     'browser/profiler_controller_impl.cc',
@@ -648,6 +670,8 @@
     'browser/renderer_host/clipboard_message_filter_mac.mm',
     'browser/renderer_host/compositor_impl_android.cc',
     'browser/renderer_host/compositor_impl_android.h',
+    'browser/renderer_host/compositing_iosurface_context_mac.mm',
+    'browser/renderer_host/compositing_iosurface_context_mac.h',
     'browser/renderer_host/compositing_iosurface_mac.h',
     'browser/renderer_host/compositing_iosurface_mac.mm',
     'browser/renderer_host/compositing_iosurface_shader_programs_mac.cc',
@@ -729,6 +753,8 @@
     'browser/renderer_host/media/web_contents_tracker.h',
     'browser/renderer_host/media/web_contents_video_capture_device.cc',
     'browser/renderer_host/media/web_contents_video_capture_device.h',
+    'browser/renderer_host/media/webrtc_logging_handler_host.cc',
+    'browser/renderer_host/media/webrtc_logging_handler_host.h',
     'browser/renderer_host/native_web_keyboard_event_android.cc',
     'browser/renderer_host/native_web_keyboard_event_aura.cc',
     'browser/renderer_host/native_web_keyboard_event.cc',
@@ -811,6 +837,8 @@
     'browser/renderer_host/render_widget_host_view_mac.mm',
     'browser/renderer_host/render_widget_host_view_win.cc',
     'browser/renderer_host/render_widget_host_view_win.h',
+    'browser/renderer_host/smooth_scroll_gesture_controller.cc',
+    'browser/renderer_host/smooth_scroll_gesture_controller.h',
     'browser/renderer_host/socket_stream_dispatcher_host.cc',
     'browser/renderer_host/socket_stream_dispatcher_host.h',
     'browser/renderer_host/socket_stream_host.cc',
@@ -925,6 +953,10 @@
     'browser/user_metrics.cc',
     'browser/utility_process_host_impl.cc',
     'browser/utility_process_host_impl.h',
+    'browser/web_contents/aura/image_window_delegate.cc',
+    'browser/web_contents/aura/image_window_delegate.h',
+    'browser/web_contents/aura/shadow_layer_delegate.cc',
+    'browser/web_contents/aura/shadow_layer_delegate.h',
     'browser/web_contents/debug_urls.cc',
     'browser/web_contents/debug_urls.h',
     'browser/web_contents/drag_utils_gtk.cc',
@@ -937,10 +969,14 @@
     'browser/web_contents/navigation_entry_impl.h',
     'browser/web_contents/render_view_host_manager.cc',
     'browser/web_contents/render_view_host_manager.h',
+    'browser/web_contents/touch_editable_impl_aura.cc',
+    'browser/web_contents/touch_editable_impl_aura.h',
     'browser/web_contents/web_contents_drag_win.cc',
     'browser/web_contents/web_contents_drag_win.h',
     'browser/web_contents/web_contents_impl.cc',
     'browser/web_contents/web_contents_impl.h',
+    'browser/web_contents/web_contents_screenshot_manager.cc',
+    'browser/web_contents/web_contents_screenshot_manager.h',
     'browser/web_contents/web_contents_view_android.cc',
     'browser/web_contents/web_contents_view_android.h',
     'browser/web_contents/web_contents_view_aura.cc',
@@ -1100,14 +1136,17 @@
         'libraries': [
           '-lcomctl32.lib',
           '-ldinput8.lib',
+          '-ldwmapi.lib',
           '-llocationapi.lib',
           '-lsensorsapi.lib',
+          '-lportabledeviceguids.lib',
         ],
         'msvs_settings': {
           'VCLinkerTool': {
             'DelayLoadDLLs': [
               'dinput8.dll',
               'user32.dll',
+              'dwmapi.dll',
             ],
           },
         },
@@ -1148,6 +1187,10 @@
     ['use_x11==1', {
       'dependencies': [
         '../build/linux/system.gyp:x11',
+      ],
+    }],
+    ['OS=="linux"', {
+      'dependencies': [
         '../build/linux/system.gyp:pangocairo',
       ],
     }],
@@ -1169,11 +1212,6 @@
         'browser/tracing/tracing_ui.cc',
         'browser/tracing/tracing_ui.h',
       ],
-    }, { # OS!="android"
-      'dependencies': [
-        '../third_party/flac/flac.gyp:libflac',
-        '../third_party/speex/speex.gyp:libspeex',
-      ],
     }],
     ['OS=="mac"', {
       'sources': [
@@ -1190,6 +1228,11 @@
       'dependencies': [
         '../third_party/sudden_motion_sensor/sudden_motion_sensor.gyp:sudden_motion_sensor',
       ],
+      'link_settings': {
+        'libraries': [
+          '$(SDKROOT)/usr/lib/libbsm.dylib',
+        ],
+      },
     }],
     ['chromeos==1', {
       'dependencies': [
@@ -1197,7 +1240,7 @@
       ],
       'sources!': [
         'browser/geolocation/wifi_data_provider_linux.cc',
-        'browser/power_save_blocker_linux.cc',
+        'browser/power_save_blocker_x11.cc',
         'browser/renderer_host/gtk_key_bindings_handler.cc',
         'browser/renderer_host/gtk_key_bindings_handler.h',
       ],
@@ -1223,6 +1266,7 @@
     ['use_aura==1', {
       'dependencies': [
         '../ui/aura/aura.gyp:aura',
+        '../ui/base/strings/ui_strings.gyp:ui_strings',
         '../ui/compositor/compositor.gyp:compositor',
       ],
       'sources/': [
@@ -1255,6 +1299,8 @@
         ['exclude', '^browser/renderer_host/software_output_device_x11.cc'],
         ['exclude', '^browser/renderer_host/software_output_device_x11.h'],
         ['exclude', '^browser/renderer_host/touchpad_tap_suppression_controller_aura.cc'],
+        ['exclude', '^browser/web_contents/touch_editable_impl_aura.cc'],
+        ['exclude', '^browser/web_contents/touch_editable_impl_aura.h'],
       ],
     }],
     ['enable_plugins==1', {
@@ -1293,6 +1339,11 @@
       'sources/': [
         ['exclude', '^browser/speech/'],
       ],
+    }, {  # input_speech==1
+      'dependencies': [
+        '../third_party/flac/flac.gyp:libflac',
+        '../third_party/speex/speex.gyp:libspeex',
+      ],
     }],
     ['linux_use_libgps==1', {
       'dependencies': [
diff --git a/content/content_browser.target.darwin-arm.mk b/content/content_browser.target.darwin-arm.mk
new file mode 100644
index 0000000..6d993c9
--- /dev/null
+++ b/content/content_browser.target.darwin-arm.mk
@@ -0,0 +1,536 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := content_content_browser_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,content_content_resources_gyp)/content_resources.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,content_browser_speech_proto_speech_proto_gyp)/content_browser_speech_proto_speech_proto_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_gyp)/skia_skia_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_ui_gyp)/ui_ui_gyp.a \
+	$(call intermediates-dir-for,GYP,ui_ui_resources_gyp)/ui_resources.stamp \
+	$(call intermediates-dir-for,GYP,content_browser_devtools_devtools_resources_gyp)/devtools_resources.stamp \
+	$(call intermediates-dir-for,GYP,webkit_support_webkit_resources_gyp)/webkit_resources.stamp \
+	$(call intermediates-dir-for,GYP,webkit_support_webkit_strings_gyp)/webkit_strings.stamp \
+	$(call intermediates-dir-for,GYP,sandbox_sandbox_gyp)/sandbox.stamp \
+	$(call intermediates-dir-for,GYP,content_content_jni_headers_gyp)/content_jni_headers.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+$(gyp_intermediate_dir)/devtools_resources_map.cc: $(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources_map.cc
+	mkdir -p $(@D); cp $< $@
+$(gyp_intermediate_dir)/webui_resources_map.cc: $(gyp_shared_intermediate_dir)/ui/ui_resources/grit/webui_resources_map.cc
+	mkdir -p $(@D); cp $< $@
+LOCAL_GENERATED_SOURCES := \
+	$(gyp_intermediate_dir)/devtools_resources_map.cc \
+	$(gyp_intermediate_dir)/webui_resources_map.cc
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS := \
+	$(gyp_shared_intermediate_dir)/webkit/grit \
+	$(gyp_shared_intermediate_dir)/ui/ui_resources/grit
+
+LOCAL_SRC_FILES := \
+	content/public/browser/browser_child_process_host_delegate.cc \
+	content/public/browser/browser_child_process_host_iterator.cc \
+	content/public/browser/browser_child_process_observer.cc \
+	content/public/browser/browser_main_parts.cc \
+	content/public/browser/browser_message_filter.cc \
+	content/public/browser/content_browser_client.cc \
+	content/public/browser/download_manager_delegate.cc \
+	content/public/browser/download_save_info.cc \
+	content/public/browser/download_url_parameters.cc \
+	content/public/browser/favicon_status.cc \
+	content/public/browser/indexed_db_info.cc \
+	content/public/browser/javascript_dialog_manager.cc \
+	content/public/browser/load_from_memory_cache_details.cc \
+	content/public/browser/navigation_controller.cc \
+	content/public/browser/navigation_details.cc \
+	content/public/browser/notification_registrar.cc \
+	content/public/browser/page_navigator.cc \
+	content/public/browser/render_view_host_observer.cc \
+	content/public/browser/resource_dispatcher_host_delegate.cc \
+	content/public/browser/resource_request_details.cc \
+	content/public/browser/speech_recognition_session_config.cc \
+	content/public/browser/speech_recognition_session_context.cc \
+	content/public/browser/web_contents.cc \
+	content/public/browser/web_contents_delegate.cc \
+	content/public/browser/web_contents_observer.cc \
+	content/public/browser/web_ui_controller.cc \
+	content/public/browser/url_data_source.cc \
+	content/browser/accessibility/accessibility_tree_formatter.cc \
+	content/browser/accessibility/accessibility_ui.cc \
+	content/browser/accessibility/browser_accessibility.cc \
+	content/browser/accessibility/browser_accessibility_manager.cc \
+	content/browser/accessibility/browser_accessibility_state_impl.cc \
+	content/browser/android/android_browser_process.cc \
+	content/browser/android/browser_jni_registrar.cc \
+	content/browser/android/child_process_launcher_android.cc \
+	content/browser/android/content_settings.cc \
+	content/browser/android/content_startup_flags.cc \
+	content/browser/android/content_video_view.cc \
+	content/browser/android/content_view_core_impl.cc \
+	content/browser/android/content_view_render_view.cc \
+	content/browser/android/content_view_statics.cc \
+	content/browser/android/date_time_chooser_android.cc \
+	content/browser/android/download_controller_android_impl.cc \
+	content/browser/android/devtools_auth.cc \
+	content/browser/android/interstitial_page_delegate_android.cc \
+	content/browser/android/load_url_params.cc \
+	content/browser/android/media_player_manager_impl.cc \
+	content/browser/android/media_resource_getter_impl.cc \
+	content/browser/android/surface_texture_peer_browser_impl.cc \
+	content/browser/android/sync_input_event_filter.cc \
+	content/browser/android/touch_point.cc \
+	content/browser/android/tracing_intent_handler.cc \
+	content/browser/android/web_contents_observer_android.cc \
+	content/browser/appcache/appcache_dispatcher_host.cc \
+	content/browser/appcache/appcache_frontend_proxy.cc \
+	content/browser/appcache/chrome_appcache_service.cc \
+	content/browser/browser_child_process_host_impl.cc \
+	content/browser/browser_context.cc \
+	content/browser/browser_ipc_logging.cc \
+	content/browser/browser_main.cc \
+	content/browser/browser_main_loop.cc \
+	content/browser/browser_main_runner.cc \
+	content/browser/browser_plugin/browser_plugin_embedder.cc \
+	content/browser/browser_plugin/browser_plugin_geolocation_permission_context.cc \
+	content/browser/browser_plugin/browser_plugin_guest.cc \
+	content/browser/browser_plugin/browser_plugin_guest_helper.cc \
+	content/browser/browser_plugin/browser_plugin_guest_manager.cc \
+	content/browser/browser_plugin/browser_plugin_message_filter.cc \
+	content/browser/browser_process_sub_thread.cc \
+	content/browser/browser_thread_impl.cc \
+	content/browser/browser_url_handler_impl.cc \
+	content/browser/browsing_instance.cc \
+	content/browser/byte_stream.cc \
+	content/browser/cert_store_impl.cc \
+	content/browser/child_process_launcher.cc \
+	content/browser/child_process_security_policy_impl.cc \
+	content/browser/cross_site_request_manager.cc \
+	content/browser/devtools/devtools_agent_host_impl.cc \
+	content/browser/devtools/devtools_browser_target.cc \
+	content/browser/devtools/devtools_external_agent_proxy_impl.cc \
+	content/browser/devtools/devtools_frontend_host.cc \
+	content/browser/devtools/devtools_http_handler_impl.cc \
+	content/browser/devtools/devtools_manager_impl.cc \
+	content/browser/devtools/devtools_netlog_observer.cc \
+	content/browser/devtools/devtools_protocol.cc \
+	content/browser/devtools/devtools_protocol_constants.cc \
+	content/browser/devtools/devtools_tracing_handler.cc \
+	content/browser/devtools/ipc_devtools_agent_host.cc \
+	content/browser/devtools/render_view_devtools_agent_host.cc \
+	content/browser/devtools/renderer_overrides_handler.cc \
+	content/browser/devtools/tethering_handler.cc \
+	content/browser/devtools/worker_devtools_manager.cc \
+	content/browser/devtools/worker_devtools_message_filter.cc \
+	content/browser/device_orientation/data_fetcher_impl_android.cc \
+	content/browser/device_orientation/message_filter.cc \
+	content/browser/device_orientation/motion.cc \
+	content/browser/device_orientation/motion_message_filter.cc \
+	content/browser/device_orientation/observer_delegate.cc \
+	content/browser/device_orientation/orientation.cc \
+	content/browser/device_orientation/orientation_message_filter.cc \
+	content/browser/device_orientation/provider.cc \
+	content/browser/device_orientation/provider_impl.cc \
+	content/browser/dom_storage/dom_storage_context_impl.cc \
+	content/browser/dom_storage/dom_storage_message_filter.cc \
+	content/browser/dom_storage/session_storage_namespace_impl.cc \
+	content/browser/download/base_file.cc \
+	content/browser/download/base_file_posix.cc \
+	content/browser/download/download_create_info.cc \
+	content/browser/download/download_file_factory.cc \
+	content/browser/download/download_file_impl.cc \
+	content/browser/download/download_interrupt_reasons_impl.cc \
+	content/browser/download/download_item_impl.cc \
+	content/browser/download/download_item_impl_delegate.cc \
+	content/browser/download/download_manager_impl.cc \
+	content/browser/download/download_net_log_parameters.cc \
+	content/browser/download/download_request_handle.cc \
+	content/browser/download/download_resource_handler.cc \
+	content/browser/download/download_stats.cc \
+	content/browser/download/drag_download_file.cc \
+	content/browser/download/drag_download_util.cc \
+	content/browser/download/mhtml_generation_manager.cc \
+	content/browser/download/save_file.cc \
+	content/browser/download/save_file_manager.cc \
+	content/browser/download/save_file_resource_handler.cc \
+	content/browser/download/save_item.cc \
+	content/browser/download/save_package.cc \
+	content/browser/download/save_types.cc \
+	content/browser/fileapi/browser_file_system_helper.cc \
+	content/browser/fileapi/chrome_blob_storage_context.cc \
+	content/browser/fileapi/fileapi_message_filter.cc \
+	content/browser/font_list_async.cc \
+	content/browser/gamepad/gamepad_provider.cc \
+	content/browser/gamepad/gamepad_service.cc \
+	content/browser/geolocation/device_data_provider.cc \
+	content/browser/geolocation/empty_device_data_provider.cc \
+	content/browser/geolocation/geolocation.cc \
+	content/browser/geolocation/geolocation_dispatcher_host.cc \
+	content/browser/geolocation/geolocation_provider.cc \
+	content/browser/geolocation/location_api_adapter_android.cc \
+	content/browser/geolocation/location_arbitrator_impl.cc \
+	content/browser/geolocation/location_provider_android.cc \
+	content/browser/geolocation/location_provider.cc \
+	content/browser/geolocation/wifi_data_provider_common.cc \
+	content/browser/gpu/browser_gpu_channel_host_factory.cc \
+	content/browser/gpu/compositor_util.cc \
+	content/browser/gpu/gpu_blacklist.cc \
+	content/browser/gpu/gpu_control_list.cc \
+	content/browser/gpu/gpu_data_manager_impl.cc \
+	content/browser/gpu/gpu_driver_bug_list.cc \
+	content/browser/gpu/gpu_internals_ui.cc \
+	content/browser/gpu/gpu_process_host.cc \
+	content/browser/gpu/gpu_process_host_ui_shim.cc \
+	content/browser/gpu/gpu_surface_tracker.cc \
+	content/browser/gpu/gpu_switching_list.cc \
+	content/browser/gpu/gpu_util.cc \
+	content/browser/gpu/shader_disk_cache.cc \
+	content/browser/histogram_controller.cc \
+	content/browser/histogram_internals_request_job.cc \
+	content/browser/histogram_message_filter.cc \
+	content/browser/histogram_synchronizer.cc \
+	content/browser/host_zoom_map_impl.cc \
+	content/browser/hyphenator/hyphenator_message_filter.cc \
+	content/browser/in_process_webkit/browser_webkitplatformsupport_impl.cc \
+	content/browser/in_process_webkit/indexed_db_callbacks.cc \
+	content/browser/in_process_webkit/indexed_db_database_callbacks.cc \
+	content/browser/in_process_webkit/indexed_db_dispatcher_host.cc \
+	content/browser/in_process_webkit/webkit_thread.cc \
+	content/browser/indexed_db/indexed_db_context_impl.cc \
+	content/browser/indexed_db/indexed_db_internals_ui.cc \
+	content/browser/indexed_db/indexed_db_quota_client.cc \
+	content/browser/loader/async_resource_handler.cc \
+	content/browser/loader/buffered_resource_handler.cc \
+	content/browser/loader/certificate_resource_handler.cc \
+	content/browser/loader/cross_site_resource_handler.cc \
+	content/browser/loader/doomed_resource_handler.cc \
+	content/browser/loader/layered_resource_handler.cc \
+	content/browser/loader/offline_policy.cc \
+	content/browser/loader/power_save_block_resource_throttle.cc \
+	content/browser/loader/redirect_to_file_resource_handler.cc \
+	content/browser/loader/render_view_host_tracker.cc \
+	content/browser/loader/resource_buffer.cc \
+	content/browser/loader/resource_dispatcher_host_impl.cc \
+	content/browser/loader/resource_handler.cc \
+	content/browser/loader/resource_loader.cc \
+	content/browser/loader/resource_message_delegate.cc \
+	content/browser/loader/resource_message_filter.cc \
+	content/browser/loader/resource_request_info_impl.cc \
+	content/browser/loader/resource_scheduler.cc \
+	content/browser/loader/resource_scheduler_filter.cc \
+	content/browser/loader/stream_resource_handler.cc \
+	content/browser/loader/sync_resource_handler.cc \
+	content/browser/loader/throttling_resource_handler.cc \
+	content/browser/loader/transfer_navigation_resource_throttle.cc \
+	content/browser/media_devices_monitor.cc \
+	content/browser/media/media_internals.cc \
+	content/browser/media/media_internals_handler.cc \
+	content/browser/media/media_internals_proxy.cc \
+	content/browser/media/media_internals_ui.cc \
+	content/browser/media/webrtc_internals.cc \
+	content/browser/media/webrtc_internals_message_handler.cc \
+	content/browser/media/webrtc_internals_ui.cc \
+	content/browser/mime_registry_message_filter.cc \
+	content/browser/net/browser_online_state_observer.cc \
+	content/browser/net/sqlite_persistent_cookie_store.cc \
+	content/browser/net/view_blob_internals_job_factory.cc \
+	content/browser/net/view_http_cache_job_factory.cc \
+	content/browser/notification_service_impl.cc \
+	content/browser/power_save_blocker_android.cc \
+	content/browser/power_save_blocker_impl.cc \
+	content/browser/profiler_controller_impl.cc \
+	content/browser/profiler_message_filter.cc \
+	content/browser/renderer_host/backing_store.cc \
+	content/browser/renderer_host/backing_store_manager.cc \
+	content/browser/renderer_host/basic_mouse_wheel_smooth_scroll_gesture.cc \
+	content/browser/renderer_host/clipboard_message_filter.cc \
+	content/browser/renderer_host/compositor_impl_android.cc \
+	content/browser/renderer_host/database_message_filter.cc \
+	content/browser/renderer_host/dip_util.cc \
+	content/browser/renderer_host/file_utilities_message_filter.cc \
+	content/browser/renderer_host/gamepad_browser_message_filter.cc \
+	content/browser/renderer_host/gesture_event_filter.cc \
+	content/browser/renderer_host/gpu_message_filter.cc \
+	content/browser/renderer_host/image_transport_factory_android.cc \
+	content/browser/renderer_host/ime_adapter_android.cc \
+	content/browser/renderer_host/java/java_bound_object.cc \
+	content/browser/renderer_host/java/java_bridge_channel_host.cc \
+	content/browser/renderer_host/java/java_bridge_dispatcher_host.cc \
+	content/browser/renderer_host/java/java_bridge_dispatcher_host_manager.cc \
+	content/browser/renderer_host/java/java_method.cc \
+	content/browser/renderer_host/java/java_type.cc \
+	content/browser/renderer_host/media/audio_input_device_manager.cc \
+	content/browser/renderer_host/media/audio_input_renderer_host.cc \
+	content/browser/renderer_host/media/audio_input_sync_writer.cc \
+	content/browser/renderer_host/media/audio_mirroring_manager.cc \
+	content/browser/renderer_host/media/audio_renderer_host.cc \
+	content/browser/renderer_host/media/audio_sync_reader.cc \
+	content/browser/renderer_host/media/media_stream_dispatcher_host.cc \
+	content/browser/renderer_host/media/media_stream_manager.cc \
+	content/browser/renderer_host/media/media_stream_ui_controller.cc \
+	content/browser/renderer_host/media/video_capture_buffer_pool.cc \
+	content/browser/renderer_host/media/video_capture_controller.cc \
+	content/browser/renderer_host/media/video_capture_controller_event_handler.cc \
+	content/browser/renderer_host/media/video_capture_host.cc \
+	content/browser/renderer_host/media/video_capture_manager.cc \
+	content/browser/renderer_host/media/web_contents_audio_input_stream.cc \
+	content/browser/renderer_host/media/web_contents_capture_util.cc \
+	content/browser/renderer_host/media/web_contents_tracker.cc \
+	content/browser/renderer_host/media/web_contents_video_capture_device.cc \
+	content/browser/renderer_host/media/webrtc_logging_handler_host.cc \
+	content/browser/renderer_host/native_web_keyboard_event_android.cc \
+	content/browser/renderer_host/native_web_keyboard_event.cc \
+	content/browser/renderer_host/overscroll_configuration.cc \
+	content/browser/renderer_host/overscroll_controller.cc \
+	content/browser/renderer_host/quota_dispatcher_host.cc \
+	content/browser/renderer_host/render_message_filter.cc \
+	content/browser/renderer_host/render_process_host_impl.cc \
+	content/browser/renderer_host/render_view_host_delegate.cc \
+	content/browser/renderer_host/render_view_host_factory.cc \
+	content/browser/renderer_host/render_view_host_impl.cc \
+	content/browser/renderer_host/render_widget_helper.cc \
+	content/browser/renderer_host/render_widget_host_delegate.cc \
+	content/browser/renderer_host/render_widget_host_impl.cc \
+	content/browser/renderer_host/render_widget_host_view_android.cc \
+	content/browser/renderer_host/render_widget_host_view_base.cc \
+	content/browser/renderer_host/render_widget_host_view_guest.cc \
+	content/browser/renderer_host/smooth_scroll_gesture_controller.cc \
+	content/browser/renderer_host/socket_stream_dispatcher_host.cc \
+	content/browser/renderer_host/socket_stream_host.cc \
+	content/browser/renderer_host/surface_texture_transport_client_android.cc \
+	content/browser/renderer_host/touch_event_queue.cc \
+	content/browser/renderer_host/touchpad_tap_suppression_controller.cc \
+	content/browser/renderer_host/touchscreen_tap_suppression_controller_stub.cc \
+	content/browser/resolve_proxy_msg_helper.cc \
+	content/browser/resource_context_impl.cc \
+	content/browser/site_instance_impl.cc \
+	content/browser/ssl/ssl_cert_error_handler.cc \
+	content/browser/ssl/ssl_client_auth_handler.cc \
+	content/browser/ssl/ssl_error_handler.cc \
+	content/browser/ssl/ssl_host_state.cc \
+	content/browser/ssl/ssl_manager.cc \
+	content/browser/ssl/ssl_policy_backend.cc \
+	content/browser/ssl/ssl_policy.cc \
+	content/browser/ssl/ssl_request_info.cc \
+	content/browser/streams/stream.cc \
+	content/browser/streams/stream_context.cc \
+	content/browser/streams/stream_handle_impl.cc \
+	content/browser/streams/stream_registry.cc \
+	content/browser/streams/stream_url_request_job.cc \
+	content/browser/storage_partition_impl.cc \
+	content/browser/storage_partition_impl_map.cc \
+	content/browser/tcmalloc_internals_request_job.cc \
+	content/browser/tracing/trace_controller_impl.cc \
+	content/browser/tracing/trace_message_filter.cc \
+	content/browser/tracing/trace_subscriber_stdio.cc \
+	content/browser/user_metrics.cc \
+	content/browser/utility_process_host_impl.cc \
+	content/browser/web_contents/debug_urls.cc \
+	content/browser/web_contents/interstitial_page_impl.cc \
+	content/browser/web_contents/navigation_controller_impl.cc \
+	content/browser/web_contents/navigation_entry_impl.cc \
+	content/browser/web_contents/render_view_host_manager.cc \
+	content/browser/web_contents/web_contents_impl.cc \
+	content/browser/web_contents/web_contents_screenshot_manager.cc \
+	content/browser/web_contents/web_contents_view_android.cc \
+	content/browser/web_contents/web_contents_view_guest.cc \
+	content/browser/webui/content_web_ui_controller_factory.cc \
+	content/browser/webui/generic_handler.cc \
+	content/browser/webui/shared_resources_data_source.cc \
+	content/browser/webui/url_data_manager.cc \
+	content/browser/webui/url_data_manager_backend.cc \
+	content/browser/webui/url_data_source_impl.cc \
+	content/browser/webui/web_ui_data_source_impl.cc \
+	content/browser/webui/web_ui_controller_factory_registry.cc \
+	content/browser/webui/web_ui_impl.cc \
+	content/browser/webui/web_ui_message_handler.cc \
+	content/browser/worker_host/message_port_service.cc \
+	content/browser/worker_host/worker_document_set.cc \
+	content/browser/worker_host/worker_message_filter.cc \
+	content/browser/worker_host/worker_process_host.cc \
+	content/browser/worker_host/worker_service_impl.cc \
+	content/browser/worker_host/worker_storage_partition.cc \
+	content/browser/gamepad/gamepad_platform_data_fetcher.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-fno-tree-sra \
+	-fuse-ld=gold \
+	-Wno-psabi \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections
+
+MY_CFLAGS_C :=
+
+MY_DEFS := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DUSE_LINUX_BREAKPAD' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_GPU=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DENABLE_LANGUAGE_DETECTION=1' \
+	'-DENABLE_JAVA_BRIDGE' \
+	'-DPROTOBUF_USE_DLLS' \
+	'-DGOOGLE_PROTOBUF_NO_RTTI' \
+	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DSK_BUILD_NO_IMAGE_ENCODE' \
+	'-DSK_DEFERRED_CANVAS_USES_GPIPE=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DGR_AGGRESSIVE_SHADER_OPTS=1' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_BUILD_FOR_ANDROID_NDK' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DMEDIA_DISABLE_LIBVPX' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+LOCAL_CFLAGS := $(MY_CFLAGS_C) $(MY_CFLAGS) $(MY_DEFS)
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES := \
+	$(LOCAL_PATH) \
+	$(gyp_intermediate_dir) \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(gyp_shared_intermediate_dir)/content \
+	$(gyp_shared_intermediate_dir)/protoc_out \
+	$(LOCAL_PATH)/third_party/protobuf \
+	$(LOCAL_PATH)/third_party/protobuf/src \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/config \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/gpu/gl \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(LOCAL_PATH)/third_party/re2 \
+	$(LOCAL_PATH)/third_party/zlib \
+	$(GYP_ABS_ANDROID_TOP_DIR)/external/icu4c/common \
+	$(GYP_ABS_ANDROID_TOP_DIR)/external/icu4c/i18n \
+	$(gyp_shared_intermediate_dir)/ui/ui_resources \
+	$(gyp_shared_intermediate_dir)/webkit \
+	$(LOCAL_PATH)/third_party/WebKit/Source/Platform/chromium \
+	$(LOCAL_PATH)/third_party/WebKit/Source/Platform/chromium \
+	$(LOCAL_PATH)/third_party/npapi \
+	$(LOCAL_PATH)/third_party/npapi/bindings \
+	$(LOCAL_PATH)/v8/include \
+	$(GYP_ABS_ANDROID_TOP_DIR)/frameworks/wilhelm/include \
+	$(GYP_ABS_ANDROID_TOP_DIR)/bionic \
+	$(GYP_ABS_ANDROID_TOP_DIR)/external/stlport/stlport
+
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES)
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-abi \
+	-Wno-error=c++0x-compat \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+### Rules for final target.
+
+LOCAL_LDFLAGS := \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-Wl,-z,relro \
+	-Wl,-z,now \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--icf=safe \
+	-Wl,--gc-sections \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_STATIC_LIBRARIES := \
+	content_browser_speech_proto_speech_proto_gyp \
+	skia_skia_gyp \
+	ui_ui_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_content_browser_gyp
+
+# Alias gyp target name.
+.PHONY: content_browser
+content_browser: content_content_browser_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/content/content_browser.target.darwin-x86.mk b/content/content_browser.target.darwin-x86.mk
new file mode 100644
index 0000000..44e619e
--- /dev/null
+++ b/content/content_browser.target.darwin-x86.mk
@@ -0,0 +1,534 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := content_content_browser_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,content_content_resources_gyp)/content_resources.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,content_browser_speech_proto_speech_proto_gyp)/content_browser_speech_proto_speech_proto_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_gyp)/skia_skia_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_ui_gyp)/ui_ui_gyp.a \
+	$(call intermediates-dir-for,GYP,ui_ui_resources_gyp)/ui_resources.stamp \
+	$(call intermediates-dir-for,GYP,content_browser_devtools_devtools_resources_gyp)/devtools_resources.stamp \
+	$(call intermediates-dir-for,GYP,webkit_support_webkit_resources_gyp)/webkit_resources.stamp \
+	$(call intermediates-dir-for,GYP,webkit_support_webkit_strings_gyp)/webkit_strings.stamp \
+	$(call intermediates-dir-for,GYP,sandbox_sandbox_gyp)/sandbox.stamp \
+	$(call intermediates-dir-for,GYP,content_content_jni_headers_gyp)/content_jni_headers.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+$(gyp_intermediate_dir)/devtools_resources_map.cc: $(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources_map.cc
+	mkdir -p $(@D); cp $< $@
+$(gyp_intermediate_dir)/webui_resources_map.cc: $(gyp_shared_intermediate_dir)/ui/ui_resources/grit/webui_resources_map.cc
+	mkdir -p $(@D); cp $< $@
+LOCAL_GENERATED_SOURCES := \
+	$(gyp_intermediate_dir)/devtools_resources_map.cc \
+	$(gyp_intermediate_dir)/webui_resources_map.cc
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS := \
+	$(gyp_shared_intermediate_dir)/webkit/grit \
+	$(gyp_shared_intermediate_dir)/ui/ui_resources/grit
+
+LOCAL_SRC_FILES := \
+	content/public/browser/browser_child_process_host_delegate.cc \
+	content/public/browser/browser_child_process_host_iterator.cc \
+	content/public/browser/browser_child_process_observer.cc \
+	content/public/browser/browser_main_parts.cc \
+	content/public/browser/browser_message_filter.cc \
+	content/public/browser/content_browser_client.cc \
+	content/public/browser/download_manager_delegate.cc \
+	content/public/browser/download_save_info.cc \
+	content/public/browser/download_url_parameters.cc \
+	content/public/browser/favicon_status.cc \
+	content/public/browser/indexed_db_info.cc \
+	content/public/browser/javascript_dialog_manager.cc \
+	content/public/browser/load_from_memory_cache_details.cc \
+	content/public/browser/navigation_controller.cc \
+	content/public/browser/navigation_details.cc \
+	content/public/browser/notification_registrar.cc \
+	content/public/browser/page_navigator.cc \
+	content/public/browser/render_view_host_observer.cc \
+	content/public/browser/resource_dispatcher_host_delegate.cc \
+	content/public/browser/resource_request_details.cc \
+	content/public/browser/speech_recognition_session_config.cc \
+	content/public/browser/speech_recognition_session_context.cc \
+	content/public/browser/web_contents.cc \
+	content/public/browser/web_contents_delegate.cc \
+	content/public/browser/web_contents_observer.cc \
+	content/public/browser/web_ui_controller.cc \
+	content/public/browser/url_data_source.cc \
+	content/browser/accessibility/accessibility_tree_formatter.cc \
+	content/browser/accessibility/accessibility_ui.cc \
+	content/browser/accessibility/browser_accessibility.cc \
+	content/browser/accessibility/browser_accessibility_manager.cc \
+	content/browser/accessibility/browser_accessibility_state_impl.cc \
+	content/browser/android/android_browser_process.cc \
+	content/browser/android/browser_jni_registrar.cc \
+	content/browser/android/child_process_launcher_android.cc \
+	content/browser/android/content_settings.cc \
+	content/browser/android/content_startup_flags.cc \
+	content/browser/android/content_video_view.cc \
+	content/browser/android/content_view_core_impl.cc \
+	content/browser/android/content_view_render_view.cc \
+	content/browser/android/content_view_statics.cc \
+	content/browser/android/date_time_chooser_android.cc \
+	content/browser/android/download_controller_android_impl.cc \
+	content/browser/android/devtools_auth.cc \
+	content/browser/android/interstitial_page_delegate_android.cc \
+	content/browser/android/load_url_params.cc \
+	content/browser/android/media_player_manager_impl.cc \
+	content/browser/android/media_resource_getter_impl.cc \
+	content/browser/android/surface_texture_peer_browser_impl.cc \
+	content/browser/android/sync_input_event_filter.cc \
+	content/browser/android/touch_point.cc \
+	content/browser/android/tracing_intent_handler.cc \
+	content/browser/android/web_contents_observer_android.cc \
+	content/browser/appcache/appcache_dispatcher_host.cc \
+	content/browser/appcache/appcache_frontend_proxy.cc \
+	content/browser/appcache/chrome_appcache_service.cc \
+	content/browser/browser_child_process_host_impl.cc \
+	content/browser/browser_context.cc \
+	content/browser/browser_ipc_logging.cc \
+	content/browser/browser_main.cc \
+	content/browser/browser_main_loop.cc \
+	content/browser/browser_main_runner.cc \
+	content/browser/browser_plugin/browser_plugin_embedder.cc \
+	content/browser/browser_plugin/browser_plugin_geolocation_permission_context.cc \
+	content/browser/browser_plugin/browser_plugin_guest.cc \
+	content/browser/browser_plugin/browser_plugin_guest_helper.cc \
+	content/browser/browser_plugin/browser_plugin_guest_manager.cc \
+	content/browser/browser_plugin/browser_plugin_message_filter.cc \
+	content/browser/browser_process_sub_thread.cc \
+	content/browser/browser_thread_impl.cc \
+	content/browser/browser_url_handler_impl.cc \
+	content/browser/browsing_instance.cc \
+	content/browser/byte_stream.cc \
+	content/browser/cert_store_impl.cc \
+	content/browser/child_process_launcher.cc \
+	content/browser/child_process_security_policy_impl.cc \
+	content/browser/cross_site_request_manager.cc \
+	content/browser/devtools/devtools_agent_host_impl.cc \
+	content/browser/devtools/devtools_browser_target.cc \
+	content/browser/devtools/devtools_external_agent_proxy_impl.cc \
+	content/browser/devtools/devtools_frontend_host.cc \
+	content/browser/devtools/devtools_http_handler_impl.cc \
+	content/browser/devtools/devtools_manager_impl.cc \
+	content/browser/devtools/devtools_netlog_observer.cc \
+	content/browser/devtools/devtools_protocol.cc \
+	content/browser/devtools/devtools_protocol_constants.cc \
+	content/browser/devtools/devtools_tracing_handler.cc \
+	content/browser/devtools/ipc_devtools_agent_host.cc \
+	content/browser/devtools/render_view_devtools_agent_host.cc \
+	content/browser/devtools/renderer_overrides_handler.cc \
+	content/browser/devtools/tethering_handler.cc \
+	content/browser/devtools/worker_devtools_manager.cc \
+	content/browser/devtools/worker_devtools_message_filter.cc \
+	content/browser/device_orientation/data_fetcher_impl_android.cc \
+	content/browser/device_orientation/message_filter.cc \
+	content/browser/device_orientation/motion.cc \
+	content/browser/device_orientation/motion_message_filter.cc \
+	content/browser/device_orientation/observer_delegate.cc \
+	content/browser/device_orientation/orientation.cc \
+	content/browser/device_orientation/orientation_message_filter.cc \
+	content/browser/device_orientation/provider.cc \
+	content/browser/device_orientation/provider_impl.cc \
+	content/browser/dom_storage/dom_storage_context_impl.cc \
+	content/browser/dom_storage/dom_storage_message_filter.cc \
+	content/browser/dom_storage/session_storage_namespace_impl.cc \
+	content/browser/download/base_file.cc \
+	content/browser/download/base_file_posix.cc \
+	content/browser/download/download_create_info.cc \
+	content/browser/download/download_file_factory.cc \
+	content/browser/download/download_file_impl.cc \
+	content/browser/download/download_interrupt_reasons_impl.cc \
+	content/browser/download/download_item_impl.cc \
+	content/browser/download/download_item_impl_delegate.cc \
+	content/browser/download/download_manager_impl.cc \
+	content/browser/download/download_net_log_parameters.cc \
+	content/browser/download/download_request_handle.cc \
+	content/browser/download/download_resource_handler.cc \
+	content/browser/download/download_stats.cc \
+	content/browser/download/drag_download_file.cc \
+	content/browser/download/drag_download_util.cc \
+	content/browser/download/mhtml_generation_manager.cc \
+	content/browser/download/save_file.cc \
+	content/browser/download/save_file_manager.cc \
+	content/browser/download/save_file_resource_handler.cc \
+	content/browser/download/save_item.cc \
+	content/browser/download/save_package.cc \
+	content/browser/download/save_types.cc \
+	content/browser/fileapi/browser_file_system_helper.cc \
+	content/browser/fileapi/chrome_blob_storage_context.cc \
+	content/browser/fileapi/fileapi_message_filter.cc \
+	content/browser/font_list_async.cc \
+	content/browser/gamepad/gamepad_provider.cc \
+	content/browser/gamepad/gamepad_service.cc \
+	content/browser/geolocation/device_data_provider.cc \
+	content/browser/geolocation/empty_device_data_provider.cc \
+	content/browser/geolocation/geolocation.cc \
+	content/browser/geolocation/geolocation_dispatcher_host.cc \
+	content/browser/geolocation/geolocation_provider.cc \
+	content/browser/geolocation/location_api_adapter_android.cc \
+	content/browser/geolocation/location_arbitrator_impl.cc \
+	content/browser/geolocation/location_provider_android.cc \
+	content/browser/geolocation/location_provider.cc \
+	content/browser/geolocation/wifi_data_provider_common.cc \
+	content/browser/gpu/browser_gpu_channel_host_factory.cc \
+	content/browser/gpu/compositor_util.cc \
+	content/browser/gpu/gpu_blacklist.cc \
+	content/browser/gpu/gpu_control_list.cc \
+	content/browser/gpu/gpu_data_manager_impl.cc \
+	content/browser/gpu/gpu_driver_bug_list.cc \
+	content/browser/gpu/gpu_internals_ui.cc \
+	content/browser/gpu/gpu_process_host.cc \
+	content/browser/gpu/gpu_process_host_ui_shim.cc \
+	content/browser/gpu/gpu_surface_tracker.cc \
+	content/browser/gpu/gpu_switching_list.cc \
+	content/browser/gpu/gpu_util.cc \
+	content/browser/gpu/shader_disk_cache.cc \
+	content/browser/histogram_controller.cc \
+	content/browser/histogram_internals_request_job.cc \
+	content/browser/histogram_message_filter.cc \
+	content/browser/histogram_synchronizer.cc \
+	content/browser/host_zoom_map_impl.cc \
+	content/browser/hyphenator/hyphenator_message_filter.cc \
+	content/browser/in_process_webkit/browser_webkitplatformsupport_impl.cc \
+	content/browser/in_process_webkit/indexed_db_callbacks.cc \
+	content/browser/in_process_webkit/indexed_db_database_callbacks.cc \
+	content/browser/in_process_webkit/indexed_db_dispatcher_host.cc \
+	content/browser/in_process_webkit/webkit_thread.cc \
+	content/browser/indexed_db/indexed_db_context_impl.cc \
+	content/browser/indexed_db/indexed_db_internals_ui.cc \
+	content/browser/indexed_db/indexed_db_quota_client.cc \
+	content/browser/loader/async_resource_handler.cc \
+	content/browser/loader/buffered_resource_handler.cc \
+	content/browser/loader/certificate_resource_handler.cc \
+	content/browser/loader/cross_site_resource_handler.cc \
+	content/browser/loader/doomed_resource_handler.cc \
+	content/browser/loader/layered_resource_handler.cc \
+	content/browser/loader/offline_policy.cc \
+	content/browser/loader/power_save_block_resource_throttle.cc \
+	content/browser/loader/redirect_to_file_resource_handler.cc \
+	content/browser/loader/render_view_host_tracker.cc \
+	content/browser/loader/resource_buffer.cc \
+	content/browser/loader/resource_dispatcher_host_impl.cc \
+	content/browser/loader/resource_handler.cc \
+	content/browser/loader/resource_loader.cc \
+	content/browser/loader/resource_message_delegate.cc \
+	content/browser/loader/resource_message_filter.cc \
+	content/browser/loader/resource_request_info_impl.cc \
+	content/browser/loader/resource_scheduler.cc \
+	content/browser/loader/resource_scheduler_filter.cc \
+	content/browser/loader/stream_resource_handler.cc \
+	content/browser/loader/sync_resource_handler.cc \
+	content/browser/loader/throttling_resource_handler.cc \
+	content/browser/loader/transfer_navigation_resource_throttle.cc \
+	content/browser/media_devices_monitor.cc \
+	content/browser/media/media_internals.cc \
+	content/browser/media/media_internals_handler.cc \
+	content/browser/media/media_internals_proxy.cc \
+	content/browser/media/media_internals_ui.cc \
+	content/browser/media/webrtc_internals.cc \
+	content/browser/media/webrtc_internals_message_handler.cc \
+	content/browser/media/webrtc_internals_ui.cc \
+	content/browser/mime_registry_message_filter.cc \
+	content/browser/net/browser_online_state_observer.cc \
+	content/browser/net/sqlite_persistent_cookie_store.cc \
+	content/browser/net/view_blob_internals_job_factory.cc \
+	content/browser/net/view_http_cache_job_factory.cc \
+	content/browser/notification_service_impl.cc \
+	content/browser/power_save_blocker_android.cc \
+	content/browser/power_save_blocker_impl.cc \
+	content/browser/profiler_controller_impl.cc \
+	content/browser/profiler_message_filter.cc \
+	content/browser/renderer_host/backing_store.cc \
+	content/browser/renderer_host/backing_store_manager.cc \
+	content/browser/renderer_host/basic_mouse_wheel_smooth_scroll_gesture.cc \
+	content/browser/renderer_host/clipboard_message_filter.cc \
+	content/browser/renderer_host/compositor_impl_android.cc \
+	content/browser/renderer_host/database_message_filter.cc \
+	content/browser/renderer_host/dip_util.cc \
+	content/browser/renderer_host/file_utilities_message_filter.cc \
+	content/browser/renderer_host/gamepad_browser_message_filter.cc \
+	content/browser/renderer_host/gesture_event_filter.cc \
+	content/browser/renderer_host/gpu_message_filter.cc \
+	content/browser/renderer_host/image_transport_factory_android.cc \
+	content/browser/renderer_host/ime_adapter_android.cc \
+	content/browser/renderer_host/java/java_bound_object.cc \
+	content/browser/renderer_host/java/java_bridge_channel_host.cc \
+	content/browser/renderer_host/java/java_bridge_dispatcher_host.cc \
+	content/browser/renderer_host/java/java_bridge_dispatcher_host_manager.cc \
+	content/browser/renderer_host/java/java_method.cc \
+	content/browser/renderer_host/java/java_type.cc \
+	content/browser/renderer_host/media/audio_input_device_manager.cc \
+	content/browser/renderer_host/media/audio_input_renderer_host.cc \
+	content/browser/renderer_host/media/audio_input_sync_writer.cc \
+	content/browser/renderer_host/media/audio_mirroring_manager.cc \
+	content/browser/renderer_host/media/audio_renderer_host.cc \
+	content/browser/renderer_host/media/audio_sync_reader.cc \
+	content/browser/renderer_host/media/media_stream_dispatcher_host.cc \
+	content/browser/renderer_host/media/media_stream_manager.cc \
+	content/browser/renderer_host/media/media_stream_ui_controller.cc \
+	content/browser/renderer_host/media/video_capture_buffer_pool.cc \
+	content/browser/renderer_host/media/video_capture_controller.cc \
+	content/browser/renderer_host/media/video_capture_controller_event_handler.cc \
+	content/browser/renderer_host/media/video_capture_host.cc \
+	content/browser/renderer_host/media/video_capture_manager.cc \
+	content/browser/renderer_host/media/web_contents_audio_input_stream.cc \
+	content/browser/renderer_host/media/web_contents_capture_util.cc \
+	content/browser/renderer_host/media/web_contents_tracker.cc \
+	content/browser/renderer_host/media/web_contents_video_capture_device.cc \
+	content/browser/renderer_host/media/webrtc_logging_handler_host.cc \
+	content/browser/renderer_host/native_web_keyboard_event_android.cc \
+	content/browser/renderer_host/native_web_keyboard_event.cc \
+	content/browser/renderer_host/overscroll_configuration.cc \
+	content/browser/renderer_host/overscroll_controller.cc \
+	content/browser/renderer_host/quota_dispatcher_host.cc \
+	content/browser/renderer_host/render_message_filter.cc \
+	content/browser/renderer_host/render_process_host_impl.cc \
+	content/browser/renderer_host/render_view_host_delegate.cc \
+	content/browser/renderer_host/render_view_host_factory.cc \
+	content/browser/renderer_host/render_view_host_impl.cc \
+	content/browser/renderer_host/render_widget_helper.cc \
+	content/browser/renderer_host/render_widget_host_delegate.cc \
+	content/browser/renderer_host/render_widget_host_impl.cc \
+	content/browser/renderer_host/render_widget_host_view_android.cc \
+	content/browser/renderer_host/render_widget_host_view_base.cc \
+	content/browser/renderer_host/render_widget_host_view_guest.cc \
+	content/browser/renderer_host/smooth_scroll_gesture_controller.cc \
+	content/browser/renderer_host/socket_stream_dispatcher_host.cc \
+	content/browser/renderer_host/socket_stream_host.cc \
+	content/browser/renderer_host/surface_texture_transport_client_android.cc \
+	content/browser/renderer_host/touch_event_queue.cc \
+	content/browser/renderer_host/touchpad_tap_suppression_controller.cc \
+	content/browser/renderer_host/touchscreen_tap_suppression_controller_stub.cc \
+	content/browser/resolve_proxy_msg_helper.cc \
+	content/browser/resource_context_impl.cc \
+	content/browser/site_instance_impl.cc \
+	content/browser/ssl/ssl_cert_error_handler.cc \
+	content/browser/ssl/ssl_client_auth_handler.cc \
+	content/browser/ssl/ssl_error_handler.cc \
+	content/browser/ssl/ssl_host_state.cc \
+	content/browser/ssl/ssl_manager.cc \
+	content/browser/ssl/ssl_policy_backend.cc \
+	content/browser/ssl/ssl_policy.cc \
+	content/browser/ssl/ssl_request_info.cc \
+	content/browser/streams/stream.cc \
+	content/browser/streams/stream_context.cc \
+	content/browser/streams/stream_handle_impl.cc \
+	content/browser/streams/stream_registry.cc \
+	content/browser/streams/stream_url_request_job.cc \
+	content/browser/storage_partition_impl.cc \
+	content/browser/storage_partition_impl_map.cc \
+	content/browser/tcmalloc_internals_request_job.cc \
+	content/browser/tracing/trace_controller_impl.cc \
+	content/browser/tracing/trace_message_filter.cc \
+	content/browser/tracing/trace_subscriber_stdio.cc \
+	content/browser/user_metrics.cc \
+	content/browser/utility_process_host_impl.cc \
+	content/browser/web_contents/debug_urls.cc \
+	content/browser/web_contents/interstitial_page_impl.cc \
+	content/browser/web_contents/navigation_controller_impl.cc \
+	content/browser/web_contents/navigation_entry_impl.cc \
+	content/browser/web_contents/render_view_host_manager.cc \
+	content/browser/web_contents/web_contents_impl.cc \
+	content/browser/web_contents/web_contents_screenshot_manager.cc \
+	content/browser/web_contents/web_contents_view_android.cc \
+	content/browser/web_contents/web_contents_view_guest.cc \
+	content/browser/webui/content_web_ui_controller_factory.cc \
+	content/browser/webui/generic_handler.cc \
+	content/browser/webui/shared_resources_data_source.cc \
+	content/browser/webui/url_data_manager.cc \
+	content/browser/webui/url_data_manager_backend.cc \
+	content/browser/webui/url_data_source_impl.cc \
+	content/browser/webui/web_ui_data_source_impl.cc \
+	content/browser/webui/web_ui_controller_factory_registry.cc \
+	content/browser/webui/web_ui_impl.cc \
+	content/browser/webui/web_ui_message_handler.cc \
+	content/browser/worker_host/message_port_service.cc \
+	content/browser/worker_host/worker_document_set.cc \
+	content/browser/worker_host/worker_message_filter.cc \
+	content/browser/worker_host/worker_process_host.cc \
+	content/browser/worker_host/worker_service_impl.cc \
+	content/browser/worker_host/worker_storage_partition.cc \
+	content/browser/gamepad/gamepad_platform_data_fetcher.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS := \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-m32 \
+	-mmmx \
+	-march=pentium4 \
+	-msse2 \
+	-mfpmath=sse \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-fno-stack-protector \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections
+
+MY_CFLAGS_C :=
+
+MY_DEFS := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DUSE_LINUX_BREAKPAD' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_GPU=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DENABLE_LANGUAGE_DETECTION=1' \
+	'-DENABLE_JAVA_BRIDGE' \
+	'-DPROTOBUF_USE_DLLS' \
+	'-DGOOGLE_PROTOBUF_NO_RTTI' \
+	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
+	'-DSK_BUILD_NO_IMAGE_ENCODE' \
+	'-DSK_DEFERRED_CANVAS_USES_GPIPE=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DGR_AGGRESSIVE_SHADER_OPTS=1' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_BUILD_FOR_ANDROID_NDK' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DMEDIA_DISABLE_LIBVPX' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+LOCAL_CFLAGS := $(MY_CFLAGS_C) $(MY_CFLAGS) $(MY_DEFS)
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES := \
+	$(LOCAL_PATH) \
+	$(gyp_intermediate_dir) \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(gyp_shared_intermediate_dir)/content \
+	$(gyp_shared_intermediate_dir)/protoc_out \
+	$(LOCAL_PATH)/third_party/protobuf \
+	$(LOCAL_PATH)/third_party/protobuf/src \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/config \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/gpu/gl \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(LOCAL_PATH)/third_party/re2 \
+	$(LOCAL_PATH)/third_party/zlib \
+	$(GYP_ABS_ANDROID_TOP_DIR)/external/icu4c/common \
+	$(GYP_ABS_ANDROID_TOP_DIR)/external/icu4c/i18n \
+	$(gyp_shared_intermediate_dir)/ui/ui_resources \
+	$(gyp_shared_intermediate_dir)/webkit \
+	$(LOCAL_PATH)/third_party/WebKit/Source/Platform/chromium \
+	$(LOCAL_PATH)/third_party/WebKit/Source/Platform/chromium \
+	$(LOCAL_PATH)/third_party/npapi \
+	$(LOCAL_PATH)/third_party/npapi/bindings \
+	$(LOCAL_PATH)/v8/include \
+	$(GYP_ABS_ANDROID_TOP_DIR)/frameworks/wilhelm/include \
+	$(GYP_ABS_ANDROID_TOP_DIR)/bionic \
+	$(GYP_ABS_ANDROID_TOP_DIR)/external/stlport/stlport
+
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES)
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-error=c++0x-compat \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+### Rules for final target.
+
+LOCAL_LDFLAGS := \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m32 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_STATIC_LIBRARIES := \
+	content_browser_speech_proto_speech_proto_gyp \
+	skia_skia_gyp \
+	ui_ui_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_content_browser_gyp
+
+# Alias gyp target name.
+.PHONY: content_browser
+content_browser: content_content_browser_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/content/content_browser.target.linux-arm.mk b/content/content_browser.target.linux-arm.mk
index 9d32fc3..6d993c9 100644
--- a/content/content_browser.target.linux-arm.mk
+++ b/content/content_browser.target.linux-arm.mk
@@ -14,6 +14,7 @@
 	$(call intermediates-dir-for,GYP,content_content_resources_gyp)/content_resources.stamp \
 	$(call intermediates-dir-for,STATIC_LIBRARIES,content_browser_speech_proto_speech_proto_gyp)/content_browser_speech_proto_speech_proto_gyp.a \
 	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_gyp)/skia_skia_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_ui_gyp)/ui_ui_gyp.a \
 	$(call intermediates-dir-for,GYP,ui_ui_resources_gyp)/ui_resources.stamp \
 	$(call intermediates-dir-for,GYP,content_browser_devtools_devtools_resources_gyp)/devtools_resources.stamp \
 	$(call intermediates-dir-for,GYP,webkit_support_webkit_resources_gyp)/webkit_resources.stamp \
@@ -50,6 +51,7 @@
 	content/public/browser/download_save_info.cc \
 	content/public/browser/download_url_parameters.cc \
 	content/public/browser/favicon_status.cc \
+	content/public/browser/indexed_db_info.cc \
 	content/public/browser/javascript_dialog_manager.cc \
 	content/public/browser/load_from_memory_cache_details.cc \
 	content/public/browser/navigation_controller.cc \
@@ -85,7 +87,7 @@
 	content/browser/android/devtools_auth.cc \
 	content/browser/android/interstitial_page_delegate_android.cc \
 	content/browser/android/load_url_params.cc \
-	content/browser/android/media_player_manager_android.cc \
+	content/browser/android/media_player_manager_impl.cc \
 	content/browser/android/media_resource_getter_impl.cc \
 	content/browser/android/surface_texture_peer_browser_impl.cc \
 	content/browser/android/sync_input_event_filter.cc \
@@ -118,6 +120,7 @@
 	content/browser/cross_site_request_manager.cc \
 	content/browser/devtools/devtools_agent_host_impl.cc \
 	content/browser/devtools/devtools_browser_target.cc \
+	content/browser/devtools/devtools_external_agent_proxy_impl.cc \
 	content/browser/devtools/devtools_frontend_host.cc \
 	content/browser/devtools/devtools_http_handler_impl.cc \
 	content/browser/devtools/devtools_manager_impl.cc \
@@ -125,8 +128,10 @@
 	content/browser/devtools/devtools_protocol.cc \
 	content/browser/devtools/devtools_protocol_constants.cc \
 	content/browser/devtools/devtools_tracing_handler.cc \
+	content/browser/devtools/ipc_devtools_agent_host.cc \
 	content/browser/devtools/render_view_devtools_agent_host.cc \
 	content/browser/devtools/renderer_overrides_handler.cc \
+	content/browser/devtools/tethering_handler.cc \
 	content/browser/devtools/worker_devtools_manager.cc \
 	content/browser/devtools/worker_devtools_message_filter.cc \
 	content/browser/device_orientation/data_fetcher_impl_android.cc \
@@ -200,17 +205,19 @@
 	content/browser/hyphenator/hyphenator_message_filter.cc \
 	content/browser/in_process_webkit/browser_webkitplatformsupport_impl.cc \
 	content/browser/in_process_webkit/indexed_db_callbacks.cc \
-	content/browser/in_process_webkit/indexed_db_context_impl.cc \
 	content/browser/in_process_webkit/indexed_db_database_callbacks.cc \
 	content/browser/in_process_webkit/indexed_db_dispatcher_host.cc \
-	content/browser/in_process_webkit/indexed_db_quota_client.cc \
 	content/browser/in_process_webkit/webkit_thread.cc \
+	content/browser/indexed_db/indexed_db_context_impl.cc \
+	content/browser/indexed_db/indexed_db_internals_ui.cc \
+	content/browser/indexed_db/indexed_db_quota_client.cc \
 	content/browser/loader/async_resource_handler.cc \
 	content/browser/loader/buffered_resource_handler.cc \
 	content/browser/loader/certificate_resource_handler.cc \
 	content/browser/loader/cross_site_resource_handler.cc \
 	content/browser/loader/doomed_resource_handler.cc \
 	content/browser/loader/layered_resource_handler.cc \
+	content/browser/loader/offline_policy.cc \
 	content/browser/loader/power_save_block_resource_throttle.cc \
 	content/browser/loader/redirect_to_file_resource_handler.cc \
 	content/browser/loader/render_view_host_tracker.cc \
@@ -237,6 +244,7 @@
 	content/browser/media/webrtc_internals_ui.cc \
 	content/browser/mime_registry_message_filter.cc \
 	content/browser/net/browser_online_state_observer.cc \
+	content/browser/net/sqlite_persistent_cookie_store.cc \
 	content/browser/net/view_blob_internals_job_factory.cc \
 	content/browser/net/view_http_cache_job_factory.cc \
 	content/browser/notification_service_impl.cc \
@@ -281,6 +289,7 @@
 	content/browser/renderer_host/media/web_contents_capture_util.cc \
 	content/browser/renderer_host/media/web_contents_tracker.cc \
 	content/browser/renderer_host/media/web_contents_video_capture_device.cc \
+	content/browser/renderer_host/media/webrtc_logging_handler_host.cc \
 	content/browser/renderer_host/native_web_keyboard_event_android.cc \
 	content/browser/renderer_host/native_web_keyboard_event.cc \
 	content/browser/renderer_host/overscroll_configuration.cc \
@@ -297,6 +306,7 @@
 	content/browser/renderer_host/render_widget_host_view_android.cc \
 	content/browser/renderer_host/render_widget_host_view_base.cc \
 	content/browser/renderer_host/render_widget_host_view_guest.cc \
+	content/browser/renderer_host/smooth_scroll_gesture_controller.cc \
 	content/browser/renderer_host/socket_stream_dispatcher_host.cc \
 	content/browser/renderer_host/socket_stream_host.cc \
 	content/browser/renderer_host/surface_texture_transport_client_android.cc \
@@ -333,6 +343,7 @@
 	content/browser/web_contents/navigation_entry_impl.cc \
 	content/browser/web_contents/render_view_host_manager.cc \
 	content/browser/web_contents/web_contents_impl.cc \
+	content/browser/web_contents/web_contents_screenshot_manager.cc \
 	content/browser/web_contents/web_contents_view_android.cc \
 	content/browser/web_contents/web_contents_view_guest.cc \
 	content/browser/webui/content_web_ui_controller_factory.cc \
@@ -391,7 +402,6 @@
 
 MY_DEFS := \
 	'-DCONTENT_IMPLEMENTATION' \
-	'-DUSE_SKIA' \
 	'-D_FILE_OFFSET_BITS=64' \
 	'-DUSE_LINUX_BREAKPAD' \
 	'-DNO_TCMALLOC' \
@@ -399,7 +409,6 @@
 	'-DCHROMIUM_BUILD' \
 	'-DUSE_LIBJPEG_TURBO=1' \
 	'-DUSE_PROPRIETARY_CODECS' \
-	'-DENABLE_PEPPER_THREADING' \
 	'-DENABLE_GPU=1' \
 	'-DUSE_OPENSSL=1' \
 	'-DENABLE_EGLIMAGE=1' \
@@ -433,10 +442,11 @@
 
 # Include paths placed before CFLAGS/CPPFLAGS
 LOCAL_C_INCLUDES := \
-	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
-	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
 	$(LOCAL_PATH) \
 	$(gyp_intermediate_dir) \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
 	$(LOCAL_PATH)/third_party/khronos \
 	$(LOCAL_PATH)/gpu \
 	$(gyp_shared_intermediate_dir)/content \
@@ -451,6 +461,7 @@
 	$(LOCAL_PATH)/third_party/skia/include/pdf \
 	$(LOCAL_PATH)/third_party/skia/include/gpu \
 	$(LOCAL_PATH)/third_party/skia/include/gpu/gl \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
 	$(LOCAL_PATH)/third_party/skia/include/pipe \
 	$(LOCAL_PATH)/third_party/skia/include/ports \
 	$(LOCAL_PATH)/third_party/skia/include/utils \
@@ -463,7 +474,6 @@
 	$(gyp_shared_intermediate_dir)/webkit \
 	$(LOCAL_PATH)/third_party/WebKit/Source/Platform/chromium \
 	$(LOCAL_PATH)/third_party/WebKit/Source/Platform/chromium \
-	$(gyp_shared_intermediate_dir)/webcore_headers \
 	$(LOCAL_PATH)/third_party/npapi \
 	$(LOCAL_PATH)/third_party/npapi/bindings \
 	$(LOCAL_PATH)/v8/include \
@@ -498,14 +508,15 @@
 	-Wl,--no-undefined \
 	-Wl,--exclude-libs=ALL \
 	-Wl,--icf=safe \
+	-Wl,--gc-sections \
 	-Wl,-O1 \
-	-Wl,--as-needed \
-	-Wl,--gc-sections
+	-Wl,--as-needed
 
 
 LOCAL_STATIC_LIBRARIES := \
 	content_browser_speech_proto_speech_proto_gyp \
-	skia_skia_gyp
+	skia_skia_gyp \
+	ui_ui_gyp
 
 # Enable grouping to fix circular references
 LOCAL_GROUP_STATIC_LIBRARIES := true
diff --git a/content/content_browser.target.linux-x86.mk b/content/content_browser.target.linux-x86.mk
index 62486e9..44e619e 100644
--- a/content/content_browser.target.linux-x86.mk
+++ b/content/content_browser.target.linux-x86.mk
@@ -14,6 +14,7 @@
 	$(call intermediates-dir-for,GYP,content_content_resources_gyp)/content_resources.stamp \
 	$(call intermediates-dir-for,STATIC_LIBRARIES,content_browser_speech_proto_speech_proto_gyp)/content_browser_speech_proto_speech_proto_gyp.a \
 	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_gyp)/skia_skia_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_ui_gyp)/ui_ui_gyp.a \
 	$(call intermediates-dir-for,GYP,ui_ui_resources_gyp)/ui_resources.stamp \
 	$(call intermediates-dir-for,GYP,content_browser_devtools_devtools_resources_gyp)/devtools_resources.stamp \
 	$(call intermediates-dir-for,GYP,webkit_support_webkit_resources_gyp)/webkit_resources.stamp \
@@ -50,6 +51,7 @@
 	content/public/browser/download_save_info.cc \
 	content/public/browser/download_url_parameters.cc \
 	content/public/browser/favicon_status.cc \
+	content/public/browser/indexed_db_info.cc \
 	content/public/browser/javascript_dialog_manager.cc \
 	content/public/browser/load_from_memory_cache_details.cc \
 	content/public/browser/navigation_controller.cc \
@@ -85,7 +87,7 @@
 	content/browser/android/devtools_auth.cc \
 	content/browser/android/interstitial_page_delegate_android.cc \
 	content/browser/android/load_url_params.cc \
-	content/browser/android/media_player_manager_android.cc \
+	content/browser/android/media_player_manager_impl.cc \
 	content/browser/android/media_resource_getter_impl.cc \
 	content/browser/android/surface_texture_peer_browser_impl.cc \
 	content/browser/android/sync_input_event_filter.cc \
@@ -118,6 +120,7 @@
 	content/browser/cross_site_request_manager.cc \
 	content/browser/devtools/devtools_agent_host_impl.cc \
 	content/browser/devtools/devtools_browser_target.cc \
+	content/browser/devtools/devtools_external_agent_proxy_impl.cc \
 	content/browser/devtools/devtools_frontend_host.cc \
 	content/browser/devtools/devtools_http_handler_impl.cc \
 	content/browser/devtools/devtools_manager_impl.cc \
@@ -125,8 +128,10 @@
 	content/browser/devtools/devtools_protocol.cc \
 	content/browser/devtools/devtools_protocol_constants.cc \
 	content/browser/devtools/devtools_tracing_handler.cc \
+	content/browser/devtools/ipc_devtools_agent_host.cc \
 	content/browser/devtools/render_view_devtools_agent_host.cc \
 	content/browser/devtools/renderer_overrides_handler.cc \
+	content/browser/devtools/tethering_handler.cc \
 	content/browser/devtools/worker_devtools_manager.cc \
 	content/browser/devtools/worker_devtools_message_filter.cc \
 	content/browser/device_orientation/data_fetcher_impl_android.cc \
@@ -200,17 +205,19 @@
 	content/browser/hyphenator/hyphenator_message_filter.cc \
 	content/browser/in_process_webkit/browser_webkitplatformsupport_impl.cc \
 	content/browser/in_process_webkit/indexed_db_callbacks.cc \
-	content/browser/in_process_webkit/indexed_db_context_impl.cc \
 	content/browser/in_process_webkit/indexed_db_database_callbacks.cc \
 	content/browser/in_process_webkit/indexed_db_dispatcher_host.cc \
-	content/browser/in_process_webkit/indexed_db_quota_client.cc \
 	content/browser/in_process_webkit/webkit_thread.cc \
+	content/browser/indexed_db/indexed_db_context_impl.cc \
+	content/browser/indexed_db/indexed_db_internals_ui.cc \
+	content/browser/indexed_db/indexed_db_quota_client.cc \
 	content/browser/loader/async_resource_handler.cc \
 	content/browser/loader/buffered_resource_handler.cc \
 	content/browser/loader/certificate_resource_handler.cc \
 	content/browser/loader/cross_site_resource_handler.cc \
 	content/browser/loader/doomed_resource_handler.cc \
 	content/browser/loader/layered_resource_handler.cc \
+	content/browser/loader/offline_policy.cc \
 	content/browser/loader/power_save_block_resource_throttle.cc \
 	content/browser/loader/redirect_to_file_resource_handler.cc \
 	content/browser/loader/render_view_host_tracker.cc \
@@ -237,6 +244,7 @@
 	content/browser/media/webrtc_internals_ui.cc \
 	content/browser/mime_registry_message_filter.cc \
 	content/browser/net/browser_online_state_observer.cc \
+	content/browser/net/sqlite_persistent_cookie_store.cc \
 	content/browser/net/view_blob_internals_job_factory.cc \
 	content/browser/net/view_http_cache_job_factory.cc \
 	content/browser/notification_service_impl.cc \
@@ -281,6 +289,7 @@
 	content/browser/renderer_host/media/web_contents_capture_util.cc \
 	content/browser/renderer_host/media/web_contents_tracker.cc \
 	content/browser/renderer_host/media/web_contents_video_capture_device.cc \
+	content/browser/renderer_host/media/webrtc_logging_handler_host.cc \
 	content/browser/renderer_host/native_web_keyboard_event_android.cc \
 	content/browser/renderer_host/native_web_keyboard_event.cc \
 	content/browser/renderer_host/overscroll_configuration.cc \
@@ -297,6 +306,7 @@
 	content/browser/renderer_host/render_widget_host_view_android.cc \
 	content/browser/renderer_host/render_widget_host_view_base.cc \
 	content/browser/renderer_host/render_widget_host_view_guest.cc \
+	content/browser/renderer_host/smooth_scroll_gesture_controller.cc \
 	content/browser/renderer_host/socket_stream_dispatcher_host.cc \
 	content/browser/renderer_host/socket_stream_host.cc \
 	content/browser/renderer_host/surface_texture_transport_client_android.cc \
@@ -333,6 +343,7 @@
 	content/browser/web_contents/navigation_entry_impl.cc \
 	content/browser/web_contents/render_view_host_manager.cc \
 	content/browser/web_contents/web_contents_impl.cc \
+	content/browser/web_contents/web_contents_screenshot_manager.cc \
 	content/browser/web_contents/web_contents_view_android.cc \
 	content/browser/web_contents/web_contents_view_guest.cc \
 	content/browser/webui/content_web_ui_controller_factory.cc \
@@ -371,6 +382,7 @@
 	-march=pentium4 \
 	-msse2 \
 	-mfpmath=sse \
+	-fuse-ld=gold \
 	-ffunction-sections \
 	-funwind-tables \
 	-g \
@@ -392,7 +404,6 @@
 
 MY_DEFS := \
 	'-DCONTENT_IMPLEMENTATION' \
-	'-DUSE_SKIA' \
 	'-D_FILE_OFFSET_BITS=64' \
 	'-DUSE_LINUX_BREAKPAD' \
 	'-DNO_TCMALLOC' \
@@ -400,7 +411,6 @@
 	'-DCHROMIUM_BUILD' \
 	'-DUSE_LIBJPEG_TURBO=1' \
 	'-DUSE_PROPRIETARY_CODECS' \
-	'-DENABLE_PEPPER_THREADING' \
 	'-DENABLE_GPU=1' \
 	'-DUSE_OPENSSL=1' \
 	'-DENABLE_EGLIMAGE=1' \
@@ -433,10 +443,11 @@
 
 # Include paths placed before CFLAGS/CPPFLAGS
 LOCAL_C_INCLUDES := \
-	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
-	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
 	$(LOCAL_PATH) \
 	$(gyp_intermediate_dir) \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
 	$(LOCAL_PATH)/third_party/khronos \
 	$(LOCAL_PATH)/gpu \
 	$(gyp_shared_intermediate_dir)/content \
@@ -451,6 +462,7 @@
 	$(LOCAL_PATH)/third_party/skia/include/pdf \
 	$(LOCAL_PATH)/third_party/skia/include/gpu \
 	$(LOCAL_PATH)/third_party/skia/include/gpu/gl \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
 	$(LOCAL_PATH)/third_party/skia/include/pipe \
 	$(LOCAL_PATH)/third_party/skia/include/ports \
 	$(LOCAL_PATH)/third_party/skia/include/utils \
@@ -463,7 +475,6 @@
 	$(gyp_shared_intermediate_dir)/webkit \
 	$(LOCAL_PATH)/third_party/WebKit/Source/Platform/chromium \
 	$(LOCAL_PATH)/third_party/WebKit/Source/Platform/chromium \
-	$(gyp_shared_intermediate_dir)/webcore_headers \
 	$(LOCAL_PATH)/third_party/npapi \
 	$(LOCAL_PATH)/third_party/npapi/bindings \
 	$(LOCAL_PATH)/v8/include \
@@ -491,17 +502,19 @@
 	-Wl,-z,noexecstack \
 	-fPIC \
 	-m32 \
+	-fuse-ld=gold \
 	-nostdlib \
 	-Wl,--no-undefined \
 	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
 	-Wl,-O1 \
-	-Wl,--as-needed \
-	-Wl,--gc-sections
+	-Wl,--as-needed
 
 
 LOCAL_STATIC_LIBRARIES := \
 	content_browser_speech_proto_speech_proto_gyp \
-	skia_skia_gyp
+	skia_skia_gyp \
+	ui_ui_gyp
 
 # Enable grouping to fix circular references
 LOCAL_GROUP_STATIC_LIBRARIES := true
diff --git a/content/content_common.gypi b/content/content_common.gypi
index 1e40703..9537c6c 100644
--- a/content/content_common.gypi
+++ b/content/content_common.gypi
@@ -114,12 +114,6 @@
     'common/android/device_telephony_info.h',
     'common/android/hash_set.cc',
     'common/android/hash_set.h',
-    'common/android/scoped_java_surface.cc',
-    'common/android/scoped_java_surface.h',
-    'common/android/surface_texture_bridge.cc',
-    'common/android/surface_texture_bridge.h',
-    'common/android/surface_texture_listener.cc',
-    'common/android/surface_texture_listener.h',
     'common/android/surface_texture_peer.cc',
     'common/android/surface_texture_peer.h',
     'common/android/trace_event_binding.cc',
@@ -192,6 +186,7 @@
     'common/font_cache_dispatcher_win.h',
     'common/font_config_ipc_linux.cc',
     'common/font_config_ipc_linux.h',
+    'common/font_list.cc',
     'common/font_list.h',
     'common/font_list_android.cc',
     'common/font_list_linux.cc',
@@ -245,17 +240,13 @@
     'common/gpu/image_transport_surface.h',
     'common/gpu/image_transport_surface.cc',
     'common/gpu/image_transport_surface_android.cc',
-    'common/gpu/image_transport_surface_linux.cc',
     'common/gpu/image_transport_surface_mac.cc',
     'common/gpu/image_transport_surface_win.cc',
-    'common/gpu/media/avc_config_record_builder.cc',
-    'common/gpu/media/avc_config_record_builder.h',
+    'common/gpu/image_transport_surface_x11.cc',
     'common/gpu/media/h264_bit_reader.cc',
     'common/gpu/media/h264_bit_reader.h',
     'common/gpu/media/h264_parser.cc',
     'common/gpu/media/h264_parser.h',
-    'common/gpu/media/mac_video_decode_accelerator.h',
-    'common/gpu/media/mac_video_decode_accelerator.mm',
     'common/gpu/media/gpu_video_decode_accelerator.cc',
     'common/gpu/media/gpu_video_decode_accelerator.h',
     'common/gpu/sync_point_manager.h',
@@ -264,7 +255,7 @@
     'common/gpu/texture_image_transport_surface.cc',
     'common/handle_enumerator_win.cc',
     'common/handle_enumerator_win.h',
-    'common/icon_messages.h',
+    'common/image_messages.h',
     'common/indexed_db/indexed_db_key.cc',
     'common/indexed_db/indexed_db_key.h',
     'common/indexed_db/indexed_db_key_path.cc',
@@ -284,6 +275,7 @@
     'common/indexed_db/proxy_webidbdatabase_impl.h',
     'common/indexed_db/proxy_webidbfactory_impl.cc',
     'common/indexed_db/proxy_webidbfactory_impl.h',
+    'common/input_messages.h',
     'common/inter_process_time_ticks_converter.cc',
     'common/inter_process_time_ticks_converter.h',
     'common/java_bridge_messages.h',
@@ -302,6 +294,7 @@
     'common/media/media_stream_options.h',
     'common/media/video_capture.h',
     'common/media/video_capture_messages.h',
+    'common/media/webrtc_logging_messages.h',
     'common/message_router.cc',
     'common/message_router.h',
     'common/mime_registry_messages.h',
@@ -321,6 +314,8 @@
     'common/p2p_messages.h',
     'common/p2p_sockets.h',
     'common/page_zoom.cc',
+    'common/partial_circular_buffer.cc',
+    'common/partial_circular_buffer.h',
     'common/pepper_messages.h',
     'common/pepper_plugin_registry.cc',
     'common/pepper_plugin_registry.h',
@@ -342,7 +337,6 @@
     'common/sandbox_init_mac.cc',
     'common/sandbox_init_mac.h',
     'common/sandbox_init_win.cc',
-    'common/sandbox_init_linux.cc',
     'common/sandbox_mac.h',
     'common/sandbox_mac.mm',
     'common/sandbox_linux.h',
@@ -451,10 +445,12 @@
         '../build/linux/system.gyp:gtk',
       ],
     }],
-    ['use_x11 == 1', {
+    ['OS=="linux"', {
       'dependencies': [
         '../build/linux/system.gyp:pangocairo',
       ],
+    }],
+    ['use_x11 == 1', {
       'include_dirs': [
         '<(DEPTH)/third_party/angle/include',
       ],
diff --git a/content/content_common.target.darwin-arm.mk b/content/content_common.target.darwin-arm.mk
new file mode 100644
index 0000000..f9269a2
--- /dev/null
+++ b/content/content_common.target.darwin-arm.mk
@@ -0,0 +1,317 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := content_content_common_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_gyp)/skia_skia_gyp.a \
+	$(call intermediates-dir-for,GYP,third_party_icu_icuuc_gyp)/icuuc.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_ui_gyp)/ui_ui_gyp.a \
+	$(call intermediates-dir-for,GYP,content_content_resources_gyp)/content_resources.stamp \
+	$(call intermediates-dir-for,GYP,third_party_npapi_npapi_gyp)/npapi.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_gl_gl_gyp)/ui_gl_gl_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,webkit_support_glue_gyp)/webkit_support_glue_gyp.a \
+	$(call intermediates-dir-for,GYP,content_content_jni_headers_gyp)/content_jni_headers.stamp \
+	$(call intermediates-dir-for,GYP,content_common_aidl_gyp)/common_aidl.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	content/public/common/child_process_host_delegate.cc \
+	content/public/common/content_constants.cc \
+	content/public/common/content_switches.cc \
+	content/public/common/context_menu_params.cc \
+	content/public/common/dx_diag_node.cc \
+	content/public/common/favicon_url.cc \
+	content/public/common/file_chooser_params.cc \
+	content/public/common/frame_navigate_params.cc \
+	content/public/common/geoposition.cc \
+	content/public/common/gpu_info.cc \
+	content/public/common/gpu_memory_stats.cc \
+	content/public/common/media_stream_request.cc \
+	content/public/common/page_transition_types.cc \
+	content/public/common/password_form.cc \
+	content/public/common/pepper_plugin_info.cc \
+	content/public/common/renderer_preferences.cc \
+	content/public/common/show_desktop_notification_params.cc \
+	content/public/common/speech_recognition_result.cc \
+	content/public/common/ssl_status.cc \
+	content/public/common/url_constants.cc \
+	content/common/accessibility_node_data.cc \
+	content/common/android/address_parser.cc \
+	content/common/android/address_parser_internal.cc \
+	content/common/android/command_line.cc \
+	content/common/android/common_jni_registrar.cc \
+	content/common/android/device_telephony_info.cc \
+	content/common/android/hash_set.cc \
+	content/common/android/surface_texture_peer.cc \
+	content/common/android/trace_event_binding.cc \
+	content/common/appcache/appcache_backend_proxy.cc \
+	content/common/appcache/appcache_dispatcher.cc \
+	content/common/browser_plugin/browser_plugin_constants.cc \
+	content/common/cc_messages.cc \
+	content/common/child_histogram_message_filter.cc \
+	content/common/child_process.cc \
+	content/common/child_process_host_impl.cc \
+	content/common/child_thread.cc \
+	content/common/clipboard_messages.cc \
+	content/common/content_constants_internal.cc \
+	content/common/content_ipc_logging.cc \
+	content/common/content_message_generator.cc \
+	content/common/content_param_traits.cc \
+	content/common/content_paths.cc \
+	content/common/database_util.cc \
+	content/common/db_message_filter.cc \
+	content/common/fileapi/file_system_dispatcher.cc \
+	content/common/fileapi/webblobregistry_impl.cc \
+	content/common/fileapi/webfilesystem_callback_dispatcher.cc \
+	content/common/fileapi/webfilesystem_impl.cc \
+	content/common/fileapi/webfilewriter_impl.cc \
+	content/common/find_match_rect_android.cc \
+	content/common/font_list.cc \
+	content/common/font_list_android.cc \
+	content/common/gamepad_seqlock.cc \
+	content/common/gamepad_user_gesture.cc \
+	content/common/gpu/client/command_buffer_proxy_impl.cc \
+	content/common/gpu/client/context_provider_command_buffer.cc \
+	content/common/gpu/client/gl_helper.cc \
+	content/common/gpu/client/gpu_channel_host.cc \
+	content/common/gpu/client/gpu_video_decode_accelerator_host.cc \
+	content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.cc \
+	content/common/gpu/gl_scoped_binders.cc \
+	content/common/gpu/gpu_channel.cc \
+	content/common/gpu/gpu_channel_manager.cc \
+	content/common/gpu/gpu_command_buffer_stub.cc \
+	content/common/gpu/gpu_memory_manager.cc \
+	content/common/gpu/gpu_memory_manager_client.cc \
+	content/common/gpu/gpu_memory_tracking.cc \
+	content/common/gpu/gpu_rendering_stats.cc \
+	content/common/gpu/gpu_surface_lookup.cc \
+	content/common/gpu/stream_texture_manager_android.cc \
+	content/common/gpu/image_transport_surface.cc \
+	content/common/gpu/image_transport_surface_android.cc \
+	content/common/gpu/media/h264_bit_reader.cc \
+	content/common/gpu/media/h264_parser.cc \
+	content/common/gpu/media/gpu_video_decode_accelerator.cc \
+	content/common/gpu/sync_point_manager.cc \
+	content/common/gpu/texture_image_transport_surface.cc \
+	content/common/indexed_db/indexed_db_key.cc \
+	content/common/indexed_db/indexed_db_key_path.cc \
+	content/common/indexed_db/indexed_db_key_range.cc \
+	content/common/indexed_db/indexed_db_param_traits.cc \
+	content/common/indexed_db/indexed_db_dispatcher.cc \
+	content/common/indexed_db/indexed_db_message_filter.cc \
+	content/common/indexed_db/proxy_webidbcursor_impl.cc \
+	content/common/indexed_db/proxy_webidbdatabase_impl.cc \
+	content/common/indexed_db/proxy_webidbfactory_impl.cc \
+	content/common/inter_process_time_ticks_converter.cc \
+	content/common/media/media_param_traits.cc \
+	content/common/media/media_stream_options.cc \
+	content/common/message_router.cc \
+	content/common/net/url_fetcher.cc \
+	content/common/net/url_request_user_data.cc \
+	content/common/np_channel_base.cc \
+	content/common/npobject_proxy.cc \
+	content/common/npobject_stub.cc \
+	content/common/npobject_util.cc \
+	content/common/page_zoom.cc \
+	content/common/partial_circular_buffer.cc \
+	content/common/pepper_renderer_instance_data.cc \
+	content/common/process_type.cc \
+	content/common/quota_dispatcher.cc \
+	content/common/request_extra_data.cc \
+	content/common/resource_dispatcher.cc \
+	content/common/resource_messages.cc \
+	content/common/sandbox_util.cc \
+	content/common/savable_url_schemes.cc \
+	content/common/set_process_title.cc \
+	content/common/socket_stream_dispatcher.cc \
+	content/common/socket_stream_handle_data.cc \
+	content/common/ssl_status_serialization.cc \
+	content/common/swapped_out_messages.cc \
+	content/common/thread_safe_sender.cc \
+	content/common/url_schemes.cc \
+	content/common/web_database_observer_impl.cc \
+	content/common/webkitplatformsupport_impl.cc \
+	content/common/webmessageportchannel_impl.cc \
+	content/public/common/common_param_traits.cc \
+	content/public/common/content_client.cc \
+	content/public/common/window_container_type.cc \
+	content/common/gpu/media/android_video_decode_accelerator.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-fno-tree-sra \
+	-fuse-ld=gold \
+	-Wno-psabi \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections
+
+MY_CFLAGS_C :=
+
+MY_DEFS := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DUSE_LINUX_BREAKPAD' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_GPU=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DENABLE_LANGUAGE_DETECTION=1' \
+	'-DMEDIA_DISABLE_LIBVPX' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DSK_BUILD_NO_IMAGE_ENCODE' \
+	'-DSK_DEFERRED_CANVAS_USES_GPIPE=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DGR_AGGRESSIVE_SHADER_OPTS=1' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_BUILD_FOR_ANDROID_NDK' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+LOCAL_CFLAGS := $(MY_CFLAGS_C) $(MY_CFLAGS) $(MY_DEFS)
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES := \
+	$(LOCAL_PATH) \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/config \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/gpu/gl \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(GYP_ABS_ANDROID_TOP_DIR)/external/icu4c/common \
+	$(GYP_ABS_ANDROID_TOP_DIR)/external/icu4c/i18n \
+	$(gyp_shared_intermediate_dir)/content \
+	$(LOCAL_PATH)/third_party/npapi \
+	$(LOCAL_PATH)/third_party/npapi/bindings \
+	$(LOCAL_PATH)/third_party/WebKit/Source/Platform/chromium \
+	$(LOCAL_PATH)/third_party/WebKit/Source/Platform/chromium \
+	$(LOCAL_PATH)/v8/include \
+	$(gyp_shared_intermediate_dir)/ui/gl \
+	$(LOCAL_PATH)/third_party/mesa/MesaLib/include \
+	$(GYP_ABS_ANDROID_TOP_DIR)/frameworks/wilhelm/include \
+	$(GYP_ABS_ANDROID_TOP_DIR)/bionic \
+	$(GYP_ABS_ANDROID_TOP_DIR)/external/stlport/stlport
+
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES)
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-abi \
+	-Wno-error=c++0x-compat \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+### Rules for final target.
+
+LOCAL_LDFLAGS := \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-Wl,-z,relro \
+	-Wl,-z,now \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--icf=safe \
+	-Wl,--gc-sections \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_STATIC_LIBRARIES := \
+	skia_skia_gyp \
+	ui_ui_gyp \
+	ui_gl_gl_gyp \
+	webkit_support_glue_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_content_common_gyp
+
+# Alias gyp target name.
+.PHONY: content_common
+content_common: content_content_common_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/content/content_common.target.darwin-x86.mk b/content/content_common.target.darwin-x86.mk
new file mode 100644
index 0000000..452cf6d
--- /dev/null
+++ b/content/content_common.target.darwin-x86.mk
@@ -0,0 +1,315 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := content_content_common_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_gyp)/skia_skia_gyp.a \
+	$(call intermediates-dir-for,GYP,third_party_icu_icuuc_gyp)/icuuc.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_ui_gyp)/ui_ui_gyp.a \
+	$(call intermediates-dir-for,GYP,content_content_resources_gyp)/content_resources.stamp \
+	$(call intermediates-dir-for,GYP,third_party_npapi_npapi_gyp)/npapi.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_gl_gl_gyp)/ui_gl_gl_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,webkit_support_glue_gyp)/webkit_support_glue_gyp.a \
+	$(call intermediates-dir-for,GYP,content_content_jni_headers_gyp)/content_jni_headers.stamp \
+	$(call intermediates-dir-for,GYP,content_common_aidl_gyp)/common_aidl.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	content/public/common/child_process_host_delegate.cc \
+	content/public/common/content_constants.cc \
+	content/public/common/content_switches.cc \
+	content/public/common/context_menu_params.cc \
+	content/public/common/dx_diag_node.cc \
+	content/public/common/favicon_url.cc \
+	content/public/common/file_chooser_params.cc \
+	content/public/common/frame_navigate_params.cc \
+	content/public/common/geoposition.cc \
+	content/public/common/gpu_info.cc \
+	content/public/common/gpu_memory_stats.cc \
+	content/public/common/media_stream_request.cc \
+	content/public/common/page_transition_types.cc \
+	content/public/common/password_form.cc \
+	content/public/common/pepper_plugin_info.cc \
+	content/public/common/renderer_preferences.cc \
+	content/public/common/show_desktop_notification_params.cc \
+	content/public/common/speech_recognition_result.cc \
+	content/public/common/ssl_status.cc \
+	content/public/common/url_constants.cc \
+	content/common/accessibility_node_data.cc \
+	content/common/android/address_parser.cc \
+	content/common/android/address_parser_internal.cc \
+	content/common/android/command_line.cc \
+	content/common/android/common_jni_registrar.cc \
+	content/common/android/device_telephony_info.cc \
+	content/common/android/hash_set.cc \
+	content/common/android/surface_texture_peer.cc \
+	content/common/android/trace_event_binding.cc \
+	content/common/appcache/appcache_backend_proxy.cc \
+	content/common/appcache/appcache_dispatcher.cc \
+	content/common/browser_plugin/browser_plugin_constants.cc \
+	content/common/cc_messages.cc \
+	content/common/child_histogram_message_filter.cc \
+	content/common/child_process.cc \
+	content/common/child_process_host_impl.cc \
+	content/common/child_thread.cc \
+	content/common/clipboard_messages.cc \
+	content/common/content_constants_internal.cc \
+	content/common/content_ipc_logging.cc \
+	content/common/content_message_generator.cc \
+	content/common/content_param_traits.cc \
+	content/common/content_paths.cc \
+	content/common/database_util.cc \
+	content/common/db_message_filter.cc \
+	content/common/fileapi/file_system_dispatcher.cc \
+	content/common/fileapi/webblobregistry_impl.cc \
+	content/common/fileapi/webfilesystem_callback_dispatcher.cc \
+	content/common/fileapi/webfilesystem_impl.cc \
+	content/common/fileapi/webfilewriter_impl.cc \
+	content/common/find_match_rect_android.cc \
+	content/common/font_list.cc \
+	content/common/font_list_android.cc \
+	content/common/gamepad_seqlock.cc \
+	content/common/gamepad_user_gesture.cc \
+	content/common/gpu/client/command_buffer_proxy_impl.cc \
+	content/common/gpu/client/context_provider_command_buffer.cc \
+	content/common/gpu/client/gl_helper.cc \
+	content/common/gpu/client/gpu_channel_host.cc \
+	content/common/gpu/client/gpu_video_decode_accelerator_host.cc \
+	content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.cc \
+	content/common/gpu/gl_scoped_binders.cc \
+	content/common/gpu/gpu_channel.cc \
+	content/common/gpu/gpu_channel_manager.cc \
+	content/common/gpu/gpu_command_buffer_stub.cc \
+	content/common/gpu/gpu_memory_manager.cc \
+	content/common/gpu/gpu_memory_manager_client.cc \
+	content/common/gpu/gpu_memory_tracking.cc \
+	content/common/gpu/gpu_rendering_stats.cc \
+	content/common/gpu/gpu_surface_lookup.cc \
+	content/common/gpu/stream_texture_manager_android.cc \
+	content/common/gpu/image_transport_surface.cc \
+	content/common/gpu/image_transport_surface_android.cc \
+	content/common/gpu/media/h264_bit_reader.cc \
+	content/common/gpu/media/h264_parser.cc \
+	content/common/gpu/media/gpu_video_decode_accelerator.cc \
+	content/common/gpu/sync_point_manager.cc \
+	content/common/gpu/texture_image_transport_surface.cc \
+	content/common/indexed_db/indexed_db_key.cc \
+	content/common/indexed_db/indexed_db_key_path.cc \
+	content/common/indexed_db/indexed_db_key_range.cc \
+	content/common/indexed_db/indexed_db_param_traits.cc \
+	content/common/indexed_db/indexed_db_dispatcher.cc \
+	content/common/indexed_db/indexed_db_message_filter.cc \
+	content/common/indexed_db/proxy_webidbcursor_impl.cc \
+	content/common/indexed_db/proxy_webidbdatabase_impl.cc \
+	content/common/indexed_db/proxy_webidbfactory_impl.cc \
+	content/common/inter_process_time_ticks_converter.cc \
+	content/common/media/media_param_traits.cc \
+	content/common/media/media_stream_options.cc \
+	content/common/message_router.cc \
+	content/common/net/url_fetcher.cc \
+	content/common/net/url_request_user_data.cc \
+	content/common/np_channel_base.cc \
+	content/common/npobject_proxy.cc \
+	content/common/npobject_stub.cc \
+	content/common/npobject_util.cc \
+	content/common/page_zoom.cc \
+	content/common/partial_circular_buffer.cc \
+	content/common/pepper_renderer_instance_data.cc \
+	content/common/process_type.cc \
+	content/common/quota_dispatcher.cc \
+	content/common/request_extra_data.cc \
+	content/common/resource_dispatcher.cc \
+	content/common/resource_messages.cc \
+	content/common/sandbox_util.cc \
+	content/common/savable_url_schemes.cc \
+	content/common/set_process_title.cc \
+	content/common/socket_stream_dispatcher.cc \
+	content/common/socket_stream_handle_data.cc \
+	content/common/ssl_status_serialization.cc \
+	content/common/swapped_out_messages.cc \
+	content/common/thread_safe_sender.cc \
+	content/common/url_schemes.cc \
+	content/common/web_database_observer_impl.cc \
+	content/common/webkitplatformsupport_impl.cc \
+	content/common/webmessageportchannel_impl.cc \
+	content/public/common/common_param_traits.cc \
+	content/public/common/content_client.cc \
+	content/public/common/window_container_type.cc \
+	content/common/gpu/media/android_video_decode_accelerator.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS := \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-m32 \
+	-mmmx \
+	-march=pentium4 \
+	-msse2 \
+	-mfpmath=sse \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-fno-stack-protector \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections
+
+MY_CFLAGS_C :=
+
+MY_DEFS := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DUSE_LINUX_BREAKPAD' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_GPU=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DENABLE_LANGUAGE_DETECTION=1' \
+	'-DMEDIA_DISABLE_LIBVPX' \
+	'-DSK_BUILD_NO_IMAGE_ENCODE' \
+	'-DSK_DEFERRED_CANVAS_USES_GPIPE=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DGR_AGGRESSIVE_SHADER_OPTS=1' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_BUILD_FOR_ANDROID_NDK' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+LOCAL_CFLAGS := $(MY_CFLAGS_C) $(MY_CFLAGS) $(MY_DEFS)
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES := \
+	$(LOCAL_PATH) \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/config \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/gpu/gl \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(GYP_ABS_ANDROID_TOP_DIR)/external/icu4c/common \
+	$(GYP_ABS_ANDROID_TOP_DIR)/external/icu4c/i18n \
+	$(gyp_shared_intermediate_dir)/content \
+	$(LOCAL_PATH)/third_party/npapi \
+	$(LOCAL_PATH)/third_party/npapi/bindings \
+	$(LOCAL_PATH)/third_party/WebKit/Source/Platform/chromium \
+	$(LOCAL_PATH)/third_party/WebKit/Source/Platform/chromium \
+	$(LOCAL_PATH)/v8/include \
+	$(gyp_shared_intermediate_dir)/ui/gl \
+	$(LOCAL_PATH)/third_party/mesa/MesaLib/include \
+	$(GYP_ABS_ANDROID_TOP_DIR)/frameworks/wilhelm/include \
+	$(GYP_ABS_ANDROID_TOP_DIR)/bionic \
+	$(GYP_ABS_ANDROID_TOP_DIR)/external/stlport/stlport
+
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES)
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-error=c++0x-compat \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+### Rules for final target.
+
+LOCAL_LDFLAGS := \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m32 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_STATIC_LIBRARIES := \
+	skia_skia_gyp \
+	ui_ui_gyp \
+	ui_gl_gl_gyp \
+	webkit_support_glue_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_content_common_gyp
+
+# Alias gyp target name.
+.PHONY: content_common
+content_common: content_content_common_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/content/content_common.target.linux-arm.mk b/content/content_common.target.linux-arm.mk
index 132444d..f9269a2 100644
--- a/content/content_common.target.linux-arm.mk
+++ b/content/content_common.target.linux-arm.mk
@@ -13,6 +13,7 @@
 GYP_TARGET_DEPENDENCIES := \
 	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_gyp)/skia_skia_gyp.a \
 	$(call intermediates-dir-for,GYP,third_party_icu_icuuc_gyp)/icuuc.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_ui_gyp)/ui_ui_gyp.a \
 	$(call intermediates-dir-for,GYP,content_content_resources_gyp)/content_resources.stamp \
 	$(call intermediates-dir-for,GYP,third_party_npapi_npapi_gyp)/npapi.stamp \
 	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_gl_gl_gyp)/ui_gl_gl_gyp.a \
@@ -58,9 +59,6 @@
 	content/common/android/common_jni_registrar.cc \
 	content/common/android/device_telephony_info.cc \
 	content/common/android/hash_set.cc \
-	content/common/android/scoped_java_surface.cc \
-	content/common/android/surface_texture_bridge.cc \
-	content/common/android/surface_texture_listener.cc \
 	content/common/android/surface_texture_peer.cc \
 	content/common/android/trace_event_binding.cc \
 	content/common/appcache/appcache_backend_proxy.cc \
@@ -85,6 +83,7 @@
 	content/common/fileapi/webfilesystem_impl.cc \
 	content/common/fileapi/webfilewriter_impl.cc \
 	content/common/find_match_rect_android.cc \
+	content/common/font_list.cc \
 	content/common/font_list_android.cc \
 	content/common/gamepad_seqlock.cc \
 	content/common/gamepad_user_gesture.cc \
@@ -106,7 +105,6 @@
 	content/common/gpu/stream_texture_manager_android.cc \
 	content/common/gpu/image_transport_surface.cc \
 	content/common/gpu/image_transport_surface_android.cc \
-	content/common/gpu/media/avc_config_record_builder.cc \
 	content/common/gpu/media/h264_bit_reader.cc \
 	content/common/gpu/media/h264_parser.cc \
 	content/common/gpu/media/gpu_video_decode_accelerator.cc \
@@ -132,6 +130,7 @@
 	content/common/npobject_stub.cc \
 	content/common/npobject_util.cc \
 	content/common/page_zoom.cc \
+	content/common/partial_circular_buffer.cc \
 	content/common/pepper_renderer_instance_data.cc \
 	content/common/process_type.cc \
 	content/common/quota_dispatcher.cc \
@@ -193,7 +192,6 @@
 
 MY_DEFS := \
 	'-DCONTENT_IMPLEMENTATION' \
-	'-DUSE_SKIA' \
 	'-D_FILE_OFFSET_BITS=64' \
 	'-DUSE_LINUX_BREAKPAD' \
 	'-DNO_TCMALLOC' \
@@ -201,7 +199,6 @@
 	'-DCHROMIUM_BUILD' \
 	'-DUSE_LIBJPEG_TURBO=1' \
 	'-DUSE_PROPRIETARY_CODECS' \
-	'-DENABLE_PEPPER_THREADING' \
 	'-DENABLE_GPU=1' \
 	'-DUSE_OPENSSL=1' \
 	'-DENABLE_EGLIMAGE=1' \
@@ -231,9 +228,10 @@
 
 # Include paths placed before CFLAGS/CPPFLAGS
 LOCAL_C_INCLUDES := \
+	$(LOCAL_PATH) \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
 	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
 	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
-	$(LOCAL_PATH) \
 	$(LOCAL_PATH)/third_party/khronos \
 	$(LOCAL_PATH)/gpu \
 	$(LOCAL_PATH)/skia/config \
@@ -244,6 +242,7 @@
 	$(LOCAL_PATH)/third_party/skia/include/pdf \
 	$(LOCAL_PATH)/third_party/skia/include/gpu \
 	$(LOCAL_PATH)/third_party/skia/include/gpu/gl \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
 	$(LOCAL_PATH)/third_party/skia/include/pipe \
 	$(LOCAL_PATH)/third_party/skia/include/ports \
 	$(LOCAL_PATH)/third_party/skia/include/utils \
@@ -255,7 +254,6 @@
 	$(LOCAL_PATH)/third_party/npapi/bindings \
 	$(LOCAL_PATH)/third_party/WebKit/Source/Platform/chromium \
 	$(LOCAL_PATH)/third_party/WebKit/Source/Platform/chromium \
-	$(gyp_shared_intermediate_dir)/webcore_headers \
 	$(LOCAL_PATH)/v8/include \
 	$(gyp_shared_intermediate_dir)/ui/gl \
 	$(LOCAL_PATH)/third_party/mesa/MesaLib/include \
@@ -290,13 +288,14 @@
 	-Wl,--no-undefined \
 	-Wl,--exclude-libs=ALL \
 	-Wl,--icf=safe \
+	-Wl,--gc-sections \
 	-Wl,-O1 \
-	-Wl,--as-needed \
-	-Wl,--gc-sections
+	-Wl,--as-needed
 
 
 LOCAL_STATIC_LIBRARIES := \
 	skia_skia_gyp \
+	ui_ui_gyp \
 	ui_gl_gl_gyp \
 	webkit_support_glue_gyp
 
diff --git a/content/content_common.target.linux-x86.mk b/content/content_common.target.linux-x86.mk
index 5282915..452cf6d 100644
--- a/content/content_common.target.linux-x86.mk
+++ b/content/content_common.target.linux-x86.mk
@@ -13,6 +13,7 @@
 GYP_TARGET_DEPENDENCIES := \
 	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_gyp)/skia_skia_gyp.a \
 	$(call intermediates-dir-for,GYP,third_party_icu_icuuc_gyp)/icuuc.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_ui_gyp)/ui_ui_gyp.a \
 	$(call intermediates-dir-for,GYP,content_content_resources_gyp)/content_resources.stamp \
 	$(call intermediates-dir-for,GYP,third_party_npapi_npapi_gyp)/npapi.stamp \
 	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_gl_gl_gyp)/ui_gl_gl_gyp.a \
@@ -58,9 +59,6 @@
 	content/common/android/common_jni_registrar.cc \
 	content/common/android/device_telephony_info.cc \
 	content/common/android/hash_set.cc \
-	content/common/android/scoped_java_surface.cc \
-	content/common/android/surface_texture_bridge.cc \
-	content/common/android/surface_texture_listener.cc \
 	content/common/android/surface_texture_peer.cc \
 	content/common/android/trace_event_binding.cc \
 	content/common/appcache/appcache_backend_proxy.cc \
@@ -85,6 +83,7 @@
 	content/common/fileapi/webfilesystem_impl.cc \
 	content/common/fileapi/webfilewriter_impl.cc \
 	content/common/find_match_rect_android.cc \
+	content/common/font_list.cc \
 	content/common/font_list_android.cc \
 	content/common/gamepad_seqlock.cc \
 	content/common/gamepad_user_gesture.cc \
@@ -106,7 +105,6 @@
 	content/common/gpu/stream_texture_manager_android.cc \
 	content/common/gpu/image_transport_surface.cc \
 	content/common/gpu/image_transport_surface_android.cc \
-	content/common/gpu/media/avc_config_record_builder.cc \
 	content/common/gpu/media/h264_bit_reader.cc \
 	content/common/gpu/media/h264_parser.cc \
 	content/common/gpu/media/gpu_video_decode_accelerator.cc \
@@ -132,6 +130,7 @@
 	content/common/npobject_stub.cc \
 	content/common/npobject_util.cc \
 	content/common/page_zoom.cc \
+	content/common/partial_circular_buffer.cc \
 	content/common/pepper_renderer_instance_data.cc \
 	content/common/process_type.cc \
 	content/common/quota_dispatcher.cc \
@@ -173,6 +172,7 @@
 	-march=pentium4 \
 	-msse2 \
 	-mfpmath=sse \
+	-fuse-ld=gold \
 	-ffunction-sections \
 	-funwind-tables \
 	-g \
@@ -194,7 +194,6 @@
 
 MY_DEFS := \
 	'-DCONTENT_IMPLEMENTATION' \
-	'-DUSE_SKIA' \
 	'-D_FILE_OFFSET_BITS=64' \
 	'-DUSE_LINUX_BREAKPAD' \
 	'-DNO_TCMALLOC' \
@@ -202,7 +201,6 @@
 	'-DCHROMIUM_BUILD' \
 	'-DUSE_LIBJPEG_TURBO=1' \
 	'-DUSE_PROPRIETARY_CODECS' \
-	'-DENABLE_PEPPER_THREADING' \
 	'-DENABLE_GPU=1' \
 	'-DUSE_OPENSSL=1' \
 	'-DENABLE_EGLIMAGE=1' \
@@ -231,9 +229,10 @@
 
 # Include paths placed before CFLAGS/CPPFLAGS
 LOCAL_C_INCLUDES := \
+	$(LOCAL_PATH) \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
 	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
 	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
-	$(LOCAL_PATH) \
 	$(LOCAL_PATH)/third_party/khronos \
 	$(LOCAL_PATH)/gpu \
 	$(LOCAL_PATH)/skia/config \
@@ -244,6 +243,7 @@
 	$(LOCAL_PATH)/third_party/skia/include/pdf \
 	$(LOCAL_PATH)/third_party/skia/include/gpu \
 	$(LOCAL_PATH)/third_party/skia/include/gpu/gl \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
 	$(LOCAL_PATH)/third_party/skia/include/pipe \
 	$(LOCAL_PATH)/third_party/skia/include/ports \
 	$(LOCAL_PATH)/third_party/skia/include/utils \
@@ -255,7 +255,6 @@
 	$(LOCAL_PATH)/third_party/npapi/bindings \
 	$(LOCAL_PATH)/third_party/WebKit/Source/Platform/chromium \
 	$(LOCAL_PATH)/third_party/WebKit/Source/Platform/chromium \
-	$(gyp_shared_intermediate_dir)/webcore_headers \
 	$(LOCAL_PATH)/v8/include \
 	$(gyp_shared_intermediate_dir)/ui/gl \
 	$(LOCAL_PATH)/third_party/mesa/MesaLib/include \
@@ -283,16 +282,18 @@
 	-Wl,-z,noexecstack \
 	-fPIC \
 	-m32 \
+	-fuse-ld=gold \
 	-nostdlib \
 	-Wl,--no-undefined \
 	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
 	-Wl,-O1 \
-	-Wl,--as-needed \
-	-Wl,--gc-sections
+	-Wl,--as-needed
 
 
 LOCAL_STATIC_LIBRARIES := \
 	skia_skia_gyp \
+	ui_ui_gyp \
 	ui_gl_gl_gyp \
 	webkit_support_glue_gyp
 
diff --git a/content/content_gpu.gypi b/content/content_gpu.gypi
index ec4f552..9be835e 100644
--- a/content/content_gpu.gypi
+++ b/content/content_gpu.gypi
@@ -12,9 +12,9 @@
   'sources': [
     'gpu/gpu_dx_diagnostics_win.cc',
     'gpu/gpu_info_collector_android.cc',
-    'gpu/gpu_info_collector_linux.cc',
     'gpu/gpu_info_collector_mac.mm',
     'gpu/gpu_info_collector_win.cc',
+    'gpu/gpu_info_collector_x11.cc',
     'gpu/gpu_info_collector.cc',
     'gpu/gpu_info_collector.h',
     'gpu/gpu_main.cc',
@@ -85,7 +85,7 @@
         '../third_party/amd/amd_videocard_info_win.cc',
       ],
     }],
-    ['OS=="linux"', {
+    ['OS=="linux" and use_x11==1', {
       'dependencies': [
         '../build/linux/system.gyp:libpci',
         '../third_party/libXNVCtrl/libXNVCtrl.gyp:libXNVCtrl',
diff --git a/content/content_gpu.target.darwin-arm.mk b/content/content_gpu.target.darwin-arm.mk
new file mode 100644
index 0000000..aecbc53
--- /dev/null
+++ b/content/content_gpu.target.darwin-arm.mk
@@ -0,0 +1,183 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := content_content_gpu_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_gyp)/skia_skia_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_gl_gl_gyp)/ui_gl_gl_gyp.a
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	content/gpu/gpu_info_collector_android.cc \
+	content/gpu/gpu_info_collector.cc \
+	content/gpu/gpu_main.cc \
+	content/gpu/gpu_process.cc \
+	content/gpu/gpu_child_thread.cc \
+	content/gpu/gpu_watchdog_thread.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-fno-tree-sra \
+	-fuse-ld=gold \
+	-Wno-psabi \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections
+
+MY_CFLAGS_C :=
+
+MY_DEFS := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DUSE_LINUX_BREAKPAD' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_GPU=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DENABLE_LANGUAGE_DETECTION=1' \
+	'-DSK_BUILD_NO_IMAGE_ENCODE' \
+	'-DSK_DEFERRED_CANVAS_USES_GPIPE=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DGR_AGGRESSIVE_SHADER_OPTS=1' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_BUILD_FOR_ANDROID_NDK' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+LOCAL_CFLAGS := $(MY_CFLAGS_C) $(MY_CFLAGS) $(MY_DEFS)
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES := \
+	$(LOCAL_PATH) \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/config \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/gpu/gl \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(LOCAL_PATH)/third_party/re2 \
+	$(gyp_shared_intermediate_dir)/ui/gl \
+	$(LOCAL_PATH)/third_party/mesa/MesaLib/include \
+	$(GYP_ABS_ANDROID_TOP_DIR)/frameworks/wilhelm/include \
+	$(GYP_ABS_ANDROID_TOP_DIR)/bionic \
+	$(GYP_ABS_ANDROID_TOP_DIR)/external/stlport/stlport
+
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES)
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-abi \
+	-Wno-error=c++0x-compat \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+### Rules for final target.
+
+LOCAL_LDFLAGS := \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-Wl,-z,relro \
+	-Wl,-z,now \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--icf=safe \
+	-Wl,--gc-sections \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_STATIC_LIBRARIES := \
+	skia_skia_gyp \
+	ui_gl_gl_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_content_gpu_gyp
+
+# Alias gyp target name.
+.PHONY: content_gpu
+content_gpu: content_content_gpu_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/content/content_gpu.target.darwin-x86.mk b/content/content_gpu.target.darwin-x86.mk
new file mode 100644
index 0000000..02ea638
--- /dev/null
+++ b/content/content_gpu.target.darwin-x86.mk
@@ -0,0 +1,182 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := content_content_gpu_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_gyp)/skia_skia_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_gl_gl_gyp)/ui_gl_gl_gyp.a
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	content/gpu/gpu_info_collector_android.cc \
+	content/gpu/gpu_info_collector.cc \
+	content/gpu/gpu_main.cc \
+	content/gpu/gpu_process.cc \
+	content/gpu/gpu_child_thread.cc \
+	content/gpu/gpu_watchdog_thread.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS := \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-m32 \
+	-mmmx \
+	-march=pentium4 \
+	-msse2 \
+	-mfpmath=sse \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-fno-stack-protector \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections
+
+MY_CFLAGS_C :=
+
+MY_DEFS := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DUSE_LINUX_BREAKPAD' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_GPU=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DENABLE_LANGUAGE_DETECTION=1' \
+	'-DSK_BUILD_NO_IMAGE_ENCODE' \
+	'-DSK_DEFERRED_CANVAS_USES_GPIPE=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DGR_AGGRESSIVE_SHADER_OPTS=1' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_BUILD_FOR_ANDROID_NDK' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+LOCAL_CFLAGS := $(MY_CFLAGS_C) $(MY_CFLAGS) $(MY_DEFS)
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES := \
+	$(LOCAL_PATH) \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/config \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/gpu/gl \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(LOCAL_PATH)/third_party/re2 \
+	$(gyp_shared_intermediate_dir)/ui/gl \
+	$(LOCAL_PATH)/third_party/mesa/MesaLib/include \
+	$(GYP_ABS_ANDROID_TOP_DIR)/frameworks/wilhelm/include \
+	$(GYP_ABS_ANDROID_TOP_DIR)/bionic \
+	$(GYP_ABS_ANDROID_TOP_DIR)/external/stlport/stlport
+
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES)
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-error=c++0x-compat \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+### Rules for final target.
+
+LOCAL_LDFLAGS := \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m32 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_STATIC_LIBRARIES := \
+	skia_skia_gyp \
+	ui_gl_gl_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_content_gpu_gyp
+
+# Alias gyp target name.
+.PHONY: content_gpu
+content_gpu: content_content_gpu_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/content/content_gpu.target.linux-arm.mk b/content/content_gpu.target.linux-arm.mk
index e26b69a..aecbc53 100644
--- a/content/content_gpu.target.linux-arm.mk
+++ b/content/content_gpu.target.linux-arm.mk
@@ -70,7 +70,6 @@
 
 MY_DEFS := \
 	'-DCONTENT_IMPLEMENTATION' \
-	'-DUSE_SKIA' \
 	'-D_FILE_OFFSET_BITS=64' \
 	'-DUSE_LINUX_BREAKPAD' \
 	'-DNO_TCMALLOC' \
@@ -78,7 +77,6 @@
 	'-DCHROMIUM_BUILD' \
 	'-DUSE_LIBJPEG_TURBO=1' \
 	'-DUSE_PROPRIETARY_CODECS' \
-	'-DENABLE_PEPPER_THREADING' \
 	'-DENABLE_GPU=1' \
 	'-DUSE_OPENSSL=1' \
 	'-DENABLE_EGLIMAGE=1' \
@@ -105,9 +103,10 @@
 
 # Include paths placed before CFLAGS/CPPFLAGS
 LOCAL_C_INCLUDES := \
+	$(LOCAL_PATH) \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
 	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
 	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
-	$(LOCAL_PATH) \
 	$(LOCAL_PATH)/third_party/khronos \
 	$(LOCAL_PATH)/gpu \
 	$(LOCAL_PATH)/skia/config \
@@ -118,6 +117,7 @@
 	$(LOCAL_PATH)/third_party/skia/include/pdf \
 	$(LOCAL_PATH)/third_party/skia/include/gpu \
 	$(LOCAL_PATH)/third_party/skia/include/gpu/gl \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
 	$(LOCAL_PATH)/third_party/skia/include/pipe \
 	$(LOCAL_PATH)/third_party/skia/include/ports \
 	$(LOCAL_PATH)/third_party/skia/include/utils \
@@ -156,9 +156,9 @@
 	-Wl,--no-undefined \
 	-Wl,--exclude-libs=ALL \
 	-Wl,--icf=safe \
+	-Wl,--gc-sections \
 	-Wl,-O1 \
-	-Wl,--as-needed \
-	-Wl,--gc-sections
+	-Wl,--as-needed
 
 
 LOCAL_STATIC_LIBRARIES := \
diff --git a/content/content_gpu.target.linux-x86.mk b/content/content_gpu.target.linux-x86.mk
index 827b7b8..02ea638 100644
--- a/content/content_gpu.target.linux-x86.mk
+++ b/content/content_gpu.target.linux-x86.mk
@@ -50,6 +50,7 @@
 	-march=pentium4 \
 	-msse2 \
 	-mfpmath=sse \
+	-fuse-ld=gold \
 	-ffunction-sections \
 	-funwind-tables \
 	-g \
@@ -71,7 +72,6 @@
 
 MY_DEFS := \
 	'-DCONTENT_IMPLEMENTATION' \
-	'-DUSE_SKIA' \
 	'-D_FILE_OFFSET_BITS=64' \
 	'-DUSE_LINUX_BREAKPAD' \
 	'-DNO_TCMALLOC' \
@@ -79,7 +79,6 @@
 	'-DCHROMIUM_BUILD' \
 	'-DUSE_LIBJPEG_TURBO=1' \
 	'-DUSE_PROPRIETARY_CODECS' \
-	'-DENABLE_PEPPER_THREADING' \
 	'-DENABLE_GPU=1' \
 	'-DUSE_OPENSSL=1' \
 	'-DENABLE_EGLIMAGE=1' \
@@ -106,9 +105,10 @@
 
 # Include paths placed before CFLAGS/CPPFLAGS
 LOCAL_C_INCLUDES := \
+	$(LOCAL_PATH) \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
 	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
 	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
-	$(LOCAL_PATH) \
 	$(LOCAL_PATH)/third_party/khronos \
 	$(LOCAL_PATH)/gpu \
 	$(LOCAL_PATH)/skia/config \
@@ -119,6 +119,7 @@
 	$(LOCAL_PATH)/third_party/skia/include/pdf \
 	$(LOCAL_PATH)/third_party/skia/include/gpu \
 	$(LOCAL_PATH)/third_party/skia/include/gpu/gl \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
 	$(LOCAL_PATH)/third_party/skia/include/pipe \
 	$(LOCAL_PATH)/third_party/skia/include/ports \
 	$(LOCAL_PATH)/third_party/skia/include/utils \
@@ -150,12 +151,13 @@
 	-Wl,-z,noexecstack \
 	-fPIC \
 	-m32 \
+	-fuse-ld=gold \
 	-nostdlib \
 	-Wl,--no-undefined \
 	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
 	-Wl,-O1 \
-	-Wl,--as-needed \
-	-Wl,--gc-sections
+	-Wl,--as-needed
 
 
 LOCAL_STATIC_LIBRARIES := \
diff --git a/content/content_jni.gypi b/content/content_jni.gypi
index 784428a..7dac8ee 100644
--- a/content/content_jni.gypi
+++ b/content/content_jni.gypi
@@ -18,19 +18,19 @@
     'public/android/java/src/org/chromium/content/browser/ContentViewCore.java',
     'public/android/java/src/org/chromium/content/browser/ContentViewRenderView.java',
     'public/android/java/src/org/chromium/content/browser/ContentViewStatics.java',
-    'public/android/java/src/org/chromium/content/browser/DateTimeChooserAndroid.java',
-    'public/android/java/src/org/chromium/content/browser/DeviceOrientation.java',
+    'public/android/java/src/org/chromium/content/browser/DeviceMotionAndOrientation.java',
     'public/android/java/src/org/chromium/content/browser/DownloadController.java',
-    'public/android/java/src/org/chromium/content/browser/ImeAdapter.java',
+    'public/android/java/src/org/chromium/content/browser/input/ImeAdapter.java',
+    'public/android/java/src/org/chromium/content/browser/input/DateTimeChooserAndroid.java',
     'public/android/java/src/org/chromium/content/browser/InterstitialPageDelegateAndroid.java',
     'public/android/java/src/org/chromium/content/browser/LoadUrlParams.java',
     'public/android/java/src/org/chromium/content/browser/LocationProvider.java',
+    'public/android/java/src/org/chromium/content/browser/MediaResourceGetter.java',
     'public/android/java/src/org/chromium/content/browser/TouchPoint.java',
     'public/android/java/src/org/chromium/content/browser/TracingIntentHandler.java',
     'public/android/java/src/org/chromium/content/browser/WebContentsObserverAndroid.java',
     'public/android/java/src/org/chromium/content/common/CommandLine.java',
     'public/android/java/src/org/chromium/content/common/DeviceTelephonyInfo.java',
-    'public/android/java/src/org/chromium/content/common/SurfaceTextureListener.java',
     'public/android/java/src/org/chromium/content/common/TraceEvent.java',
    ],
   'variables': {
diff --git a/content/content_jni_headers.target.darwin-arm.mk b/content/content_jni_headers.target.darwin-arm.mk
new file mode 100644
index 0000000..71a1b8e
--- /dev/null
+++ b/content/content_jni_headers.target.darwin-arm.mk
@@ -0,0 +1,420 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := content_content_jni_headers_gyp
+LOCAL_MODULE_STEM := content_jni_headers
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,content_java_set_jni_headers_gyp)/java_set_jni_headers.stamp
+
+
+### Generated for rule "content_content_gyp_content_jni_headers_target_generate_jni_headers":
+# "{'inputs': ['../base/android/jni_generator/jni_generator.py'], 'process_outputs_as_sources': '1', 'extension': 'java', 'outputs': ['$(gyp_shared_intermediate_dir)/content/jni/%(INPUT_ROOT)s_jni.h'], 'rule_name': 'generate_jni_headers', 'rule_sources': ['public/android/java/src/org/chromium/content/app/ChildProcessService.java', 'public/android/java/src/org/chromium/content/app/ContentMain.java', 'public/android/java/src/org/chromium/content/app/LibraryLoader.java', 'public/android/java/src/org/chromium/content/browser/AndroidBrowserProcess.java', 'public/android/java/src/org/chromium/content/browser/ChildProcessLauncher.java', 'public/android/java/src/org/chromium/content/browser/ContentSettings.java', 'public/android/java/src/org/chromium/content/browser/ContentVideoView.java', 'public/android/java/src/org/chromium/content/browser/ContentViewCore.java', 'public/android/java/src/org/chromium/content/browser/ContentViewRenderView.java', 'public/android/java/src/org/chromium/content/browser/ContentViewStatics.java', 'public/android/java/src/org/chromium/content/browser/DeviceMotionAndOrientation.java', 'public/android/java/src/org/chromium/content/browser/DownloadController.java', 'public/android/java/src/org/chromium/content/browser/input/ImeAdapter.java', 'public/android/java/src/org/chromium/content/browser/input/DateTimeChooserAndroid.java', 'public/android/java/src/org/chromium/content/browser/InterstitialPageDelegateAndroid.java', 'public/android/java/src/org/chromium/content/browser/LoadUrlParams.java', 'public/android/java/src/org/chromium/content/browser/LocationProvider.java', 'public/android/java/src/org/chromium/content/browser/MediaResourceGetter.java', 'public/android/java/src/org/chromium/content/browser/TouchPoint.java', 'public/android/java/src/org/chromium/content/browser/TracingIntentHandler.java', 'public/android/java/src/org/chromium/content/browser/WebContentsObserverAndroid.java', 'public/android/java/src/org/chromium/content/common/CommandLine.java', 'public/android/java/src/org/chromium/content/common/DeviceTelephonyInfo.java', 'public/android/java/src/org/chromium/content/common/TraceEvent.java'], 'action': ['../base/android/jni_generator/jni_generator.py', '--input_file', '$(RULE_SOURCES)', '--output_dir', '$(gyp_shared_intermediate_dir)/content/jni', '--optimize_generation', '0'], 'message': 'Generating JNI bindings from $(RULE_SOURCES)'}":
+$(gyp_shared_intermediate_dir)/content/jni/ChildProcessService_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/ChildProcessService_jni.h: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/ChildProcessService_jni.h: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/ChildProcessService_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/ChildProcessService_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/app/ChildProcessService.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/app/ChildProcessService.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --optimize_generation 0
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/ChildProcessService_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/ContentMain_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/ContentMain_jni.h: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/ContentMain_jni.h: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/ContentMain_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/ContentMain_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/app/ContentMain.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/app/ContentMain.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --optimize_generation 0
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/ContentMain_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/LibraryLoader_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/LibraryLoader_jni.h: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/LibraryLoader_jni.h: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/LibraryLoader_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/LibraryLoader_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/app/LibraryLoader.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/app/LibraryLoader.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --optimize_generation 0
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/LibraryLoader_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/AndroidBrowserProcess_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/AndroidBrowserProcess_jni.h: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/AndroidBrowserProcess_jni.h: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/AndroidBrowserProcess_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/AndroidBrowserProcess_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/AndroidBrowserProcess.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/AndroidBrowserProcess.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --optimize_generation 0
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/AndroidBrowserProcess_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/ChildProcessLauncher_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/ChildProcessLauncher_jni.h: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/ChildProcessLauncher_jni.h: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/ChildProcessLauncher_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/ChildProcessLauncher_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/ChildProcessLauncher.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/ChildProcessLauncher.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --optimize_generation 0
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/ChildProcessLauncher_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/ContentSettings_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/ContentSettings_jni.h: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/ContentSettings_jni.h: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/ContentSettings_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/ContentSettings_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/ContentSettings.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/ContentSettings.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --optimize_generation 0
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/ContentSettings_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/ContentVideoView_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/ContentVideoView_jni.h: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/ContentVideoView_jni.h: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/ContentVideoView_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/ContentVideoView_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/ContentVideoView.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/ContentVideoView.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --optimize_generation 0
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/ContentVideoView_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/ContentViewCore_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/ContentViewCore_jni.h: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/ContentViewCore_jni.h: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/ContentViewCore_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/ContentViewCore_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/ContentViewCore.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --optimize_generation 0
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/ContentViewCore_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/ContentViewRenderView_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/ContentViewRenderView_jni.h: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/ContentViewRenderView_jni.h: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/ContentViewRenderView_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/ContentViewRenderView_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/ContentViewRenderView.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/ContentViewRenderView.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --optimize_generation 0
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/ContentViewRenderView_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/ContentViewStatics_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/ContentViewStatics_jni.h: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/ContentViewStatics_jni.h: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/ContentViewStatics_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/ContentViewStatics_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/ContentViewStatics.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/ContentViewStatics.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --optimize_generation 0
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/ContentViewStatics_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/DeviceMotionAndOrientation_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/DeviceMotionAndOrientation_jni.h: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/DeviceMotionAndOrientation_jni.h: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/DeviceMotionAndOrientation_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/DeviceMotionAndOrientation_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/DeviceMotionAndOrientation.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/DeviceMotionAndOrientation.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --optimize_generation 0
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/DeviceMotionAndOrientation_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/DownloadController_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/DownloadController_jni.h: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/DownloadController_jni.h: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/DownloadController_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/DownloadController_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/DownloadController.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/DownloadController.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --optimize_generation 0
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/DownloadController_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/ImeAdapter_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/ImeAdapter_jni.h: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/ImeAdapter_jni.h: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/ImeAdapter_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/ImeAdapter_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/input/ImeAdapter.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/input/ImeAdapter.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --optimize_generation 0
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/ImeAdapter_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/DateTimeChooserAndroid_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/DateTimeChooserAndroid_jni.h: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/DateTimeChooserAndroid_jni.h: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/DateTimeChooserAndroid_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/DateTimeChooserAndroid_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/input/DateTimeChooserAndroid.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/input/DateTimeChooserAndroid.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --optimize_generation 0
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/DateTimeChooserAndroid_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/InterstitialPageDelegateAndroid_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/InterstitialPageDelegateAndroid_jni.h: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/InterstitialPageDelegateAndroid_jni.h: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/InterstitialPageDelegateAndroid_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/InterstitialPageDelegateAndroid_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/InterstitialPageDelegateAndroid.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/InterstitialPageDelegateAndroid.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --optimize_generation 0
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/InterstitialPageDelegateAndroid_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/LoadUrlParams_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/LoadUrlParams_jni.h: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/LoadUrlParams_jni.h: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/LoadUrlParams_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/LoadUrlParams_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/LoadUrlParams.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/LoadUrlParams.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --optimize_generation 0
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/LoadUrlParams_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/LocationProvider_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/LocationProvider_jni.h: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/LocationProvider_jni.h: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/LocationProvider_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/LocationProvider_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/LocationProvider.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/LocationProvider.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --optimize_generation 0
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/LocationProvider_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/MediaResourceGetter_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/MediaResourceGetter_jni.h: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/MediaResourceGetter_jni.h: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/MediaResourceGetter_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/MediaResourceGetter_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/MediaResourceGetter.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/MediaResourceGetter.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --optimize_generation 0
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/MediaResourceGetter_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/TouchPoint_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/TouchPoint_jni.h: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/TouchPoint_jni.h: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/TouchPoint_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/TouchPoint_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/TouchPoint.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/TouchPoint.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --optimize_generation 0
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/TouchPoint_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/TracingIntentHandler_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/TracingIntentHandler_jni.h: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/TracingIntentHandler_jni.h: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/TracingIntentHandler_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/TracingIntentHandler_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/TracingIntentHandler.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/TracingIntentHandler.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --optimize_generation 0
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/TracingIntentHandler_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/WebContentsObserverAndroid_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/WebContentsObserverAndroid_jni.h: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/WebContentsObserverAndroid_jni.h: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/WebContentsObserverAndroid_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/WebContentsObserverAndroid_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/WebContentsObserverAndroid.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/WebContentsObserverAndroid.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --optimize_generation 0
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/WebContentsObserverAndroid_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/CommandLine_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/CommandLine_jni.h: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/CommandLine_jni.h: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/CommandLine_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/CommandLine_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/common/CommandLine.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/common/CommandLine.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --optimize_generation 0
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/CommandLine_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/DeviceTelephonyInfo_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/DeviceTelephonyInfo_jni.h: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/DeviceTelephonyInfo_jni.h: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/DeviceTelephonyInfo_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/DeviceTelephonyInfo_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/common/DeviceTelephonyInfo.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/common/DeviceTelephonyInfo.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --optimize_generation 0
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/DeviceTelephonyInfo_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/TraceEvent_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/TraceEvent_jni.h: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/TraceEvent_jni.h: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/TraceEvent_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/TraceEvent_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/common/TraceEvent.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/common/TraceEvent.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --optimize_generation 0
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/TraceEvent_jni.h
+
+### Finished generating for all rules
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/content/jni/ChildProcessService_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/ContentMain_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/LibraryLoader_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/AndroidBrowserProcess_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/ChildProcessLauncher_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/ContentSettings_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/ContentVideoView_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/ContentViewCore_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/ContentViewRenderView_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/ContentViewStatics_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/DeviceMotionAndOrientation_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/DownloadController_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/ImeAdapter_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/DateTimeChooserAndroid_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/InterstitialPageDelegateAndroid_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/LoadUrlParams_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/LocationProvider_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/MediaResourceGetter_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/TouchPoint_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/TracingIntentHandler_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/WebContentsObserverAndroid_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/CommandLine_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/DeviceTelephonyInfo_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/TraceEvent_jni.h
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES := \
+	$(gyp_shared_intermediate_dir)/content/jni/ChildProcessService_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/ContentMain_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/LibraryLoader_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/AndroidBrowserProcess_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/ChildProcessLauncher_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/ContentSettings_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/ContentVideoView_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/ContentViewCore_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/ContentViewRenderView_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/ContentViewStatics_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/DeviceMotionAndOrientation_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/DownloadController_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/ImeAdapter_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/DateTimeChooserAndroid_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/InterstitialPageDelegateAndroid_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/LoadUrlParams_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/LocationProvider_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/MediaResourceGetter_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/TouchPoint_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/TracingIntentHandler_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/WebContentsObserverAndroid_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/CommandLine_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/DeviceTelephonyInfo_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/TraceEvent_jni.h \
+	content_content_jni_headers_gyp_rule_trigger
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-fno-tree-sra \
+	-fuse-ld=gold \
+	-Wno-psabi \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections
+
+MY_CFLAGS_C :=
+
+MY_DEFS := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DUSE_LINUX_BREAKPAD' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_GPU=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DENABLE_LANGUAGE_DETECTION=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+LOCAL_CFLAGS := $(MY_CFLAGS_C) $(MY_CFLAGS) $(MY_DEFS)
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES := \
+	$(GYP_ABS_ANDROID_TOP_DIR)/frameworks/wilhelm/include \
+	$(GYP_ABS_ANDROID_TOP_DIR)/bionic \
+	$(GYP_ABS_ANDROID_TOP_DIR)/external/stlport/stlport
+
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES)
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-abi \
+	-Wno-error=c++0x-compat \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_content_jni_headers_gyp
+
+# Alias gyp target name.
+.PHONY: content_jni_headers
+content_jni_headers: content_content_jni_headers_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/content/content_jni_headers.target.darwin-x86.mk b/content/content_jni_headers.target.darwin-x86.mk
new file mode 100644
index 0000000..5ef7a75
--- /dev/null
+++ b/content/content_jni_headers.target.darwin-x86.mk
@@ -0,0 +1,421 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := content_content_jni_headers_gyp
+LOCAL_MODULE_STEM := content_jni_headers
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,content_java_set_jni_headers_gyp)/java_set_jni_headers.stamp
+
+
+### Generated for rule "content_content_gyp_content_jni_headers_target_generate_jni_headers":
+# "{'inputs': ['../base/android/jni_generator/jni_generator.py'], 'process_outputs_as_sources': '1', 'extension': 'java', 'outputs': ['$(gyp_shared_intermediate_dir)/content/jni/%(INPUT_ROOT)s_jni.h'], 'rule_name': 'generate_jni_headers', 'rule_sources': ['public/android/java/src/org/chromium/content/app/ChildProcessService.java', 'public/android/java/src/org/chromium/content/app/ContentMain.java', 'public/android/java/src/org/chromium/content/app/LibraryLoader.java', 'public/android/java/src/org/chromium/content/browser/AndroidBrowserProcess.java', 'public/android/java/src/org/chromium/content/browser/ChildProcessLauncher.java', 'public/android/java/src/org/chromium/content/browser/ContentSettings.java', 'public/android/java/src/org/chromium/content/browser/ContentVideoView.java', 'public/android/java/src/org/chromium/content/browser/ContentViewCore.java', 'public/android/java/src/org/chromium/content/browser/ContentViewRenderView.java', 'public/android/java/src/org/chromium/content/browser/ContentViewStatics.java', 'public/android/java/src/org/chromium/content/browser/DeviceMotionAndOrientation.java', 'public/android/java/src/org/chromium/content/browser/DownloadController.java', 'public/android/java/src/org/chromium/content/browser/input/ImeAdapter.java', 'public/android/java/src/org/chromium/content/browser/input/DateTimeChooserAndroid.java', 'public/android/java/src/org/chromium/content/browser/InterstitialPageDelegateAndroid.java', 'public/android/java/src/org/chromium/content/browser/LoadUrlParams.java', 'public/android/java/src/org/chromium/content/browser/LocationProvider.java', 'public/android/java/src/org/chromium/content/browser/MediaResourceGetter.java', 'public/android/java/src/org/chromium/content/browser/TouchPoint.java', 'public/android/java/src/org/chromium/content/browser/TracingIntentHandler.java', 'public/android/java/src/org/chromium/content/browser/WebContentsObserverAndroid.java', 'public/android/java/src/org/chromium/content/common/CommandLine.java', 'public/android/java/src/org/chromium/content/common/DeviceTelephonyInfo.java', 'public/android/java/src/org/chromium/content/common/TraceEvent.java'], 'action': ['../base/android/jni_generator/jni_generator.py', '--input_file', '$(RULE_SOURCES)', '--output_dir', '$(gyp_shared_intermediate_dir)/content/jni', '--optimize_generation', '0'], 'message': 'Generating JNI bindings from $(RULE_SOURCES)'}":
+$(gyp_shared_intermediate_dir)/content/jni/ChildProcessService_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/ChildProcessService_jni.h: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/ChildProcessService_jni.h: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/ChildProcessService_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/ChildProcessService_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/app/ChildProcessService.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/app/ChildProcessService.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --optimize_generation 0
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/ChildProcessService_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/ContentMain_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/ContentMain_jni.h: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/ContentMain_jni.h: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/ContentMain_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/ContentMain_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/app/ContentMain.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/app/ContentMain.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --optimize_generation 0
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/ContentMain_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/LibraryLoader_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/LibraryLoader_jni.h: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/LibraryLoader_jni.h: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/LibraryLoader_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/LibraryLoader_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/app/LibraryLoader.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/app/LibraryLoader.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --optimize_generation 0
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/LibraryLoader_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/AndroidBrowserProcess_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/AndroidBrowserProcess_jni.h: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/AndroidBrowserProcess_jni.h: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/AndroidBrowserProcess_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/AndroidBrowserProcess_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/AndroidBrowserProcess.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/AndroidBrowserProcess.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --optimize_generation 0
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/AndroidBrowserProcess_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/ChildProcessLauncher_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/ChildProcessLauncher_jni.h: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/ChildProcessLauncher_jni.h: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/ChildProcessLauncher_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/ChildProcessLauncher_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/ChildProcessLauncher.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/ChildProcessLauncher.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --optimize_generation 0
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/ChildProcessLauncher_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/ContentSettings_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/ContentSettings_jni.h: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/ContentSettings_jni.h: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/ContentSettings_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/ContentSettings_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/ContentSettings.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/ContentSettings.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --optimize_generation 0
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/ContentSettings_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/ContentVideoView_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/ContentVideoView_jni.h: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/ContentVideoView_jni.h: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/ContentVideoView_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/ContentVideoView_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/ContentVideoView.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/ContentVideoView.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --optimize_generation 0
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/ContentVideoView_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/ContentViewCore_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/ContentViewCore_jni.h: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/ContentViewCore_jni.h: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/ContentViewCore_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/ContentViewCore_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/ContentViewCore.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --optimize_generation 0
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/ContentViewCore_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/ContentViewRenderView_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/ContentViewRenderView_jni.h: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/ContentViewRenderView_jni.h: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/ContentViewRenderView_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/ContentViewRenderView_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/ContentViewRenderView.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/ContentViewRenderView.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --optimize_generation 0
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/ContentViewRenderView_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/ContentViewStatics_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/ContentViewStatics_jni.h: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/ContentViewStatics_jni.h: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/ContentViewStatics_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/ContentViewStatics_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/ContentViewStatics.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/ContentViewStatics.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --optimize_generation 0
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/ContentViewStatics_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/DeviceMotionAndOrientation_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/DeviceMotionAndOrientation_jni.h: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/DeviceMotionAndOrientation_jni.h: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/DeviceMotionAndOrientation_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/DeviceMotionAndOrientation_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/DeviceMotionAndOrientation.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/DeviceMotionAndOrientation.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --optimize_generation 0
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/DeviceMotionAndOrientation_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/DownloadController_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/DownloadController_jni.h: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/DownloadController_jni.h: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/DownloadController_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/DownloadController_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/DownloadController.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/DownloadController.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --optimize_generation 0
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/DownloadController_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/ImeAdapter_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/ImeAdapter_jni.h: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/ImeAdapter_jni.h: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/ImeAdapter_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/ImeAdapter_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/input/ImeAdapter.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/input/ImeAdapter.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --optimize_generation 0
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/ImeAdapter_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/DateTimeChooserAndroid_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/DateTimeChooserAndroid_jni.h: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/DateTimeChooserAndroid_jni.h: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/DateTimeChooserAndroid_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/DateTimeChooserAndroid_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/input/DateTimeChooserAndroid.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/input/DateTimeChooserAndroid.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --optimize_generation 0
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/DateTimeChooserAndroid_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/InterstitialPageDelegateAndroid_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/InterstitialPageDelegateAndroid_jni.h: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/InterstitialPageDelegateAndroid_jni.h: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/InterstitialPageDelegateAndroid_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/InterstitialPageDelegateAndroid_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/InterstitialPageDelegateAndroid.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/InterstitialPageDelegateAndroid.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --optimize_generation 0
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/InterstitialPageDelegateAndroid_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/LoadUrlParams_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/LoadUrlParams_jni.h: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/LoadUrlParams_jni.h: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/LoadUrlParams_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/LoadUrlParams_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/LoadUrlParams.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/LoadUrlParams.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --optimize_generation 0
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/LoadUrlParams_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/LocationProvider_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/LocationProvider_jni.h: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/LocationProvider_jni.h: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/LocationProvider_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/LocationProvider_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/LocationProvider.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/LocationProvider.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --optimize_generation 0
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/LocationProvider_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/MediaResourceGetter_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/MediaResourceGetter_jni.h: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/MediaResourceGetter_jni.h: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/MediaResourceGetter_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/MediaResourceGetter_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/MediaResourceGetter.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/MediaResourceGetter.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --optimize_generation 0
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/MediaResourceGetter_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/TouchPoint_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/TouchPoint_jni.h: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/TouchPoint_jni.h: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/TouchPoint_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/TouchPoint_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/TouchPoint.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/TouchPoint.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --optimize_generation 0
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/TouchPoint_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/TracingIntentHandler_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/TracingIntentHandler_jni.h: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/TracingIntentHandler_jni.h: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/TracingIntentHandler_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/TracingIntentHandler_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/TracingIntentHandler.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/TracingIntentHandler.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --optimize_generation 0
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/TracingIntentHandler_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/WebContentsObserverAndroid_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/WebContentsObserverAndroid_jni.h: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/WebContentsObserverAndroid_jni.h: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/WebContentsObserverAndroid_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/WebContentsObserverAndroid_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/WebContentsObserverAndroid.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/WebContentsObserverAndroid.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --optimize_generation 0
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/WebContentsObserverAndroid_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/CommandLine_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/CommandLine_jni.h: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/CommandLine_jni.h: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/CommandLine_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/CommandLine_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/common/CommandLine.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/common/CommandLine.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --optimize_generation 0
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/CommandLine_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/DeviceTelephonyInfo_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/DeviceTelephonyInfo_jni.h: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/DeviceTelephonyInfo_jni.h: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/DeviceTelephonyInfo_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/DeviceTelephonyInfo_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/common/DeviceTelephonyInfo.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/common/DeviceTelephonyInfo.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --optimize_generation 0
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/DeviceTelephonyInfo_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/TraceEvent_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/TraceEvent_jni.h: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/TraceEvent_jni.h: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/TraceEvent_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/TraceEvent_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/common/TraceEvent.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/common/TraceEvent.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --optimize_generation 0
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/TraceEvent_jni.h
+
+### Finished generating for all rules
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/content/jni/ChildProcessService_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/ContentMain_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/LibraryLoader_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/AndroidBrowserProcess_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/ChildProcessLauncher_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/ContentSettings_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/ContentVideoView_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/ContentViewCore_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/ContentViewRenderView_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/ContentViewStatics_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/DeviceMotionAndOrientation_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/DownloadController_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/ImeAdapter_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/DateTimeChooserAndroid_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/InterstitialPageDelegateAndroid_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/LoadUrlParams_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/LocationProvider_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/MediaResourceGetter_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/TouchPoint_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/TracingIntentHandler_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/WebContentsObserverAndroid_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/CommandLine_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/DeviceTelephonyInfo_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/TraceEvent_jni.h
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES := \
+	$(gyp_shared_intermediate_dir)/content/jni/ChildProcessService_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/ContentMain_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/LibraryLoader_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/AndroidBrowserProcess_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/ChildProcessLauncher_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/ContentSettings_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/ContentVideoView_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/ContentViewCore_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/ContentViewRenderView_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/ContentViewStatics_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/DeviceMotionAndOrientation_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/DownloadController_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/ImeAdapter_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/DateTimeChooserAndroid_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/InterstitialPageDelegateAndroid_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/LoadUrlParams_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/LocationProvider_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/MediaResourceGetter_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/TouchPoint_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/TracingIntentHandler_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/WebContentsObserverAndroid_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/CommandLine_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/DeviceTelephonyInfo_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/TraceEvent_jni.h \
+	content_content_jni_headers_gyp_rule_trigger
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS := \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-m32 \
+	-mmmx \
+	-march=pentium4 \
+	-msse2 \
+	-mfpmath=sse \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-fno-stack-protector \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections
+
+MY_CFLAGS_C :=
+
+MY_DEFS := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DUSE_LINUX_BREAKPAD' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_GPU=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DENABLE_LANGUAGE_DETECTION=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+LOCAL_CFLAGS := $(MY_CFLAGS_C) $(MY_CFLAGS) $(MY_DEFS)
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES := \
+	$(GYP_ABS_ANDROID_TOP_DIR)/frameworks/wilhelm/include \
+	$(GYP_ABS_ANDROID_TOP_DIR)/bionic \
+	$(GYP_ABS_ANDROID_TOP_DIR)/external/stlport/stlport
+
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES)
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-error=c++0x-compat \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_content_jni_headers_gyp
+
+# Alias gyp target name.
+.PHONY: content_jni_headers
+content_jni_headers: content_content_jni_headers_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/content/content_jni_headers.target.linux-arm.mk b/content/content_jni_headers.target.linux-arm.mk
index 178b89f..71a1b8e 100644
--- a/content/content_jni_headers.target.linux-arm.mk
+++ b/content/content_jni_headers.target.linux-arm.mk
@@ -12,13 +12,11 @@
 
 # Make sure our deps are built first.
 GYP_TARGET_DEPENDENCIES := \
-	$(call intermediates-dir-for,GYP,content_java_set_jni_headers_gyp)/java_set_jni_headers.stamp \
-	$(call intermediates-dir-for,GYP,content_surface_texture_jni_headers_gyp)/surface_texture_jni_headers.stamp \
-	$(call intermediates-dir-for,GYP,content_surface_jni_headers_gyp)/surface_jni_headers.stamp
+	$(call intermediates-dir-for,GYP,content_java_set_jni_headers_gyp)/java_set_jni_headers.stamp
 
 
 ### Generated for rule "content_content_gyp_content_jni_headers_target_generate_jni_headers":
-# "{'inputs': ['../base/android/jni_generator/jni_generator.py'], 'process_outputs_as_sources': '1', 'extension': 'java', 'outputs': ['$(gyp_shared_intermediate_dir)/content/jni/%(INPUT_ROOT)s_jni.h'], 'rule_name': 'generate_jni_headers', 'rule_sources': ['public/android/java/src/org/chromium/content/app/ChildProcessService.java', 'public/android/java/src/org/chromium/content/app/ContentMain.java', 'public/android/java/src/org/chromium/content/app/LibraryLoader.java', 'public/android/java/src/org/chromium/content/browser/AndroidBrowserProcess.java', 'public/android/java/src/org/chromium/content/browser/ChildProcessLauncher.java', 'public/android/java/src/org/chromium/content/browser/ContentSettings.java', 'public/android/java/src/org/chromium/content/browser/ContentVideoView.java', 'public/android/java/src/org/chromium/content/browser/ContentViewCore.java', 'public/android/java/src/org/chromium/content/browser/ContentViewRenderView.java', 'public/android/java/src/org/chromium/content/browser/ContentViewStatics.java', 'public/android/java/src/org/chromium/content/browser/DateTimeChooserAndroid.java', 'public/android/java/src/org/chromium/content/browser/DeviceOrientation.java', 'public/android/java/src/org/chromium/content/browser/DownloadController.java', 'public/android/java/src/org/chromium/content/browser/ImeAdapter.java', 'public/android/java/src/org/chromium/content/browser/InterstitialPageDelegateAndroid.java', 'public/android/java/src/org/chromium/content/browser/LoadUrlParams.java', 'public/android/java/src/org/chromium/content/browser/LocationProvider.java', 'public/android/java/src/org/chromium/content/browser/TouchPoint.java', 'public/android/java/src/org/chromium/content/browser/TracingIntentHandler.java', 'public/android/java/src/org/chromium/content/browser/WebContentsObserverAndroid.java', 'public/android/java/src/org/chromium/content/common/CommandLine.java', 'public/android/java/src/org/chromium/content/common/DeviceTelephonyInfo.java', 'public/android/java/src/org/chromium/content/common/SurfaceTextureListener.java', 'public/android/java/src/org/chromium/content/common/TraceEvent.java'], 'action': ['../base/android/jni_generator/jni_generator.py', '--input_file', '$(RULE_SOURCES)', '--output_dir', '$(gyp_shared_intermediate_dir)/content/jni', '--optimize_generation', '0'], 'message': 'Generating JNI bindings from $(RULE_SOURCES)'}":
+# "{'inputs': ['../base/android/jni_generator/jni_generator.py'], 'process_outputs_as_sources': '1', 'extension': 'java', 'outputs': ['$(gyp_shared_intermediate_dir)/content/jni/%(INPUT_ROOT)s_jni.h'], 'rule_name': 'generate_jni_headers', 'rule_sources': ['public/android/java/src/org/chromium/content/app/ChildProcessService.java', 'public/android/java/src/org/chromium/content/app/ContentMain.java', 'public/android/java/src/org/chromium/content/app/LibraryLoader.java', 'public/android/java/src/org/chromium/content/browser/AndroidBrowserProcess.java', 'public/android/java/src/org/chromium/content/browser/ChildProcessLauncher.java', 'public/android/java/src/org/chromium/content/browser/ContentSettings.java', 'public/android/java/src/org/chromium/content/browser/ContentVideoView.java', 'public/android/java/src/org/chromium/content/browser/ContentViewCore.java', 'public/android/java/src/org/chromium/content/browser/ContentViewRenderView.java', 'public/android/java/src/org/chromium/content/browser/ContentViewStatics.java', 'public/android/java/src/org/chromium/content/browser/DeviceMotionAndOrientation.java', 'public/android/java/src/org/chromium/content/browser/DownloadController.java', 'public/android/java/src/org/chromium/content/browser/input/ImeAdapter.java', 'public/android/java/src/org/chromium/content/browser/input/DateTimeChooserAndroid.java', 'public/android/java/src/org/chromium/content/browser/InterstitialPageDelegateAndroid.java', 'public/android/java/src/org/chromium/content/browser/LoadUrlParams.java', 'public/android/java/src/org/chromium/content/browser/LocationProvider.java', 'public/android/java/src/org/chromium/content/browser/MediaResourceGetter.java', 'public/android/java/src/org/chromium/content/browser/TouchPoint.java', 'public/android/java/src/org/chromium/content/browser/TracingIntentHandler.java', 'public/android/java/src/org/chromium/content/browser/WebContentsObserverAndroid.java', 'public/android/java/src/org/chromium/content/common/CommandLine.java', 'public/android/java/src/org/chromium/content/common/DeviceTelephonyInfo.java', 'public/android/java/src/org/chromium/content/common/TraceEvent.java'], 'action': ['../base/android/jni_generator/jni_generator.py', '--input_file', '$(RULE_SOURCES)', '--output_dir', '$(gyp_shared_intermediate_dir)/content/jni', '--optimize_generation', '0'], 'message': 'Generating JNI bindings from $(RULE_SOURCES)'}":
 $(gyp_shared_intermediate_dir)/content/jni/ChildProcessService_jni.h: gyp_local_path := $(LOCAL_PATH)
 $(gyp_shared_intermediate_dir)/content/jni/ChildProcessService_jni.h: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
 $(gyp_shared_intermediate_dir)/content/jni/ChildProcessService_jni.h: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
@@ -119,25 +117,15 @@
 .PHONY: content_content_jni_headers_gyp_rule_trigger
 content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/ContentViewStatics_jni.h
 
-$(gyp_shared_intermediate_dir)/content/jni/DateTimeChooserAndroid_jni.h: gyp_local_path := $(LOCAL_PATH)
-$(gyp_shared_intermediate_dir)/content/jni/DateTimeChooserAndroid_jni.h: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
-$(gyp_shared_intermediate_dir)/content/jni/DateTimeChooserAndroid_jni.h: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
-$(gyp_shared_intermediate_dir)/content/jni/DateTimeChooserAndroid_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
-$(gyp_shared_intermediate_dir)/content/jni/DateTimeChooserAndroid_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/DateTimeChooserAndroid.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(GYP_TARGET_DEPENDENCIES)
-	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/DateTimeChooserAndroid.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --optimize_generation 0
+$(gyp_shared_intermediate_dir)/content/jni/DeviceMotionAndOrientation_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/DeviceMotionAndOrientation_jni.h: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/DeviceMotionAndOrientation_jni.h: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/DeviceMotionAndOrientation_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/DeviceMotionAndOrientation_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/DeviceMotionAndOrientation.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/DeviceMotionAndOrientation.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --optimize_generation 0
 
 .PHONY: content_content_jni_headers_gyp_rule_trigger
-content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/DateTimeChooserAndroid_jni.h
-
-$(gyp_shared_intermediate_dir)/content/jni/DeviceOrientation_jni.h: gyp_local_path := $(LOCAL_PATH)
-$(gyp_shared_intermediate_dir)/content/jni/DeviceOrientation_jni.h: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
-$(gyp_shared_intermediate_dir)/content/jni/DeviceOrientation_jni.h: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
-$(gyp_shared_intermediate_dir)/content/jni/DeviceOrientation_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
-$(gyp_shared_intermediate_dir)/content/jni/DeviceOrientation_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/DeviceOrientation.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(GYP_TARGET_DEPENDENCIES)
-	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/DeviceOrientation.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --optimize_generation 0
-
-.PHONY: content_content_jni_headers_gyp_rule_trigger
-content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/DeviceOrientation_jni.h
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/DeviceMotionAndOrientation_jni.h
 
 $(gyp_shared_intermediate_dir)/content/jni/DownloadController_jni.h: gyp_local_path := $(LOCAL_PATH)
 $(gyp_shared_intermediate_dir)/content/jni/DownloadController_jni.h: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
@@ -153,12 +141,22 @@
 $(gyp_shared_intermediate_dir)/content/jni/ImeAdapter_jni.h: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
 $(gyp_shared_intermediate_dir)/content/jni/ImeAdapter_jni.h: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
 $(gyp_shared_intermediate_dir)/content/jni/ImeAdapter_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
-$(gyp_shared_intermediate_dir)/content/jni/ImeAdapter_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/ImeAdapter.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(GYP_TARGET_DEPENDENCIES)
-	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/ImeAdapter.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --optimize_generation 0
+$(gyp_shared_intermediate_dir)/content/jni/ImeAdapter_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/input/ImeAdapter.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/input/ImeAdapter.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --optimize_generation 0
 
 .PHONY: content_content_jni_headers_gyp_rule_trigger
 content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/ImeAdapter_jni.h
 
+$(gyp_shared_intermediate_dir)/content/jni/DateTimeChooserAndroid_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/DateTimeChooserAndroid_jni.h: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/DateTimeChooserAndroid_jni.h: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/DateTimeChooserAndroid_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/DateTimeChooserAndroid_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/input/DateTimeChooserAndroid.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/input/DateTimeChooserAndroid.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --optimize_generation 0
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/DateTimeChooserAndroid_jni.h
+
 $(gyp_shared_intermediate_dir)/content/jni/InterstitialPageDelegateAndroid_jni.h: gyp_local_path := $(LOCAL_PATH)
 $(gyp_shared_intermediate_dir)/content/jni/InterstitialPageDelegateAndroid_jni.h: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
 $(gyp_shared_intermediate_dir)/content/jni/InterstitialPageDelegateAndroid_jni.h: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
@@ -189,6 +187,16 @@
 .PHONY: content_content_jni_headers_gyp_rule_trigger
 content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/LocationProvider_jni.h
 
+$(gyp_shared_intermediate_dir)/content/jni/MediaResourceGetter_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/MediaResourceGetter_jni.h: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/MediaResourceGetter_jni.h: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/MediaResourceGetter_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/MediaResourceGetter_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/MediaResourceGetter.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/MediaResourceGetter.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --optimize_generation 0
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/MediaResourceGetter_jni.h
+
 $(gyp_shared_intermediate_dir)/content/jni/TouchPoint_jni.h: gyp_local_path := $(LOCAL_PATH)
 $(gyp_shared_intermediate_dir)/content/jni/TouchPoint_jni.h: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
 $(gyp_shared_intermediate_dir)/content/jni/TouchPoint_jni.h: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
@@ -239,16 +247,6 @@
 .PHONY: content_content_jni_headers_gyp_rule_trigger
 content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/DeviceTelephonyInfo_jni.h
 
-$(gyp_shared_intermediate_dir)/content/jni/SurfaceTextureListener_jni.h: gyp_local_path := $(LOCAL_PATH)
-$(gyp_shared_intermediate_dir)/content/jni/SurfaceTextureListener_jni.h: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
-$(gyp_shared_intermediate_dir)/content/jni/SurfaceTextureListener_jni.h: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
-$(gyp_shared_intermediate_dir)/content/jni/SurfaceTextureListener_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
-$(gyp_shared_intermediate_dir)/content/jni/SurfaceTextureListener_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/common/SurfaceTextureListener.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(GYP_TARGET_DEPENDENCIES)
-	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/common/SurfaceTextureListener.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --optimize_generation 0
-
-.PHONY: content_content_jni_headers_gyp_rule_trigger
-content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/SurfaceTextureListener_jni.h
-
 $(gyp_shared_intermediate_dir)/content/jni/TraceEvent_jni.h: gyp_local_path := $(LOCAL_PATH)
 $(gyp_shared_intermediate_dir)/content/jni/TraceEvent_jni.h: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
 $(gyp_shared_intermediate_dir)/content/jni/TraceEvent_jni.h: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
@@ -272,19 +270,19 @@
 	$(gyp_shared_intermediate_dir)/content/jni/ContentViewCore_jni.h \
 	$(gyp_shared_intermediate_dir)/content/jni/ContentViewRenderView_jni.h \
 	$(gyp_shared_intermediate_dir)/content/jni/ContentViewStatics_jni.h \
-	$(gyp_shared_intermediate_dir)/content/jni/DateTimeChooserAndroid_jni.h \
-	$(gyp_shared_intermediate_dir)/content/jni/DeviceOrientation_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/DeviceMotionAndOrientation_jni.h \
 	$(gyp_shared_intermediate_dir)/content/jni/DownloadController_jni.h \
 	$(gyp_shared_intermediate_dir)/content/jni/ImeAdapter_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/DateTimeChooserAndroid_jni.h \
 	$(gyp_shared_intermediate_dir)/content/jni/InterstitialPageDelegateAndroid_jni.h \
 	$(gyp_shared_intermediate_dir)/content/jni/LoadUrlParams_jni.h \
 	$(gyp_shared_intermediate_dir)/content/jni/LocationProvider_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/MediaResourceGetter_jni.h \
 	$(gyp_shared_intermediate_dir)/content/jni/TouchPoint_jni.h \
 	$(gyp_shared_intermediate_dir)/content/jni/TracingIntentHandler_jni.h \
 	$(gyp_shared_intermediate_dir)/content/jni/WebContentsObserverAndroid_jni.h \
 	$(gyp_shared_intermediate_dir)/content/jni/CommandLine_jni.h \
 	$(gyp_shared_intermediate_dir)/content/jni/DeviceTelephonyInfo_jni.h \
-	$(gyp_shared_intermediate_dir)/content/jni/SurfaceTextureListener_jni.h \
 	$(gyp_shared_intermediate_dir)/content/jni/TraceEvent_jni.h
 
 # Make sure our deps and generated files are built first.
@@ -301,19 +299,19 @@
 	$(gyp_shared_intermediate_dir)/content/jni/ContentViewCore_jni.h \
 	$(gyp_shared_intermediate_dir)/content/jni/ContentViewRenderView_jni.h \
 	$(gyp_shared_intermediate_dir)/content/jni/ContentViewStatics_jni.h \
-	$(gyp_shared_intermediate_dir)/content/jni/DateTimeChooserAndroid_jni.h \
-	$(gyp_shared_intermediate_dir)/content/jni/DeviceOrientation_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/DeviceMotionAndOrientation_jni.h \
 	$(gyp_shared_intermediate_dir)/content/jni/DownloadController_jni.h \
 	$(gyp_shared_intermediate_dir)/content/jni/ImeAdapter_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/DateTimeChooserAndroid_jni.h \
 	$(gyp_shared_intermediate_dir)/content/jni/InterstitialPageDelegateAndroid_jni.h \
 	$(gyp_shared_intermediate_dir)/content/jni/LoadUrlParams_jni.h \
 	$(gyp_shared_intermediate_dir)/content/jni/LocationProvider_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/MediaResourceGetter_jni.h \
 	$(gyp_shared_intermediate_dir)/content/jni/TouchPoint_jni.h \
 	$(gyp_shared_intermediate_dir)/content/jni/TracingIntentHandler_jni.h \
 	$(gyp_shared_intermediate_dir)/content/jni/WebContentsObserverAndroid_jni.h \
 	$(gyp_shared_intermediate_dir)/content/jni/CommandLine_jni.h \
 	$(gyp_shared_intermediate_dir)/content/jni/DeviceTelephonyInfo_jni.h \
-	$(gyp_shared_intermediate_dir)/content/jni/SurfaceTextureListener_jni.h \
 	$(gyp_shared_intermediate_dir)/content/jni/TraceEvent_jni.h \
 	content_content_jni_headers_gyp_rule_trigger
 
@@ -359,7 +357,6 @@
 
 MY_DEFS := \
 	'-DCONTENT_IMPLEMENTATION' \
-	'-DUSE_SKIA' \
 	'-D_FILE_OFFSET_BITS=64' \
 	'-DUSE_LINUX_BREAKPAD' \
 	'-DNO_TCMALLOC' \
@@ -367,7 +364,6 @@
 	'-DCHROMIUM_BUILD' \
 	'-DUSE_LIBJPEG_TURBO=1' \
 	'-DUSE_PROPRIETARY_CODECS' \
-	'-DENABLE_PEPPER_THREADING' \
 	'-DENABLE_GPU=1' \
 	'-DUSE_OPENSSL=1' \
 	'-DENABLE_EGLIMAGE=1' \
diff --git a/content/content_jni_headers.target.linux-x86.mk b/content/content_jni_headers.target.linux-x86.mk
index b73f5e9..5ef7a75 100644
--- a/content/content_jni_headers.target.linux-x86.mk
+++ b/content/content_jni_headers.target.linux-x86.mk
@@ -12,13 +12,11 @@
 
 # Make sure our deps are built first.
 GYP_TARGET_DEPENDENCIES := \
-	$(call intermediates-dir-for,GYP,content_java_set_jni_headers_gyp)/java_set_jni_headers.stamp \
-	$(call intermediates-dir-for,GYP,content_surface_texture_jni_headers_gyp)/surface_texture_jni_headers.stamp \
-	$(call intermediates-dir-for,GYP,content_surface_jni_headers_gyp)/surface_jni_headers.stamp
+	$(call intermediates-dir-for,GYP,content_java_set_jni_headers_gyp)/java_set_jni_headers.stamp
 
 
 ### Generated for rule "content_content_gyp_content_jni_headers_target_generate_jni_headers":
-# "{'inputs': ['../base/android/jni_generator/jni_generator.py'], 'process_outputs_as_sources': '1', 'extension': 'java', 'outputs': ['$(gyp_shared_intermediate_dir)/content/jni/%(INPUT_ROOT)s_jni.h'], 'rule_name': 'generate_jni_headers', 'rule_sources': ['public/android/java/src/org/chromium/content/app/ChildProcessService.java', 'public/android/java/src/org/chromium/content/app/ContentMain.java', 'public/android/java/src/org/chromium/content/app/LibraryLoader.java', 'public/android/java/src/org/chromium/content/browser/AndroidBrowserProcess.java', 'public/android/java/src/org/chromium/content/browser/ChildProcessLauncher.java', 'public/android/java/src/org/chromium/content/browser/ContentSettings.java', 'public/android/java/src/org/chromium/content/browser/ContentVideoView.java', 'public/android/java/src/org/chromium/content/browser/ContentViewCore.java', 'public/android/java/src/org/chromium/content/browser/ContentViewRenderView.java', 'public/android/java/src/org/chromium/content/browser/ContentViewStatics.java', 'public/android/java/src/org/chromium/content/browser/DateTimeChooserAndroid.java', 'public/android/java/src/org/chromium/content/browser/DeviceOrientation.java', 'public/android/java/src/org/chromium/content/browser/DownloadController.java', 'public/android/java/src/org/chromium/content/browser/ImeAdapter.java', 'public/android/java/src/org/chromium/content/browser/InterstitialPageDelegateAndroid.java', 'public/android/java/src/org/chromium/content/browser/LoadUrlParams.java', 'public/android/java/src/org/chromium/content/browser/LocationProvider.java', 'public/android/java/src/org/chromium/content/browser/TouchPoint.java', 'public/android/java/src/org/chromium/content/browser/TracingIntentHandler.java', 'public/android/java/src/org/chromium/content/browser/WebContentsObserverAndroid.java', 'public/android/java/src/org/chromium/content/common/CommandLine.java', 'public/android/java/src/org/chromium/content/common/DeviceTelephonyInfo.java', 'public/android/java/src/org/chromium/content/common/SurfaceTextureListener.java', 'public/android/java/src/org/chromium/content/common/TraceEvent.java'], 'action': ['../base/android/jni_generator/jni_generator.py', '--input_file', '$(RULE_SOURCES)', '--output_dir', '$(gyp_shared_intermediate_dir)/content/jni', '--optimize_generation', '0'], 'message': 'Generating JNI bindings from $(RULE_SOURCES)'}":
+# "{'inputs': ['../base/android/jni_generator/jni_generator.py'], 'process_outputs_as_sources': '1', 'extension': 'java', 'outputs': ['$(gyp_shared_intermediate_dir)/content/jni/%(INPUT_ROOT)s_jni.h'], 'rule_name': 'generate_jni_headers', 'rule_sources': ['public/android/java/src/org/chromium/content/app/ChildProcessService.java', 'public/android/java/src/org/chromium/content/app/ContentMain.java', 'public/android/java/src/org/chromium/content/app/LibraryLoader.java', 'public/android/java/src/org/chromium/content/browser/AndroidBrowserProcess.java', 'public/android/java/src/org/chromium/content/browser/ChildProcessLauncher.java', 'public/android/java/src/org/chromium/content/browser/ContentSettings.java', 'public/android/java/src/org/chromium/content/browser/ContentVideoView.java', 'public/android/java/src/org/chromium/content/browser/ContentViewCore.java', 'public/android/java/src/org/chromium/content/browser/ContentViewRenderView.java', 'public/android/java/src/org/chromium/content/browser/ContentViewStatics.java', 'public/android/java/src/org/chromium/content/browser/DeviceMotionAndOrientation.java', 'public/android/java/src/org/chromium/content/browser/DownloadController.java', 'public/android/java/src/org/chromium/content/browser/input/ImeAdapter.java', 'public/android/java/src/org/chromium/content/browser/input/DateTimeChooserAndroid.java', 'public/android/java/src/org/chromium/content/browser/InterstitialPageDelegateAndroid.java', 'public/android/java/src/org/chromium/content/browser/LoadUrlParams.java', 'public/android/java/src/org/chromium/content/browser/LocationProvider.java', 'public/android/java/src/org/chromium/content/browser/MediaResourceGetter.java', 'public/android/java/src/org/chromium/content/browser/TouchPoint.java', 'public/android/java/src/org/chromium/content/browser/TracingIntentHandler.java', 'public/android/java/src/org/chromium/content/browser/WebContentsObserverAndroid.java', 'public/android/java/src/org/chromium/content/common/CommandLine.java', 'public/android/java/src/org/chromium/content/common/DeviceTelephonyInfo.java', 'public/android/java/src/org/chromium/content/common/TraceEvent.java'], 'action': ['../base/android/jni_generator/jni_generator.py', '--input_file', '$(RULE_SOURCES)', '--output_dir', '$(gyp_shared_intermediate_dir)/content/jni', '--optimize_generation', '0'], 'message': 'Generating JNI bindings from $(RULE_SOURCES)'}":
 $(gyp_shared_intermediate_dir)/content/jni/ChildProcessService_jni.h: gyp_local_path := $(LOCAL_PATH)
 $(gyp_shared_intermediate_dir)/content/jni/ChildProcessService_jni.h: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
 $(gyp_shared_intermediate_dir)/content/jni/ChildProcessService_jni.h: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
@@ -119,25 +117,15 @@
 .PHONY: content_content_jni_headers_gyp_rule_trigger
 content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/ContentViewStatics_jni.h
 
-$(gyp_shared_intermediate_dir)/content/jni/DateTimeChooserAndroid_jni.h: gyp_local_path := $(LOCAL_PATH)
-$(gyp_shared_intermediate_dir)/content/jni/DateTimeChooserAndroid_jni.h: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
-$(gyp_shared_intermediate_dir)/content/jni/DateTimeChooserAndroid_jni.h: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
-$(gyp_shared_intermediate_dir)/content/jni/DateTimeChooserAndroid_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
-$(gyp_shared_intermediate_dir)/content/jni/DateTimeChooserAndroid_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/DateTimeChooserAndroid.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(GYP_TARGET_DEPENDENCIES)
-	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/DateTimeChooserAndroid.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --optimize_generation 0
+$(gyp_shared_intermediate_dir)/content/jni/DeviceMotionAndOrientation_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/DeviceMotionAndOrientation_jni.h: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/DeviceMotionAndOrientation_jni.h: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/DeviceMotionAndOrientation_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/DeviceMotionAndOrientation_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/DeviceMotionAndOrientation.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/DeviceMotionAndOrientation.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --optimize_generation 0
 
 .PHONY: content_content_jni_headers_gyp_rule_trigger
-content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/DateTimeChooserAndroid_jni.h
-
-$(gyp_shared_intermediate_dir)/content/jni/DeviceOrientation_jni.h: gyp_local_path := $(LOCAL_PATH)
-$(gyp_shared_intermediate_dir)/content/jni/DeviceOrientation_jni.h: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
-$(gyp_shared_intermediate_dir)/content/jni/DeviceOrientation_jni.h: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
-$(gyp_shared_intermediate_dir)/content/jni/DeviceOrientation_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
-$(gyp_shared_intermediate_dir)/content/jni/DeviceOrientation_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/DeviceOrientation.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(GYP_TARGET_DEPENDENCIES)
-	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/DeviceOrientation.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --optimize_generation 0
-
-.PHONY: content_content_jni_headers_gyp_rule_trigger
-content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/DeviceOrientation_jni.h
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/DeviceMotionAndOrientation_jni.h
 
 $(gyp_shared_intermediate_dir)/content/jni/DownloadController_jni.h: gyp_local_path := $(LOCAL_PATH)
 $(gyp_shared_intermediate_dir)/content/jni/DownloadController_jni.h: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
@@ -153,12 +141,22 @@
 $(gyp_shared_intermediate_dir)/content/jni/ImeAdapter_jni.h: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
 $(gyp_shared_intermediate_dir)/content/jni/ImeAdapter_jni.h: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
 $(gyp_shared_intermediate_dir)/content/jni/ImeAdapter_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
-$(gyp_shared_intermediate_dir)/content/jni/ImeAdapter_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/ImeAdapter.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(GYP_TARGET_DEPENDENCIES)
-	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/ImeAdapter.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --optimize_generation 0
+$(gyp_shared_intermediate_dir)/content/jni/ImeAdapter_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/input/ImeAdapter.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/input/ImeAdapter.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --optimize_generation 0
 
 .PHONY: content_content_jni_headers_gyp_rule_trigger
 content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/ImeAdapter_jni.h
 
+$(gyp_shared_intermediate_dir)/content/jni/DateTimeChooserAndroid_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/DateTimeChooserAndroid_jni.h: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/DateTimeChooserAndroid_jni.h: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/DateTimeChooserAndroid_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/DateTimeChooserAndroid_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/input/DateTimeChooserAndroid.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/input/DateTimeChooserAndroid.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --optimize_generation 0
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/DateTimeChooserAndroid_jni.h
+
 $(gyp_shared_intermediate_dir)/content/jni/InterstitialPageDelegateAndroid_jni.h: gyp_local_path := $(LOCAL_PATH)
 $(gyp_shared_intermediate_dir)/content/jni/InterstitialPageDelegateAndroid_jni.h: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
 $(gyp_shared_intermediate_dir)/content/jni/InterstitialPageDelegateAndroid_jni.h: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
@@ -189,6 +187,16 @@
 .PHONY: content_content_jni_headers_gyp_rule_trigger
 content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/LocationProvider_jni.h
 
+$(gyp_shared_intermediate_dir)/content/jni/MediaResourceGetter_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/MediaResourceGetter_jni.h: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/MediaResourceGetter_jni.h: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/MediaResourceGetter_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/MediaResourceGetter_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/MediaResourceGetter.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/MediaResourceGetter.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --optimize_generation 0
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/MediaResourceGetter_jni.h
+
 $(gyp_shared_intermediate_dir)/content/jni/TouchPoint_jni.h: gyp_local_path := $(LOCAL_PATH)
 $(gyp_shared_intermediate_dir)/content/jni/TouchPoint_jni.h: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
 $(gyp_shared_intermediate_dir)/content/jni/TouchPoint_jni.h: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
@@ -239,16 +247,6 @@
 .PHONY: content_content_jni_headers_gyp_rule_trigger
 content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/DeviceTelephonyInfo_jni.h
 
-$(gyp_shared_intermediate_dir)/content/jni/SurfaceTextureListener_jni.h: gyp_local_path := $(LOCAL_PATH)
-$(gyp_shared_intermediate_dir)/content/jni/SurfaceTextureListener_jni.h: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
-$(gyp_shared_intermediate_dir)/content/jni/SurfaceTextureListener_jni.h: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
-$(gyp_shared_intermediate_dir)/content/jni/SurfaceTextureListener_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
-$(gyp_shared_intermediate_dir)/content/jni/SurfaceTextureListener_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/common/SurfaceTextureListener.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(GYP_TARGET_DEPENDENCIES)
-	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/common/SurfaceTextureListener.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --optimize_generation 0
-
-.PHONY: content_content_jni_headers_gyp_rule_trigger
-content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/SurfaceTextureListener_jni.h
-
 $(gyp_shared_intermediate_dir)/content/jni/TraceEvent_jni.h: gyp_local_path := $(LOCAL_PATH)
 $(gyp_shared_intermediate_dir)/content/jni/TraceEvent_jni.h: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
 $(gyp_shared_intermediate_dir)/content/jni/TraceEvent_jni.h: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
@@ -272,19 +270,19 @@
 	$(gyp_shared_intermediate_dir)/content/jni/ContentViewCore_jni.h \
 	$(gyp_shared_intermediate_dir)/content/jni/ContentViewRenderView_jni.h \
 	$(gyp_shared_intermediate_dir)/content/jni/ContentViewStatics_jni.h \
-	$(gyp_shared_intermediate_dir)/content/jni/DateTimeChooserAndroid_jni.h \
-	$(gyp_shared_intermediate_dir)/content/jni/DeviceOrientation_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/DeviceMotionAndOrientation_jni.h \
 	$(gyp_shared_intermediate_dir)/content/jni/DownloadController_jni.h \
 	$(gyp_shared_intermediate_dir)/content/jni/ImeAdapter_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/DateTimeChooserAndroid_jni.h \
 	$(gyp_shared_intermediate_dir)/content/jni/InterstitialPageDelegateAndroid_jni.h \
 	$(gyp_shared_intermediate_dir)/content/jni/LoadUrlParams_jni.h \
 	$(gyp_shared_intermediate_dir)/content/jni/LocationProvider_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/MediaResourceGetter_jni.h \
 	$(gyp_shared_intermediate_dir)/content/jni/TouchPoint_jni.h \
 	$(gyp_shared_intermediate_dir)/content/jni/TracingIntentHandler_jni.h \
 	$(gyp_shared_intermediate_dir)/content/jni/WebContentsObserverAndroid_jni.h \
 	$(gyp_shared_intermediate_dir)/content/jni/CommandLine_jni.h \
 	$(gyp_shared_intermediate_dir)/content/jni/DeviceTelephonyInfo_jni.h \
-	$(gyp_shared_intermediate_dir)/content/jni/SurfaceTextureListener_jni.h \
 	$(gyp_shared_intermediate_dir)/content/jni/TraceEvent_jni.h
 
 # Make sure our deps and generated files are built first.
@@ -301,19 +299,19 @@
 	$(gyp_shared_intermediate_dir)/content/jni/ContentViewCore_jni.h \
 	$(gyp_shared_intermediate_dir)/content/jni/ContentViewRenderView_jni.h \
 	$(gyp_shared_intermediate_dir)/content/jni/ContentViewStatics_jni.h \
-	$(gyp_shared_intermediate_dir)/content/jni/DateTimeChooserAndroid_jni.h \
-	$(gyp_shared_intermediate_dir)/content/jni/DeviceOrientation_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/DeviceMotionAndOrientation_jni.h \
 	$(gyp_shared_intermediate_dir)/content/jni/DownloadController_jni.h \
 	$(gyp_shared_intermediate_dir)/content/jni/ImeAdapter_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/DateTimeChooserAndroid_jni.h \
 	$(gyp_shared_intermediate_dir)/content/jni/InterstitialPageDelegateAndroid_jni.h \
 	$(gyp_shared_intermediate_dir)/content/jni/LoadUrlParams_jni.h \
 	$(gyp_shared_intermediate_dir)/content/jni/LocationProvider_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/MediaResourceGetter_jni.h \
 	$(gyp_shared_intermediate_dir)/content/jni/TouchPoint_jni.h \
 	$(gyp_shared_intermediate_dir)/content/jni/TracingIntentHandler_jni.h \
 	$(gyp_shared_intermediate_dir)/content/jni/WebContentsObserverAndroid_jni.h \
 	$(gyp_shared_intermediate_dir)/content/jni/CommandLine_jni.h \
 	$(gyp_shared_intermediate_dir)/content/jni/DeviceTelephonyInfo_jni.h \
-	$(gyp_shared_intermediate_dir)/content/jni/SurfaceTextureListener_jni.h \
 	$(gyp_shared_intermediate_dir)/content/jni/TraceEvent_jni.h \
 	content_content_jni_headers_gyp_rule_trigger
 
@@ -339,6 +337,7 @@
 	-march=pentium4 \
 	-msse2 \
 	-mfpmath=sse \
+	-fuse-ld=gold \
 	-ffunction-sections \
 	-funwind-tables \
 	-g \
@@ -360,7 +359,6 @@
 
 MY_DEFS := \
 	'-DCONTENT_IMPLEMENTATION' \
-	'-DUSE_SKIA' \
 	'-D_FILE_OFFSET_BITS=64' \
 	'-DUSE_LINUX_BREAKPAD' \
 	'-DNO_TCMALLOC' \
@@ -368,7 +366,6 @@
 	'-DCHROMIUM_BUILD' \
 	'-DUSE_LIBJPEG_TURBO=1' \
 	'-DUSE_PROPRIETARY_CODECS' \
-	'-DENABLE_PEPPER_THREADING' \
 	'-DENABLE_GPU=1' \
 	'-DUSE_OPENSSL=1' \
 	'-DENABLE_EGLIMAGE=1' \
diff --git a/content/content_plugin.target.darwin-arm.mk b/content/content_plugin.target.darwin-arm.mk
new file mode 100644
index 0000000..b5f541c
--- /dev/null
+++ b/content/content_plugin.target.darwin-arm.mk
@@ -0,0 +1,56 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := content_content_plugin_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+### Rules for final target.
+
+LOCAL_LDFLAGS := \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-Wl,-z,relro \
+	-Wl,-z,now \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--icf=safe \
+	-Wl,--gc-sections \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_content_plugin_gyp
+
+# Alias gyp target name.
+.PHONY: content_plugin
+content_plugin: content_content_plugin_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/content/content_plugin.target.darwin-x86.mk b/content/content_plugin.target.darwin-x86.mk
new file mode 100644
index 0000000..ce304bd
--- /dev/null
+++ b/content/content_plugin.target.darwin-x86.mk
@@ -0,0 +1,54 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := content_content_plugin_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+### Rules for final target.
+
+LOCAL_LDFLAGS := \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m32 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_content_plugin_gyp
+
+# Alias gyp target name.
+.PHONY: content_plugin
+content_plugin: content_content_plugin_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/content/content_plugin.target.linux-arm.mk b/content/content_plugin.target.linux-arm.mk
index 6c8773c..b5f541c 100644
--- a/content/content_plugin.target.linux-arm.mk
+++ b/content/content_plugin.target.linux-arm.mk
@@ -31,9 +31,9 @@
 	-Wl,--no-undefined \
 	-Wl,--exclude-libs=ALL \
 	-Wl,--icf=safe \
+	-Wl,--gc-sections \
 	-Wl,-O1 \
-	-Wl,--as-needed \
-	-Wl,--gc-sections
+	-Wl,--as-needed
 
 
 LOCAL_STATIC_LIBRARIES :=
diff --git a/content/content_plugin.target.linux-x86.mk b/content/content_plugin.target.linux-x86.mk
index 01de08b..ce304bd 100644
--- a/content/content_plugin.target.linux-x86.mk
+++ b/content/content_plugin.target.linux-x86.mk
@@ -25,12 +25,13 @@
 	-Wl,-z,noexecstack \
 	-fPIC \
 	-m32 \
+	-fuse-ld=gold \
 	-nostdlib \
 	-Wl,--no-undefined \
 	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
 	-Wl,-O1 \
-	-Wl,--as-needed \
-	-Wl,--gc-sections
+	-Wl,--as-needed
 
 
 LOCAL_STATIC_LIBRARIES :=
diff --git a/content/content_ppapi_plugin.target.darwin-arm.mk b/content/content_ppapi_plugin.target.darwin-arm.mk
new file mode 100644
index 0000000..bb45175
--- /dev/null
+++ b/content/content_ppapi_plugin.target.darwin-arm.mk
@@ -0,0 +1,56 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := content_content_ppapi_plugin_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+### Rules for final target.
+
+LOCAL_LDFLAGS := \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-Wl,-z,relro \
+	-Wl,-z,now \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--icf=safe \
+	-Wl,--gc-sections \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_content_ppapi_plugin_gyp
+
+# Alias gyp target name.
+.PHONY: content_ppapi_plugin
+content_ppapi_plugin: content_content_ppapi_plugin_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/content/content_ppapi_plugin.target.darwin-x86.mk b/content/content_ppapi_plugin.target.darwin-x86.mk
new file mode 100644
index 0000000..b639ccf
--- /dev/null
+++ b/content/content_ppapi_plugin.target.darwin-x86.mk
@@ -0,0 +1,54 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := content_content_ppapi_plugin_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+### Rules for final target.
+
+LOCAL_LDFLAGS := \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m32 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_content_ppapi_plugin_gyp
+
+# Alias gyp target name.
+.PHONY: content_ppapi_plugin
+content_ppapi_plugin: content_content_ppapi_plugin_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/content/content_ppapi_plugin.target.linux-arm.mk b/content/content_ppapi_plugin.target.linux-arm.mk
index c996293..bb45175 100644
--- a/content/content_ppapi_plugin.target.linux-arm.mk
+++ b/content/content_ppapi_plugin.target.linux-arm.mk
@@ -31,9 +31,9 @@
 	-Wl,--no-undefined \
 	-Wl,--exclude-libs=ALL \
 	-Wl,--icf=safe \
+	-Wl,--gc-sections \
 	-Wl,-O1 \
-	-Wl,--as-needed \
-	-Wl,--gc-sections
+	-Wl,--as-needed
 
 
 LOCAL_STATIC_LIBRARIES :=
diff --git a/content/content_ppapi_plugin.target.linux-x86.mk b/content/content_ppapi_plugin.target.linux-x86.mk
index 7a40fe3..b639ccf 100644
--- a/content/content_ppapi_plugin.target.linux-x86.mk
+++ b/content/content_ppapi_plugin.target.linux-x86.mk
@@ -25,12 +25,13 @@
 	-Wl,-z,noexecstack \
 	-fPIC \
 	-m32 \
+	-fuse-ld=gold \
 	-nostdlib \
 	-Wl,--no-undefined \
 	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
 	-Wl,-O1 \
-	-Wl,--as-needed \
-	-Wl,--gc-sections
+	-Wl,--as-needed
 
 
 LOCAL_STATIC_LIBRARIES :=
diff --git a/content/content_renderer.gypi b/content/content_renderer.gypi
index 10edaad..0fb1bdb 100644
--- a/content/content_renderer.gypi
+++ b/content/content_renderer.gypi
@@ -27,6 +27,8 @@
   'sources': [
     'public/renderer/android_content_detection_prefixes.cc',
     'public/renderer/android_content_detection_prefixes.h',
+    'public/renderer/android/synchronous_compositor_client.h',
+    'public/renderer/android/synchronous_compositor.h',
     'public/renderer/content_renderer_client.cc',
     'public/renderer/content_renderer_client.h',
     'public/renderer/context_menu_client.h',
@@ -66,6 +68,8 @@
     'renderer/android/email_detector.h',
     'renderer/android/phone_number_detector.cc',
     'renderer/android/phone_number_detector.h',
+    'renderer/android/synchronous_compositor_output_surface.cc',
+    'renderer/android/synchronous_compositor_output_surface.h',
     'renderer/device_orientation_dispatcher.cc',
     'renderer/device_orientation_dispatcher.h',
     'renderer/devtools/devtools_agent.cc',
@@ -76,8 +80,6 @@
     'renderer/devtools/devtools_client.h',
     'renderer/disambiguation_popup_helper.cc',
     'renderer/disambiguation_popup_helper.h',
-    'renderer/do_not_track_bindings.cc',
-    'renderer/do_not_track_bindings.h',
     'renderer/dom_automation_controller.cc',
     'renderer/dom_automation_controller.h',
     'renderer/dom_storage/dom_storage_dispatcher.cc',
@@ -88,16 +90,14 @@
     'renderer/dom_storage/webstoragenamespace_impl.h',
     'renderer/external_popup_menu.cc',
     'renderer/external_popup_menu.h',
-    'renderer/favicon_helper.cc',
-    'renderer/favicon_helper.h',
     'renderer/gamepad_shared_memory_reader.cc',
     'renderer/gamepad_shared_memory_reader.h',
     'renderer/geolocation_dispatcher.cc',
     'renderer/geolocation_dispatcher.h',
     'renderer/gpu/compositor_output_surface.cc',
     'renderer/gpu/compositor_output_surface.h',
-    'renderer/gpu/compositor_software_output_device_gl_adapter.cc',
-    'renderer/gpu/compositor_software_output_device_gl_adapter.h',
+    'renderer/gpu/compositor_software_output_device.cc',
+    'renderer/gpu/compositor_software_output_device.h',
     'renderer/gpu/input_event_filter.cc',
     'renderer/gpu/input_event_filter.h',
     'renderer/gpu/input_handler_manager.cc',
@@ -114,8 +114,12 @@
     'renderer/hyphenator/hyphenator.h',
     'renderer/idle_user_detector.cc',
     'renderer/idle_user_detector.h',
+    'renderer/image_loading_helper.cc',
+    'renderer/image_loading_helper.h',
     'renderer/input_tag_speech_dispatcher.cc',
     'renderer/input_tag_speech_dispatcher.h',
+    'renderer/internal_document_state_data.cc',
+    'renderer/internal_document_state_data.h',
     'renderer/java/java_bridge_channel.cc',
     'renderer/java/java_bridge_channel.h',
     'renderer/java/java_bridge_dispatcher.cc',
@@ -130,8 +134,6 @@
     'renderer/media/audio_message_filter.h',
     'renderer/media/audio_renderer_mixer_manager.cc',
     'renderer/media/audio_renderer_mixer_manager.h',
-    'renderer/media/local_video_capture.cc',
-    'renderer/media/local_video_capture.h',
     'renderer/media/media_stream_center.h',
     'renderer/media/media_stream_dependency_factory.h',
     'renderer/media/media_stream_dispatcher.h',
@@ -141,8 +143,6 @@
     'renderer/media/pepper_platform_video_decoder_impl.h',
     'renderer/media/render_media_log.cc',
     'renderer/media/render_media_log.h',
-    'renderer/media/renderer_audio_output_device.cc',
-    'renderer/media/renderer_audio_output_device.h',
     'renderer/media/renderer_gpu_video_decoder_factories.cc',
     'renderer/media/renderer_gpu_video_decoder_factories.h',
     'renderer/media/renderer_webaudiodevice_impl.cc',
@@ -159,6 +159,10 @@
     'renderer/media/video_capture_message_filter.h',
     'renderer/media/webmediaplayer_proxy_impl_android.cc',
     'renderer/media/webmediaplayer_proxy_impl_android.h',
+    'renderer/media/webrtc_logging_handler_impl.cc',
+    'renderer/media/webrtc_logging_handler_impl.h',
+    'renderer/media/webrtc_logging_message_filter.cc',
+    'renderer/media/webrtc_logging_message_filter.h',
     'renderer/memory_benchmarking_extension.cc',
     'renderer/memory_benchmarking_extension.h',
     'renderer/mhtml_generator.cc',
@@ -172,6 +176,8 @@
     'renderer/password_form_conversion_utils.cc',
     'renderer/pepper/content_renderer_pepper_host_factory.cc',
     'renderer/pepper/content_renderer_pepper_host_factory.h',
+    'renderer/pepper/null_file_system_callback_dispatcher.cc',
+    'renderer/pepper/null_file_system_callback_dispatcher.h',
     'renderer/pepper/pepper_audio_input_host.cc',
     'renderer/pepper/pepper_audio_input_host.h',
     'renderer/pepper/pepper_broker_impl.cc',
@@ -180,12 +186,12 @@
     'renderer/pepper/pepper_device_enumeration_event_handler.h',
     'renderer/pepper/pepper_device_enumeration_host_helper.cc',
     'renderer/pepper/pepper_device_enumeration_host_helper.h',
-    'renderer/pepper/pepper_directory_reader_host.cc',
-    'renderer/pepper/pepper_directory_reader_host.h',
     'renderer/pepper/pepper_file_chooser_host.cc',
     'renderer/pepper/pepper_file_chooser_host.h',
     'renderer/pepper/pepper_file_io_host.cc',
     'renderer/pepper/pepper_file_io_host.h',
+    'renderer/pepper/pepper_file_system_host.cc',
+    'renderer/pepper/pepper_file_system_host.h',
     'renderer/pepper/pepper_graphics_2d_host.cc',
     'renderer/pepper/pepper_graphics_2d_host.h',
     'renderer/pepper/pepper_hung_plugin_filter.cc',
@@ -217,6 +223,10 @@
     'renderer/pepper/pepper_truetype_font_win.cc',
     'renderer/pepper/pepper_video_capture_host.cc',
     'renderer/pepper/pepper_video_capture_host.h',
+    'renderer/pepper/pepper_video_destination_host.cc',
+    'renderer/pepper/pepper_video_destination_host.h',
+    'renderer/pepper/pepper_video_source_host.cc',
+    'renderer/pepper/pepper_video_source_host.h',
     'renderer/pepper/pepper_websocket_host.cc',
     'renderer/pepper/pepper_websocket_host.h',
     'renderer/pepper/renderer_ppapi_host_impl.cc',
@@ -330,6 +340,9 @@
       'dependencies': [
         '../third_party/libphonenumber/libphonenumber.gyp:libphonenumber',
       ],
+      'includes': [
+        '../build/android/cpufeatures.gypi',
+      ],
     }],
     # TODO(jrg): remove the OS=="android" section?
     # http://crbug.com/113172
@@ -351,10 +364,15 @@
         'renderer/media/media_stream_dependency_factory.cc',
         'renderer/media/media_stream_dispatcher.cc',
         'renderer/media/media_stream_impl.cc',
+        'renderer/media/media_stream_registry_interface.h',
+        'renderer/media/media_stream_source_observer.cc',
+        'renderer/media/media_stream_source_observer.h',
         'renderer/media/peer_connection_handler_base.cc',
         'renderer/media/peer_connection_handler_base.h',
         'renderer/media/peer_connection_tracker.cc',
         'renderer/media/peer_connection_tracker.h',
+        'renderer/media/remote_media_stream_impl.cc',
+        'renderer/media/remote_media_stream_impl.h',
         'renderer/media/rtc_data_channel_handler.cc',
         'renderer/media/rtc_data_channel_handler.h',
         'renderer/media/rtc_dtmf_sender_handler.cc',
@@ -367,10 +385,16 @@
         'renderer/media/rtc_video_capture_delegate.h',
         'renderer/media/rtc_video_capturer.cc',
         'renderer/media/rtc_video_capturer.h',
+        'renderer/media/video_destination_handler.cc',
+        'renderer/media/video_destination_handler.h',
+        'renderer/media/video_source_handler.cc',
+        'renderer/media/video_source_handler.h',
         'renderer/media/webaudio_capturer_source.cc',
         'renderer/media/webaudio_capturer_source.h',
         'renderer/media/webrtc_audio_capturer.cc',
         'renderer/media/webrtc_audio_capturer.h',
+        'renderer/media/webrtc_audio_capturer_sink_owner.cc',
+        'renderer/media/webrtc_audio_capturer_sink_owner.h',
         'renderer/media/webrtc_audio_device_impl.cc',
         'renderer/media/webrtc_audio_device_impl.h',
         'renderer/media/webrtc_audio_device_not_impl.cc',
@@ -379,6 +403,8 @@
         'renderer/media/webrtc_audio_renderer.h',
         'renderer/media/webrtc_local_audio_renderer.cc',
         'renderer/media/webrtc_local_audio_renderer.h',
+        'renderer/media/webrtc_local_audio_track.cc',
+        'renderer/media/webrtc_local_audio_track.h',
         'renderer/p2p/host_address_request.cc',
         'renderer/p2p/host_address_request.h',
         'renderer/p2p/ipc_network_manager.cc',
diff --git a/content/content_renderer.target.darwin-arm.mk b/content/content_renderer.target.darwin-arm.mk
new file mode 100644
index 0000000..8755e4b
--- /dev/null
+++ b/content/content_renderer.target.darwin-arm.mk
@@ -0,0 +1,318 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := content_content_renderer_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,content_content_resources_gyp)/content_resources.stamp \
+	$(call intermediates-dir-for,GYP,jingle_jingle_glue_gyp)/jingle_glue.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_gyp)/skia_skia_gyp.a \
+	$(call intermediates-dir-for,GYP,third_party_icu_icuuc_gyp)/icuuc.stamp \
+	$(call intermediates-dir-for,GYP,third_party_icu_icui18n_gyp)/icui18n.stamp \
+	$(call intermediates-dir-for,GYP,third_party_npapi_npapi_gyp)/npapi.stamp \
+	$(call intermediates-dir-for,GYP,v8_tools_gyp_v8_gyp)/v8.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,webkit_support_glue_gyp)/webkit_support_glue_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_libphonenumber_libphonenumber_without_metadata_gyp)/third_party_libphonenumber_libphonenumber_without_metadata_gyp.a
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	content/public/renderer/android_content_detection_prefixes.cc \
+	content/public/renderer/content_renderer_client.cc \
+	content/public/renderer/document_state.cc \
+	content/public/renderer/navigation_state.cc \
+	content/public/renderer/render_process_observer.cc \
+	content/public/renderer/render_thread.cc \
+	content/public/renderer/render_view_observer.cc \
+	content/renderer/accessibility/accessibility_node_serializer.cc \
+	content/renderer/accessibility/renderer_accessibility.cc \
+	content/renderer/accessibility/renderer_accessibility_complete.cc \
+	content/renderer/accessibility/renderer_accessibility_focus_only.cc \
+	content/renderer/all_rendering_benchmarks.cc \
+	content/renderer/android/address_detector.cc \
+	content/renderer/android/content_detector.cc \
+	content/renderer/android/email_detector.cc \
+	content/renderer/android/phone_number_detector.cc \
+	content/renderer/android/synchronous_compositor_output_surface.cc \
+	content/renderer/device_orientation_dispatcher.cc \
+	content/renderer/devtools/devtools_agent.cc \
+	content/renderer/devtools/devtools_agent_filter.cc \
+	content/renderer/devtools/devtools_client.cc \
+	content/renderer/disambiguation_popup_helper.cc \
+	content/renderer/dom_automation_controller.cc \
+	content/renderer/dom_storage/dom_storage_dispatcher.cc \
+	content/renderer/dom_storage/webstoragearea_impl.cc \
+	content/renderer/dom_storage/webstoragenamespace_impl.cc \
+	content/renderer/external_popup_menu.cc \
+	content/renderer/gamepad_shared_memory_reader.cc \
+	content/renderer/geolocation_dispatcher.cc \
+	content/renderer/gpu/compositor_output_surface.cc \
+	content/renderer/gpu/compositor_software_output_device.cc \
+	content/renderer/gpu/input_event_filter.cc \
+	content/renderer/gpu/input_handler_manager.cc \
+	content/renderer/gpu/gpu_benchmarking_extension.cc \
+	content/renderer/gpu/mailbox_output_surface.cc \
+	content/renderer/gpu/stream_texture_host_android.cc \
+	content/renderer/gpu/render_widget_compositor.cc \
+	content/renderer/hyphenator/hyphenator.cc \
+	content/renderer/idle_user_detector.cc \
+	content/renderer/image_loading_helper.cc \
+	content/renderer/internal_document_state_data.cc \
+	content/renderer/java/java_bridge_channel.cc \
+	content/renderer/java/java_bridge_dispatcher.cc \
+	content/renderer/load_progress_tracker.cc \
+	content/renderer/media/audio_device_factory.cc \
+	content/renderer/media/audio_input_message_filter.cc \
+	content/renderer/media/audio_message_filter.cc \
+	content/renderer/media/audio_renderer_mixer_manager.cc \
+	content/renderer/media/pepper_platform_video_decoder_impl.cc \
+	content/renderer/media/render_media_log.cc \
+	content/renderer/media/renderer_gpu_video_decoder_factories.cc \
+	content/renderer/media/renderer_webaudiodevice_impl.cc \
+	content/renderer/media/rtc_video_renderer.cc \
+	content/renderer/media/stream_texture_factory_impl_android.cc \
+	content/renderer/media/video_capture_impl.cc \
+	content/renderer/media/video_capture_impl_manager.cc \
+	content/renderer/media/video_capture_message_filter.cc \
+	content/renderer/media/webmediaplayer_proxy_impl_android.cc \
+	content/renderer/media/webrtc_logging_handler_impl.cc \
+	content/renderer/media/webrtc_logging_message_filter.cc \
+	content/renderer/memory_benchmarking_extension.cc \
+	content/renderer/mhtml_generator.cc \
+	content/renderer/mouse_lock_dispatcher.cc \
+	content/renderer/paint_aggregator.cc \
+	content/renderer/password_form_conversion_utils.cc \
+	content/renderer/plugin_channel_host.cc \
+	content/renderer/browser_plugin/browser_plugin.cc \
+	content/renderer/browser_plugin/browser_plugin_backing_store.cc \
+	content/renderer/browser_plugin/browser_plugin_bindings.cc \
+	content/renderer/browser_plugin/browser_plugin_manager.cc \
+	content/renderer/browser_plugin/browser_plugin_manager_impl.cc \
+	content/renderer/browser_plugin/browser_plugin_compositing_helper.cc \
+	content/renderer/date_time_formatter.cc \
+	content/renderer/render_process_impl.cc \
+	content/renderer/render_thread_impl.cc \
+	content/renderer/render_view_impl.cc \
+	content/renderer/render_view_impl_android.cc \
+	content/renderer/render_view_impl_params.cc \
+	content/renderer/render_view_linux.cc \
+	content/renderer/render_view_mouse_lock_dispatcher.cc \
+	content/renderer/render_view_pepper_helper.cc \
+	content/renderer/render_widget.cc \
+	content/renderer/render_widget_fullscreen.cc \
+	content/renderer/renderer_clipboard_client.cc \
+	content/renderer/renderer_date_time_picker.cc \
+	content/renderer/renderer_main.cc \
+	content/renderer/renderer_main_platform_delegate_android.cc \
+	content/renderer/renderer_webapplicationcachehost_impl.cc \
+	content/renderer/renderer_webcookiejar_impl.cc \
+	content/renderer/renderer_webcolorchooser_impl.cc \
+	content/renderer/renderer_webkitplatformsupport_impl.cc \
+	content/renderer/rendering_benchmark.cc \
+	content/renderer/text_input_client_observer.cc \
+	content/renderer/v8_value_converter_impl.cc \
+	content/renderer/web_ui_extension.cc \
+	content/renderer/web_ui_extension_data.cc \
+	content/renderer/webplugin_delegate_proxy.cc \
+	content/renderer/websharedworker_proxy.cc \
+	content/renderer/websharedworkerrepository_impl.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-fno-tree-sra \
+	-fuse-ld=gold \
+	-Wno-psabi \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections
+
+MY_CFLAGS_C :=
+
+MY_DEFS := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DUSE_LINUX_BREAKPAD' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_GPU=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DENABLE_LANGUAGE_DETECTION=1' \
+	'-DENABLE_JAVA_BRIDGE' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DSK_BUILD_NO_IMAGE_ENCODE' \
+	'-DSK_DEFERRED_CANVAS_USES_GPIPE=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DGR_AGGRESSIVE_SHADER_OPTS=1' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_BUILD_FOR_ANDROID_NDK' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DFEATURE_ENABLE_SSL' \
+	'-DFEATURE_ENABLE_VOICEMAIL' \
+	'-DEXPAT_RELATIVE_PATH' \
+	'-DGTEST_RELATIVE_PATH' \
+	'-DJSONCPP_RELATIVE_PATH' \
+	'-DNO_MAIN_THREAD_WRAPPING' \
+	'-DNO_SOUND_SYSTEM' \
+	'-DANDROID' \
+	'-DPOSIX' \
+	'-DPROTOBUF_USE_DLLS' \
+	'-DGOOGLE_PROTOBUF_NO_RTTI' \
+	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+LOCAL_CFLAGS := $(MY_CFLAGS_C) $(MY_CFLAGS) $(MY_DEFS)
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES := \
+	$(LOCAL_PATH) \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(gyp_shared_intermediate_dir)/content \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/config \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/gpu/gl \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(LOCAL_PATH)/third_party/hyphen \
+	$(GYP_ABS_ANDROID_TOP_DIR)/external/icu4c/common \
+	$(GYP_ABS_ANDROID_TOP_DIR)/external/icu4c/i18n \
+	$(LOCAL_PATH)/third_party/libjingle/overrides \
+	$(LOCAL_PATH)/third_party/libjingle/source \
+	$(LOCAL_PATH)/testing/gtest/include \
+	$(LOCAL_PATH)/third_party \
+	$(LOCAL_PATH)/third_party/webrtc \
+	$(GYP_ABS_ANDROID_TOP_DIR)/external/expat/lib \
+	$(LOCAL_PATH)/third_party/jsoncpp/overrides/include \
+	$(LOCAL_PATH)/third_party/jsoncpp/source/include \
+	$(LOCAL_PATH)/third_party/npapi \
+	$(LOCAL_PATH)/third_party/npapi/bindings \
+	$(LOCAL_PATH)/third_party/WebKit/Source/Platform/chromium \
+	$(LOCAL_PATH)/third_party/WebKit/Source/Platform/chromium \
+	$(LOCAL_PATH)/v8/include \
+	$(gyp_shared_intermediate_dir)/protoc_out/third_party/libphonenumber \
+	$(LOCAL_PATH)/third_party/libphonenumber/src \
+	$(gyp_shared_intermediate_dir)/protoc_out \
+	$(LOCAL_PATH)/third_party/protobuf \
+	$(LOCAL_PATH)/third_party/protobuf/src \
+	$(GYP_ABS_ANDROID_TOP_DIR)/frameworks/wilhelm/include \
+	$(GYP_ABS_ANDROID_TOP_DIR)/bionic \
+	$(GYP_ABS_ANDROID_TOP_DIR)/external/stlport/stlport
+
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES)
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-abi \
+	-Wno-error=c++0x-compat \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+### Rules for final target.
+
+LOCAL_LDFLAGS := \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-Wl,-z,relro \
+	-Wl,-z,now \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--icf=safe \
+	-Wl,--gc-sections \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_STATIC_LIBRARIES := \
+	cpufeatures \
+	skia_skia_gyp \
+	webkit_support_glue_gyp \
+	third_party_libphonenumber_libphonenumber_without_metadata_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_content_renderer_gyp
+
+# Alias gyp target name.
+.PHONY: content_renderer
+content_renderer: content_content_renderer_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/content/content_renderer.target.darwin-x86.mk b/content/content_renderer.target.darwin-x86.mk
new file mode 100644
index 0000000..85d76b8
--- /dev/null
+++ b/content/content_renderer.target.darwin-x86.mk
@@ -0,0 +1,316 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := content_content_renderer_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,content_content_resources_gyp)/content_resources.stamp \
+	$(call intermediates-dir-for,GYP,jingle_jingle_glue_gyp)/jingle_glue.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_gyp)/skia_skia_gyp.a \
+	$(call intermediates-dir-for,GYP,third_party_icu_icuuc_gyp)/icuuc.stamp \
+	$(call intermediates-dir-for,GYP,third_party_icu_icui18n_gyp)/icui18n.stamp \
+	$(call intermediates-dir-for,GYP,third_party_npapi_npapi_gyp)/npapi.stamp \
+	$(call intermediates-dir-for,GYP,v8_tools_gyp_v8_gyp)/v8.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,webkit_support_glue_gyp)/webkit_support_glue_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_libphonenumber_libphonenumber_without_metadata_gyp)/third_party_libphonenumber_libphonenumber_without_metadata_gyp.a
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	content/public/renderer/android_content_detection_prefixes.cc \
+	content/public/renderer/content_renderer_client.cc \
+	content/public/renderer/document_state.cc \
+	content/public/renderer/navigation_state.cc \
+	content/public/renderer/render_process_observer.cc \
+	content/public/renderer/render_thread.cc \
+	content/public/renderer/render_view_observer.cc \
+	content/renderer/accessibility/accessibility_node_serializer.cc \
+	content/renderer/accessibility/renderer_accessibility.cc \
+	content/renderer/accessibility/renderer_accessibility_complete.cc \
+	content/renderer/accessibility/renderer_accessibility_focus_only.cc \
+	content/renderer/all_rendering_benchmarks.cc \
+	content/renderer/android/address_detector.cc \
+	content/renderer/android/content_detector.cc \
+	content/renderer/android/email_detector.cc \
+	content/renderer/android/phone_number_detector.cc \
+	content/renderer/android/synchronous_compositor_output_surface.cc \
+	content/renderer/device_orientation_dispatcher.cc \
+	content/renderer/devtools/devtools_agent.cc \
+	content/renderer/devtools/devtools_agent_filter.cc \
+	content/renderer/devtools/devtools_client.cc \
+	content/renderer/disambiguation_popup_helper.cc \
+	content/renderer/dom_automation_controller.cc \
+	content/renderer/dom_storage/dom_storage_dispatcher.cc \
+	content/renderer/dom_storage/webstoragearea_impl.cc \
+	content/renderer/dom_storage/webstoragenamespace_impl.cc \
+	content/renderer/external_popup_menu.cc \
+	content/renderer/gamepad_shared_memory_reader.cc \
+	content/renderer/geolocation_dispatcher.cc \
+	content/renderer/gpu/compositor_output_surface.cc \
+	content/renderer/gpu/compositor_software_output_device.cc \
+	content/renderer/gpu/input_event_filter.cc \
+	content/renderer/gpu/input_handler_manager.cc \
+	content/renderer/gpu/gpu_benchmarking_extension.cc \
+	content/renderer/gpu/mailbox_output_surface.cc \
+	content/renderer/gpu/stream_texture_host_android.cc \
+	content/renderer/gpu/render_widget_compositor.cc \
+	content/renderer/hyphenator/hyphenator.cc \
+	content/renderer/idle_user_detector.cc \
+	content/renderer/image_loading_helper.cc \
+	content/renderer/internal_document_state_data.cc \
+	content/renderer/java/java_bridge_channel.cc \
+	content/renderer/java/java_bridge_dispatcher.cc \
+	content/renderer/load_progress_tracker.cc \
+	content/renderer/media/audio_device_factory.cc \
+	content/renderer/media/audio_input_message_filter.cc \
+	content/renderer/media/audio_message_filter.cc \
+	content/renderer/media/audio_renderer_mixer_manager.cc \
+	content/renderer/media/pepper_platform_video_decoder_impl.cc \
+	content/renderer/media/render_media_log.cc \
+	content/renderer/media/renderer_gpu_video_decoder_factories.cc \
+	content/renderer/media/renderer_webaudiodevice_impl.cc \
+	content/renderer/media/rtc_video_renderer.cc \
+	content/renderer/media/stream_texture_factory_impl_android.cc \
+	content/renderer/media/video_capture_impl.cc \
+	content/renderer/media/video_capture_impl_manager.cc \
+	content/renderer/media/video_capture_message_filter.cc \
+	content/renderer/media/webmediaplayer_proxy_impl_android.cc \
+	content/renderer/media/webrtc_logging_handler_impl.cc \
+	content/renderer/media/webrtc_logging_message_filter.cc \
+	content/renderer/memory_benchmarking_extension.cc \
+	content/renderer/mhtml_generator.cc \
+	content/renderer/mouse_lock_dispatcher.cc \
+	content/renderer/paint_aggregator.cc \
+	content/renderer/password_form_conversion_utils.cc \
+	content/renderer/plugin_channel_host.cc \
+	content/renderer/browser_plugin/browser_plugin.cc \
+	content/renderer/browser_plugin/browser_plugin_backing_store.cc \
+	content/renderer/browser_plugin/browser_plugin_bindings.cc \
+	content/renderer/browser_plugin/browser_plugin_manager.cc \
+	content/renderer/browser_plugin/browser_plugin_manager_impl.cc \
+	content/renderer/browser_plugin/browser_plugin_compositing_helper.cc \
+	content/renderer/date_time_formatter.cc \
+	content/renderer/render_process_impl.cc \
+	content/renderer/render_thread_impl.cc \
+	content/renderer/render_view_impl.cc \
+	content/renderer/render_view_impl_android.cc \
+	content/renderer/render_view_impl_params.cc \
+	content/renderer/render_view_linux.cc \
+	content/renderer/render_view_mouse_lock_dispatcher.cc \
+	content/renderer/render_view_pepper_helper.cc \
+	content/renderer/render_widget.cc \
+	content/renderer/render_widget_fullscreen.cc \
+	content/renderer/renderer_clipboard_client.cc \
+	content/renderer/renderer_date_time_picker.cc \
+	content/renderer/renderer_main.cc \
+	content/renderer/renderer_main_platform_delegate_android.cc \
+	content/renderer/renderer_webapplicationcachehost_impl.cc \
+	content/renderer/renderer_webcookiejar_impl.cc \
+	content/renderer/renderer_webcolorchooser_impl.cc \
+	content/renderer/renderer_webkitplatformsupport_impl.cc \
+	content/renderer/rendering_benchmark.cc \
+	content/renderer/text_input_client_observer.cc \
+	content/renderer/v8_value_converter_impl.cc \
+	content/renderer/web_ui_extension.cc \
+	content/renderer/web_ui_extension_data.cc \
+	content/renderer/webplugin_delegate_proxy.cc \
+	content/renderer/websharedworker_proxy.cc \
+	content/renderer/websharedworkerrepository_impl.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS := \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-m32 \
+	-mmmx \
+	-march=pentium4 \
+	-msse2 \
+	-mfpmath=sse \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-fno-stack-protector \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections
+
+MY_CFLAGS_C :=
+
+MY_DEFS := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DUSE_LINUX_BREAKPAD' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_GPU=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DENABLE_LANGUAGE_DETECTION=1' \
+	'-DENABLE_JAVA_BRIDGE' \
+	'-DSK_BUILD_NO_IMAGE_ENCODE' \
+	'-DSK_DEFERRED_CANVAS_USES_GPIPE=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DGR_AGGRESSIVE_SHADER_OPTS=1' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_BUILD_FOR_ANDROID_NDK' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DFEATURE_ENABLE_SSL' \
+	'-DFEATURE_ENABLE_VOICEMAIL' \
+	'-DEXPAT_RELATIVE_PATH' \
+	'-DGTEST_RELATIVE_PATH' \
+	'-DJSONCPP_RELATIVE_PATH' \
+	'-DNO_MAIN_THREAD_WRAPPING' \
+	'-DNO_SOUND_SYSTEM' \
+	'-DANDROID' \
+	'-DPOSIX' \
+	'-DPROTOBUF_USE_DLLS' \
+	'-DGOOGLE_PROTOBUF_NO_RTTI' \
+	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+LOCAL_CFLAGS := $(MY_CFLAGS_C) $(MY_CFLAGS) $(MY_DEFS)
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES := \
+	$(LOCAL_PATH) \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(gyp_shared_intermediate_dir)/content \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/config \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/gpu/gl \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(LOCAL_PATH)/third_party/hyphen \
+	$(GYP_ABS_ANDROID_TOP_DIR)/external/icu4c/common \
+	$(GYP_ABS_ANDROID_TOP_DIR)/external/icu4c/i18n \
+	$(LOCAL_PATH)/third_party/libjingle/overrides \
+	$(LOCAL_PATH)/third_party/libjingle/source \
+	$(LOCAL_PATH)/testing/gtest/include \
+	$(LOCAL_PATH)/third_party \
+	$(LOCAL_PATH)/third_party/webrtc \
+	$(GYP_ABS_ANDROID_TOP_DIR)/external/expat/lib \
+	$(LOCAL_PATH)/third_party/jsoncpp/overrides/include \
+	$(LOCAL_PATH)/third_party/jsoncpp/source/include \
+	$(LOCAL_PATH)/third_party/npapi \
+	$(LOCAL_PATH)/third_party/npapi/bindings \
+	$(LOCAL_PATH)/third_party/WebKit/Source/Platform/chromium \
+	$(LOCAL_PATH)/third_party/WebKit/Source/Platform/chromium \
+	$(LOCAL_PATH)/v8/include \
+	$(gyp_shared_intermediate_dir)/protoc_out/third_party/libphonenumber \
+	$(LOCAL_PATH)/third_party/libphonenumber/src \
+	$(gyp_shared_intermediate_dir)/protoc_out \
+	$(LOCAL_PATH)/third_party/protobuf \
+	$(LOCAL_PATH)/third_party/protobuf/src \
+	$(GYP_ABS_ANDROID_TOP_DIR)/frameworks/wilhelm/include \
+	$(GYP_ABS_ANDROID_TOP_DIR)/bionic \
+	$(GYP_ABS_ANDROID_TOP_DIR)/external/stlport/stlport
+
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES)
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-error=c++0x-compat \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+### Rules for final target.
+
+LOCAL_LDFLAGS := \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m32 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_STATIC_LIBRARIES := \
+	cpufeatures \
+	skia_skia_gyp \
+	webkit_support_glue_gyp \
+	third_party_libphonenumber_libphonenumber_without_metadata_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_content_renderer_gyp
+
+# Alias gyp target name.
+.PHONY: content_renderer
+content_renderer: content_content_renderer_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/content/content_renderer.target.linux-arm.mk b/content/content_renderer.target.linux-arm.mk
index 24c9f4f..8755e4b 100644
--- a/content/content_renderer.target.linux-arm.mk
+++ b/content/content_renderer.target.linux-arm.mk
@@ -48,22 +48,21 @@
 	content/renderer/android/content_detector.cc \
 	content/renderer/android/email_detector.cc \
 	content/renderer/android/phone_number_detector.cc \
+	content/renderer/android/synchronous_compositor_output_surface.cc \
 	content/renderer/device_orientation_dispatcher.cc \
 	content/renderer/devtools/devtools_agent.cc \
 	content/renderer/devtools/devtools_agent_filter.cc \
 	content/renderer/devtools/devtools_client.cc \
 	content/renderer/disambiguation_popup_helper.cc \
-	content/renderer/do_not_track_bindings.cc \
 	content/renderer/dom_automation_controller.cc \
 	content/renderer/dom_storage/dom_storage_dispatcher.cc \
 	content/renderer/dom_storage/webstoragearea_impl.cc \
 	content/renderer/dom_storage/webstoragenamespace_impl.cc \
 	content/renderer/external_popup_menu.cc \
-	content/renderer/favicon_helper.cc \
 	content/renderer/gamepad_shared_memory_reader.cc \
 	content/renderer/geolocation_dispatcher.cc \
 	content/renderer/gpu/compositor_output_surface.cc \
-	content/renderer/gpu/compositor_software_output_device_gl_adapter.cc \
+	content/renderer/gpu/compositor_software_output_device.cc \
 	content/renderer/gpu/input_event_filter.cc \
 	content/renderer/gpu/input_handler_manager.cc \
 	content/renderer/gpu/gpu_benchmarking_extension.cc \
@@ -72,6 +71,8 @@
 	content/renderer/gpu/render_widget_compositor.cc \
 	content/renderer/hyphenator/hyphenator.cc \
 	content/renderer/idle_user_detector.cc \
+	content/renderer/image_loading_helper.cc \
+	content/renderer/internal_document_state_data.cc \
 	content/renderer/java/java_bridge_channel.cc \
 	content/renderer/java/java_bridge_dispatcher.cc \
 	content/renderer/load_progress_tracker.cc \
@@ -79,10 +80,8 @@
 	content/renderer/media/audio_input_message_filter.cc \
 	content/renderer/media/audio_message_filter.cc \
 	content/renderer/media/audio_renderer_mixer_manager.cc \
-	content/renderer/media/local_video_capture.cc \
 	content/renderer/media/pepper_platform_video_decoder_impl.cc \
 	content/renderer/media/render_media_log.cc \
-	content/renderer/media/renderer_audio_output_device.cc \
 	content/renderer/media/renderer_gpu_video_decoder_factories.cc \
 	content/renderer/media/renderer_webaudiodevice_impl.cc \
 	content/renderer/media/rtc_video_renderer.cc \
@@ -91,6 +90,8 @@
 	content/renderer/media/video_capture_impl_manager.cc \
 	content/renderer/media/video_capture_message_filter.cc \
 	content/renderer/media/webmediaplayer_proxy_impl_android.cc \
+	content/renderer/media/webrtc_logging_handler_impl.cc \
+	content/renderer/media/webrtc_logging_message_filter.cc \
 	content/renderer/memory_benchmarking_extension.cc \
 	content/renderer/mhtml_generator.cc \
 	content/renderer/mouse_lock_dispatcher.cc \
@@ -169,7 +170,6 @@
 
 MY_DEFS := \
 	'-DCONTENT_IMPLEMENTATION' \
-	'-DUSE_SKIA' \
 	'-D_FILE_OFFSET_BITS=64' \
 	'-DUSE_LINUX_BREAKPAD' \
 	'-DNO_TCMALLOC' \
@@ -177,7 +177,6 @@
 	'-DCHROMIUM_BUILD' \
 	'-DUSE_LIBJPEG_TURBO=1' \
 	'-DUSE_PROPRIETARY_CODECS' \
-	'-DENABLE_PEPPER_THREADING' \
 	'-DENABLE_GPU=1' \
 	'-DUSE_OPENSSL=1' \
 	'-DENABLE_EGLIMAGE=1' \
@@ -218,9 +217,10 @@
 
 # Include paths placed before CFLAGS/CPPFLAGS
 LOCAL_C_INCLUDES := \
+	$(LOCAL_PATH) \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
 	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
 	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
-	$(LOCAL_PATH) \
 	$(LOCAL_PATH)/third_party/khronos \
 	$(LOCAL_PATH)/gpu \
 	$(gyp_shared_intermediate_dir)/content \
@@ -232,6 +232,7 @@
 	$(LOCAL_PATH)/third_party/skia/include/pdf \
 	$(LOCAL_PATH)/third_party/skia/include/gpu \
 	$(LOCAL_PATH)/third_party/skia/include/gpu/gl \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
 	$(LOCAL_PATH)/third_party/skia/include/pipe \
 	$(LOCAL_PATH)/third_party/skia/include/ports \
 	$(LOCAL_PATH)/third_party/skia/include/utils \
@@ -251,7 +252,6 @@
 	$(LOCAL_PATH)/third_party/npapi/bindings \
 	$(LOCAL_PATH)/third_party/WebKit/Source/Platform/chromium \
 	$(LOCAL_PATH)/third_party/WebKit/Source/Platform/chromium \
-	$(gyp_shared_intermediate_dir)/webcore_headers \
 	$(LOCAL_PATH)/v8/include \
 	$(gyp_shared_intermediate_dir)/protoc_out/third_party/libphonenumber \
 	$(LOCAL_PATH)/third_party/libphonenumber/src \
@@ -289,12 +289,13 @@
 	-Wl,--no-undefined \
 	-Wl,--exclude-libs=ALL \
 	-Wl,--icf=safe \
+	-Wl,--gc-sections \
 	-Wl,-O1 \
-	-Wl,--as-needed \
-	-Wl,--gc-sections
+	-Wl,--as-needed
 
 
 LOCAL_STATIC_LIBRARIES := \
+	cpufeatures \
 	skia_skia_gyp \
 	webkit_support_glue_gyp \
 	third_party_libphonenumber_libphonenumber_without_metadata_gyp
diff --git a/content/content_renderer.target.linux-x86.mk b/content/content_renderer.target.linux-x86.mk
index 9374709..85d76b8 100644
--- a/content/content_renderer.target.linux-x86.mk
+++ b/content/content_renderer.target.linux-x86.mk
@@ -48,22 +48,21 @@
 	content/renderer/android/content_detector.cc \
 	content/renderer/android/email_detector.cc \
 	content/renderer/android/phone_number_detector.cc \
+	content/renderer/android/synchronous_compositor_output_surface.cc \
 	content/renderer/device_orientation_dispatcher.cc \
 	content/renderer/devtools/devtools_agent.cc \
 	content/renderer/devtools/devtools_agent_filter.cc \
 	content/renderer/devtools/devtools_client.cc \
 	content/renderer/disambiguation_popup_helper.cc \
-	content/renderer/do_not_track_bindings.cc \
 	content/renderer/dom_automation_controller.cc \
 	content/renderer/dom_storage/dom_storage_dispatcher.cc \
 	content/renderer/dom_storage/webstoragearea_impl.cc \
 	content/renderer/dom_storage/webstoragenamespace_impl.cc \
 	content/renderer/external_popup_menu.cc \
-	content/renderer/favicon_helper.cc \
 	content/renderer/gamepad_shared_memory_reader.cc \
 	content/renderer/geolocation_dispatcher.cc \
 	content/renderer/gpu/compositor_output_surface.cc \
-	content/renderer/gpu/compositor_software_output_device_gl_adapter.cc \
+	content/renderer/gpu/compositor_software_output_device.cc \
 	content/renderer/gpu/input_event_filter.cc \
 	content/renderer/gpu/input_handler_manager.cc \
 	content/renderer/gpu/gpu_benchmarking_extension.cc \
@@ -72,6 +71,8 @@
 	content/renderer/gpu/render_widget_compositor.cc \
 	content/renderer/hyphenator/hyphenator.cc \
 	content/renderer/idle_user_detector.cc \
+	content/renderer/image_loading_helper.cc \
+	content/renderer/internal_document_state_data.cc \
 	content/renderer/java/java_bridge_channel.cc \
 	content/renderer/java/java_bridge_dispatcher.cc \
 	content/renderer/load_progress_tracker.cc \
@@ -79,10 +80,8 @@
 	content/renderer/media/audio_input_message_filter.cc \
 	content/renderer/media/audio_message_filter.cc \
 	content/renderer/media/audio_renderer_mixer_manager.cc \
-	content/renderer/media/local_video_capture.cc \
 	content/renderer/media/pepper_platform_video_decoder_impl.cc \
 	content/renderer/media/render_media_log.cc \
-	content/renderer/media/renderer_audio_output_device.cc \
 	content/renderer/media/renderer_gpu_video_decoder_factories.cc \
 	content/renderer/media/renderer_webaudiodevice_impl.cc \
 	content/renderer/media/rtc_video_renderer.cc \
@@ -91,6 +90,8 @@
 	content/renderer/media/video_capture_impl_manager.cc \
 	content/renderer/media/video_capture_message_filter.cc \
 	content/renderer/media/webmediaplayer_proxy_impl_android.cc \
+	content/renderer/media/webrtc_logging_handler_impl.cc \
+	content/renderer/media/webrtc_logging_message_filter.cc \
 	content/renderer/memory_benchmarking_extension.cc \
 	content/renderer/mhtml_generator.cc \
 	content/renderer/mouse_lock_dispatcher.cc \
@@ -149,6 +150,7 @@
 	-march=pentium4 \
 	-msse2 \
 	-mfpmath=sse \
+	-fuse-ld=gold \
 	-ffunction-sections \
 	-funwind-tables \
 	-g \
@@ -170,7 +172,6 @@
 
 MY_DEFS := \
 	'-DCONTENT_IMPLEMENTATION' \
-	'-DUSE_SKIA' \
 	'-D_FILE_OFFSET_BITS=64' \
 	'-DUSE_LINUX_BREAKPAD' \
 	'-DNO_TCMALLOC' \
@@ -178,7 +179,6 @@
 	'-DCHROMIUM_BUILD' \
 	'-DUSE_LIBJPEG_TURBO=1' \
 	'-DUSE_PROPRIETARY_CODECS' \
-	'-DENABLE_PEPPER_THREADING' \
 	'-DENABLE_GPU=1' \
 	'-DUSE_OPENSSL=1' \
 	'-DENABLE_EGLIMAGE=1' \
@@ -218,9 +218,10 @@
 
 # Include paths placed before CFLAGS/CPPFLAGS
 LOCAL_C_INCLUDES := \
+	$(LOCAL_PATH) \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
 	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
 	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
-	$(LOCAL_PATH) \
 	$(LOCAL_PATH)/third_party/khronos \
 	$(LOCAL_PATH)/gpu \
 	$(gyp_shared_intermediate_dir)/content \
@@ -232,6 +233,7 @@
 	$(LOCAL_PATH)/third_party/skia/include/pdf \
 	$(LOCAL_PATH)/third_party/skia/include/gpu \
 	$(LOCAL_PATH)/third_party/skia/include/gpu/gl \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
 	$(LOCAL_PATH)/third_party/skia/include/pipe \
 	$(LOCAL_PATH)/third_party/skia/include/ports \
 	$(LOCAL_PATH)/third_party/skia/include/utils \
@@ -251,7 +253,6 @@
 	$(LOCAL_PATH)/third_party/npapi/bindings \
 	$(LOCAL_PATH)/third_party/WebKit/Source/Platform/chromium \
 	$(LOCAL_PATH)/third_party/WebKit/Source/Platform/chromium \
-	$(gyp_shared_intermediate_dir)/webcore_headers \
 	$(LOCAL_PATH)/v8/include \
 	$(gyp_shared_intermediate_dir)/protoc_out/third_party/libphonenumber \
 	$(LOCAL_PATH)/third_party/libphonenumber/src \
@@ -282,15 +283,17 @@
 	-Wl,-z,noexecstack \
 	-fPIC \
 	-m32 \
+	-fuse-ld=gold \
 	-nostdlib \
 	-Wl,--no-undefined \
 	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
 	-Wl,-O1 \
-	-Wl,--as-needed \
-	-Wl,--gc-sections
+	-Wl,--as-needed
 
 
 LOCAL_STATIC_LIBRARIES := \
+	cpufeatures \
 	skia_skia_gyp \
 	webkit_support_glue_gyp \
 	third_party_libphonenumber_libphonenumber_without_metadata_gyp
diff --git a/content/content_resources.grd b/content/content_resources.grd
index b089e23..78ec631 100644
--- a/content/content_resources.grd
+++ b/content/content_resources.grd
@@ -19,6 +19,9 @@
       <include name="IDR_GPU_INTERNALS_HTML" file="browser/resources/gpu/gpu_internals.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" />
       <include name="IDR_GPU_INTERNALS_JS" file="browser/resources/gpu/gpu_internals.js" flattenhtml="true" type="BINDATA" />
       <include name="IDR_GPU_SWITCHING_LIST" file="browser/gpu/gpu_switching_list.json" type="BINDATA" />
+      <include name="IDR_INDEXED_DB_INTERNALS_HTML" file="browser/resources/indexed_db/indexeddb_internals.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" />
+      <include name="IDR_INDEXED_DB_INTERNALS_JS" file="browser/resources/indexed_db/indexeddb_internals.js" flattenhtml="true" type="BINDATA" />
+      <include name="IDR_INDEXED_DB_INTERNALS_CSS" file="browser/resources/indexed_db/indexeddb_internals.css" flattenhtml="true" type="BINDATA" />
       <include name="IDR_MEDIA_INTERNALS_HTML" file="browser/resources/media/media_internals.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" />
       <include name="IDR_MEDIA_INTERNALS_JS" file="browser/resources/media/media_internals.js" flattenhtml="true" type="BINDATA" />
       <include name="IDR_WEBRTC_INTERNALS_HTML" file="browser/resources/media/webrtc_internals.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" />
diff --git a/content/content_resources.target.darwin-arm.mk b/content/content_resources.target.darwin-arm.mk
new file mode 100644
index 0000000..1a70a57
--- /dev/null
+++ b/content/content_resources.target.darwin-arm.mk
@@ -0,0 +1,48 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := content_content_resources_gyp
+LOCAL_MODULE_STEM := content_resources
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,content_generate_content_resources_gyp)/generate_content_resources.stamp
+
+### Generated for copy rule.
+$(gyp_shared_intermediate_dir)/content_resources.pak: $(gyp_shared_intermediate_dir)/content/content_resources.pak $(GYP_TARGET_DEPENDENCIES) | $(ACP)
+	@echo Copying: $@
+	$(hide) mkdir -p $(dir $@)
+	$(hide) $(ACP) -r $< $@
+
+content_content_resources_gyp_content_resources_target_copies = $(gyp_shared_intermediate_dir)/content_resources.pak
+
+GYP_GENERATED_OUTPUTS := \
+	$(content_content_resources_gyp_content_resources_target_copies)
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_content_resources_gyp
+
+# Alias gyp target name.
+.PHONY: content_resources
+content_resources: content_content_resources_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/content/content_resources.target.darwin-x86.mk b/content/content_resources.target.darwin-x86.mk
new file mode 100644
index 0000000..1a70a57
--- /dev/null
+++ b/content/content_resources.target.darwin-x86.mk
@@ -0,0 +1,48 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := content_content_resources_gyp
+LOCAL_MODULE_STEM := content_resources
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,content_generate_content_resources_gyp)/generate_content_resources.stamp
+
+### Generated for copy rule.
+$(gyp_shared_intermediate_dir)/content_resources.pak: $(gyp_shared_intermediate_dir)/content/content_resources.pak $(GYP_TARGET_DEPENDENCIES) | $(ACP)
+	@echo Copying: $@
+	$(hide) mkdir -p $(dir $@)
+	$(hide) $(ACP) -r $< $@
+
+content_content_resources_gyp_content_resources_target_copies = $(gyp_shared_intermediate_dir)/content_resources.pak
+
+GYP_GENERATED_OUTPUTS := \
+	$(content_content_resources_gyp_content_resources_target_copies)
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_content_resources_gyp
+
+# Alias gyp target name.
+.PHONY: content_resources
+content_resources: content_content_resources_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/content/content_shell.gypi b/content/content_shell.gypi
index 5713513..1bf233b 100644
--- a/content/content_shell.gypi
+++ b/content/content_shell.gypi
@@ -68,8 +68,16 @@
         'shell/geolocation/shell_access_token_store.h',
         'shell/minimal_ash.cc',
         'shell/minimal_ash.h',
+        'shell/notify_done_forwarder.cc',
+        'shell/notify_done_forwarder.h',
         'shell/paths_mac.h',
         'shell/paths_mac.mm',
+        'shell/renderer/shell_content_renderer_client.cc',
+        'shell/renderer/shell_content_renderer_client.h',
+        'shell/renderer/shell_render_process_observer.cc',
+        'shell/renderer/shell_render_process_observer.h',
+        'shell/renderer/webkit_test_runner.cc',
+        'shell/renderer/webkit_test_runner.h',
         'shell/shell.cc',
         'shell/shell.h',
         'shell/shell_android.cc',
@@ -90,8 +98,6 @@
         'shell/shell_content_browser_client.h',
         'shell/shell_content_client.cc',
         'shell/shell_content_client.h',
-        'shell/shell_content_renderer_client.cc',
-        'shell/shell_content_renderer_client.h',
         'shell/shell_devtools_delegate.cc',
         'shell/shell_devtools_delegate.h',
         'shell/shell_devtools_frontend.cc',
@@ -118,8 +124,6 @@
         'shell/shell_network_delegate.h',
         'shell/shell_quota_permission_context.cc',
         'shell/shell_quota_permission_context.h',
-        'shell/shell_render_process_observer.cc',
-        'shell/shell_render_process_observer.h',
         'shell/shell_resource_dispatcher_host_delegate.cc',
         'shell/shell_resource_dispatcher_host_delegate.h',
         'shell/shell_switches.cc',
@@ -143,8 +147,6 @@
         'shell/webkit_test_platform_support_linux.cc',
         'shell/webkit_test_platform_support_mac.mm',
         'shell/webkit_test_platform_support_win.cc',
-        'shell/webkit_test_runner.cc',
-        'shell/webkit_test_runner.h',
       ],
       'msvs_settings': {
         'VCLinkerTool': {
@@ -490,6 +492,23 @@
               ],
             },
           ],
+          'conditions': [
+            ['enable_webrtc==1', {
+              'variables': {
+                'libpeer_target_type%': 'static_library',
+              },
+              'conditions': [
+                ['libpeer_target_type!="static_library"', {
+                  'copies': [{
+                   'destination': '<(PRODUCT_DIR)/$(CONTENTS_FOLDER_PATH)/Libraries',
+                   'files': [
+                      '<(PRODUCT_DIR)/libpeerconnection.so',
+                    ],
+                  }],
+                }],
+              ],
+            }],
+          ],
         },  # target content_shell_framework
         {
           'target_name': 'content_shell_helper_app',
@@ -642,24 +661,7 @@
           'dependencies': [
             'content_shell_apk',
           ],
-          # This all_dependent_settings is used for java targets only. This will
-          # add the content_shell jar to the classpath of dependent java
-          # targets.
-          'all_dependent_settings': {
-            'variables': {
-              'input_jars_paths': ['>(apk_output_jar_path)'],
-            },
-          },
-          # Add an action with the appropriate output. This allows the generated
-          # buildfiles to determine which target the output corresponds to.
-          'actions': [
-            {
-              'action_name': 'fake_generate_jar',
-              'inputs': [],
-              'outputs': ['>(apk_output_jar_path)'],
-              'action': [],
-            },
-          ],
+          'includes': [ '../build/apk_fake_jar.gypi' ],
         },
         {
           'target_name': 'content_shell_apk',
@@ -677,8 +679,8 @@
             'apk_name': 'ContentShell',
             'manifest_package_name': 'org.chromium.content_shell_apk',
             'java_in_dir': 'shell/android/shell_apk',
-            'resource_dir': 'res',
-            'native_libs_paths': ['<(SHARED_LIB_DIR)/libcontent_shell_content_view.so'],
+            'resource_dir': 'shell/android/shell_apk/res',
+            'native_lib_target': 'libcontent_shell_content_view',
             'additional_input_paths': ['<(PRODUCT_DIR)/content_shell/assets/content_shell.pak'],
             'asset_location': '<(ant_build_out)/content_shell/assets',
           },
diff --git a/content/content_tests.gypi b/content/content_tests.gypi
index cd362a5..7818c55 100644
--- a/content/content_tests.gypi
+++ b/content/content_tests.gypi
@@ -139,8 +139,6 @@
         # test support target.
         '../webkit/appcache/appcache_test_helper.cc',
         '../webkit/appcache/appcache_test_helper.h',
-        '../webkit/quota/mock_special_storage_policy.cc',
-        '../webkit/quota/mock_special_storage_policy.h',
       ],
       'conditions': [
         ['OS == "ios"', {
@@ -190,6 +188,8 @@
             'renderer/media/mock_media_stream_dependency_factory.h',
             'renderer/media/mock_media_stream_dispatcher.cc',
             'renderer/media/mock_media_stream_dispatcher.h',
+            'renderer/media/mock_media_stream_registry.cc',
+            'renderer/media/mock_media_stream_registry.h',
             'renderer/media/mock_peer_connection_impl.cc',
             'renderer/media/mock_peer_connection_impl.h',
             'renderer/media/mock_web_rtc_peer_connection_handler_client.cc',
@@ -289,23 +289,31 @@
         'browser/geolocation/win7_location_api_unittest_win.cc',
         'browser/geolocation/win7_location_provider_unittest_win.cc',
         'browser/gpu/gpu_blacklist_unittest.cc',
+        'browser/gpu/gpu_control_list_entry_unittest.cc',
+        'browser/gpu/gpu_control_list_machine_model_info_unittest.cc',
+        'browser/gpu/gpu_control_list_number_info_unittest.cc',
+        'browser/gpu/gpu_control_list_os_info_unittest.cc',
+        'browser/gpu/gpu_control_list_string_info_unittest.cc',
         'browser/gpu/gpu_control_list_unittest.cc',
+        'browser/gpu/gpu_control_list_version_info_unittest.cc',
         'browser/gpu/gpu_data_manager_impl_unittest.cc',
         'browser/gpu/gpu_driver_bug_list_unittest.cc',
         'browser/gpu/gpu_switching_list_unittest.cc',
         'browser/gpu/gpu_util_unittest.cc',
+        'browser/gpu/shader_disk_cache_unittest.cc',
         'browser/host_zoom_map_impl_unittest.cc',
         'browser/hyphenator/hyphenator_message_filter_unittest.cc',
-        'browser/in_process_webkit/indexed_db_quota_client_unittest.cc',
-        'browser/in_process_webkit/indexed_db_unittest.cc',
         'browser/in_process_webkit/webkit_thread_unittest.cc',
+        'browser/indexed_db/indexed_db_unittest.cc',
+        'browser/indexed_db/indexed_db_quota_client_unittest.cc',
+        'browser/loader/offline_policy_unittest.cc',
         'browser/loader/resource_buffer_unittest.cc',
         'browser/loader/resource_dispatcher_host_unittest.cc',
         'browser/loader/resource_loader_unittest.cc',
         'browser/loader/resource_scheduler_unittest.cc',
         'browser/mach_broker_mac_unittest.cc',
         'browser/media/media_internals_unittest.cc',
-        'browser/media/webrtc_internals_unittest.cc',
+        'browser/net/sqlite_persistent_cookie_store_unittest.cc',
         'browser/notification_service_impl_unittest.cc',
         'browser/plugin_loader_posix_unittest.cc',
         'browser/renderer_host/compositing_iosurface_transformer_mac_unittest.cc',
@@ -332,6 +340,7 @@
         'browser/renderer_host/render_widget_host_view_guest_unittest.cc',
         'browser/renderer_host/render_widget_host_view_mac_editcommand_helper_unittest.mm',
         'browser/renderer_host/render_widget_host_view_mac_unittest.mm',
+        'browser/renderer_host/smooth_scroll_gesture_controller_unittest.cc',
         'browser/renderer_host/text_input_client_mac_unittest.mm',
         'browser/renderer_host/web_input_event_aura_unittest.cc',
         'browser/resolve_proxy_msg_helper_unittest.cc',
@@ -342,6 +351,7 @@
         'browser/speech/google_streaming_remote_engine_unittest.cc',
         'browser/speech/speech_recognizer_unittest.cc',
         'browser/ssl/ssl_host_state_unittest.cc',
+        'browser/storage_partition_impl_unittest.cc',
         'browser/storage_partition_impl_map_unittest.cc',
         'browser/streams/stream_unittest.cc',
         'browser/streams/stream_url_request_job_unittest.cc',
@@ -365,11 +375,11 @@
         'common/mac/font_descriptor_unittest.mm',
         'common/gpu/gpu_info_unittest.cc',
         'common/gpu/gpu_memory_manager_unittest.cc',
-        'common/gpu/media/avc_config_record_builder_unittest.cc',
         'common/indexed_db/indexed_db_dispatcher_unittest.cc',
         'common/indexed_db/proxy_webidbcursor_impl_unittest.cc',
         'common/inter_process_time_ticks_converter_unittest.cc',
         'common/page_zoom_unittest.cc',
+        'common/partial_circular_buffer_unittest.cc',
         'common/resource_dispatcher_unittest.cc',
         'common/sandbox_mac_diraccess_unittest.mm',
         'common/sandbox_mac_fontloading_unittest.mm',
@@ -420,6 +430,7 @@
         '../webkit/appcache/mock_appcache_storage.cc',
         '../webkit/appcache/mock_appcache_storage.h',
         '../webkit/appcache/mock_appcache_storage_unittest.cc',
+        '../webkit/blob/blob_storage_context_unittest.cc',
         '../webkit/blob/blob_storage_controller_unittest.cc',
         '../webkit/blob/blob_url_request_job_unittest.cc',
         '../webkit/blob/local_file_stream_reader_unittest.cc',
@@ -427,6 +438,7 @@
         '../webkit/blob/mock_blob_url_request_context.h',
         '../webkit/blob/shareable_file_reference_unittest.cc',
         '../webkit/chromeos/fileapi/cros_mount_point_provider_unittest.cc',
+        '../webkit/chromeos/fileapi/file_access_permissions_unittest.cc',
         '../webkit/database/database_connections_unittest.cc',
         '../webkit/database/database_quota_client_unittest.cc',
         '../webkit/database/databases_table_unittest.cc',
@@ -440,6 +452,7 @@
         '../webkit/dom_storage/session_storage_database_unittest.cc',
         '../webkit/fileapi/async_file_test_helper.cc',
         '../webkit/fileapi/async_file_test_helper.h',
+        '../webkit/fileapi/copy_or_move_file_validator_unittest.cc',
         '../webkit/fileapi/external_mount_points_unittest.cc',
         '../webkit/fileapi/file_system_context_unittest.cc',
         '../webkit/fileapi/file_system_database_test_helper.cc',
@@ -465,7 +478,6 @@
         '../webkit/fileapi/local_file_system_test_helper.h',
         '../webkit/fileapi/local_file_stream_writer_unittest.cc',
         '../webkit/fileapi/local_file_util_unittest.cc',
-        '../webkit/fileapi/media/native_media_file_util_unittest.cc',
         '../webkit/fileapi/mock_file_change_observer.cc',
         '../webkit/fileapi/mock_file_change_observer.h',
         '../webkit/fileapi/native_file_util_unittest.cc',
@@ -486,7 +498,6 @@
         '../webkit/fileapi/webfilewriter_base_unittest.cc',
         '../webkit/glue/cpp_variant_unittest.cc',
         '../webkit/glue/glue_serialize_unittest.cc',
-        '../webkit/glue/regular_expression_unittest.cc',
         '../webkit/glue/resource_request_body_unittest.cc',
         '../webkit/glue/multipart_response_delegate_unittest.cc',
         '../webkit/glue/touch_fling_gesture_curve_unittest.cc',
@@ -499,12 +510,23 @@
         '../webkit/media/crypto/key_systems_unittest.cc',
         '../webkit/media/test_response_generator.cc',
         '../webkit/media/test_response_generator.h',
+        '../webkit/media/webaudiosourceprovider_impl_unittest.cc',
         '../webkit/mocks/mock_weburlloader.cc',
         '../webkit/mocks/mock_weburlloader.h',
         '../webkit/plugins/npapi/plugin_lib_unittest.cc',
         '../webkit/plugins/npapi/plugin_list_unittest.cc',
         '../webkit/plugins/npapi/plugin_utils_unittest.cc',
         '../webkit/plugins/npapi/webplugin_impl_unittest.cc',
+        '../webkit/plugins/ppapi/host_var_tracker_unittest.cc',
+        '../webkit/plugins/ppapi/mock_platform_image_2d.cc',
+        '../webkit/plugins/ppapi/mock_platform_image_2d.h',
+        '../webkit/plugins/ppapi/mock_plugin_delegate.cc',
+        '../webkit/plugins/ppapi/mock_plugin_delegate.h',
+        '../webkit/plugins/ppapi/mock_resource.h',
+        '../webkit/plugins/ppapi/ppapi_plugin_instance_unittest.cc',
+        '../webkit/plugins/ppapi/ppapi_unittest.cc',
+        '../webkit/plugins/ppapi/ppapi_unittest.h',
+        '../webkit/plugins/ppapi/quota_file_io_unittest.cc',
         '../webkit/quota/mock_quota_manager.cc',
         '../webkit/quota/mock_quota_manager.h',
         '../webkit/quota/mock_quota_manager_unittest.cc',
@@ -513,6 +535,8 @@
         '../webkit/quota/quota_database_unittest.cc',
         '../webkit/quota/quota_manager_unittest.cc',
         '../webkit/quota/quota_temporary_storage_evictor_unittest.cc',
+        '../webkit/quota/usage_tracker_unittest.cc',
+        '../webkit/user_agent/user_agent_unittest.cc',
       ],
       'conditions': [
         ['OS == "ios"', {
@@ -564,6 +588,7 @@
         }],
         ['enable_webrtc==1', {
           'sources': [
+            'browser/media/webrtc_internals_unittest.cc',
             'browser/renderer_host/p2p/socket_host_test_utils.h',
             'browser/renderer_host/p2p/socket_host_tcp_unittest.cc',
             'browser/renderer_host/p2p/socket_host_tcp_server_unittest.cc',
@@ -572,7 +597,10 @@
             'renderer/media/media_stream_dispatcher_unittest.cc',
             'renderer/media/media_stream_impl_unittest.cc',
             'renderer/media/rtc_peer_connection_handler_unittest.cc',
+            'renderer/media/video_destination_handler_unittest.cc',
+            'renderer/media/video_source_handler_unittest.cc',
             'renderer/media/webrtc_audio_device_unittest.cc',
+            'renderer/media/webrtc_local_audio_track_unittest.cc',
           ],
           'dependencies': [
             '../third_party/libjingle/libjingle.gyp:libjingle_webrtc',
@@ -634,7 +662,19 @@
             'browser/accessibility/browser_accessibility_win_unittest.cc',
           ],
         }],
+        ['use_aura==1 and OS=="linux"', {
+          'sources!': [
+            # http://crbug.com/234172: these tests depend on single process
+            # mode, which doesn't work in content_browsertests on Linux Aura.
+            'renderer/dom_operations_browsertest.cc',
+            'renderer/dom_serializer_browsertest.cc',
+            'renderer/resource_fetcher_browsertest.cc',
+          ],
+        }],
         ['OS == "android"', {
+          'dependencies': [
+            '../ui/ui.gyp:shell_dialogs',
+          ],
           'sources!': [
             'browser/geolocation/device_data_provider_unittest.cc',
             'browser/geolocation/gps_location_provider_unittest_linux.cc',
@@ -685,6 +725,7 @@
             '../testing/gmock.gyp:gmock',
             '../testing/gtest.gyp:gtest',
             '../third_party/mesa/mesa.gyp:osmesa',
+            '../third_party/widevine/cdm/widevine_cdm.gyp:widevine_cdm_version_h',
             '../ui/gl/gl.gyp:gl',
             '../ui/snapshot/snapshot.gyp:snapshot',
             '../ui/ui.gyp:shell_dialogs',
@@ -695,6 +736,7 @@
           ],
           'include_dirs': [
             '..',
+            '<(SHARED_INTERMEDIATE_DIR)',  # Needed by encrypted_media_browsertest.cc
           ],
           'includes': [
             'browser/gpu/test_support_gpu.gypi',
@@ -726,12 +768,13 @@
             'browser/fileapi/blob_layout_browsertest.cc',
             'browser/fileapi/file_system_browsertest.cc',
             'browser/gpu/gpu_crash_browsertest.cc',
+            'browser/gpu/gpu_functional_browsertest.cc',
             'browser/gpu/gpu_memory_test.cc',
             'browser/gpu/gpu_pixel_browsertest.cc',
             'browser/gpu/webgl_conformance_test.cc',
             'browser/gpu/webgl_conformance_test_list_autogen.h',
             'browser/in_process_webkit/indexed_db_browsertest.cc',
-            'browser/in_process_webkit/indexed_db_layout_browsertest.cc',
+            'browser/indexed_db/indexed_db_layout_browsertest.cc',
             'browser/loader/resource_dispatcher_host_browsertest.cc',
             'browser/media/audio_browsertest.cc',
             'browser/media/encrypted_media_browsertest.cc',
@@ -743,17 +786,18 @@
             'browser/renderer_host/clipboard_browsertest.cc',
             'browser/renderer_host/render_view_host_browsertest.cc',
             'browser/renderer_host/render_view_host_manager_browsertest.cc',
+            'browser/renderer_host/render_widget_host_browsertest.cc',
             'browser/renderer_host/render_widget_host_view_browsertest.cc',
             'browser/renderer_host/render_widget_host_view_win_browsertest.cc',
             'browser/security_exploit_browsertest.cc',
             'browser/session_history_browsertest.cc',
             'browser/site_per_process_browsertest.cc',
             'browser/speech/speech_recognition_browsertest.cc',
+            'browser/web_contents/touch_editable_impl_aura_browsertest.cc',
+            'browser/web_contents/web_contents_impl_browsertest.cc',
             'browser/web_contents/web_contents_view_aura_browsertest.cc',
             'browser/webkit_browsertest.cc',
             'browser/worker_host/test/worker_browsertest.cc',
-            'common/content_constants_internal.cc',
-            'common/content_constants_internal.h',
             'renderer/accessibility/renderer_accessibility_browsertest.cc',
             'renderer/browser_plugin/mock_browser_plugin.h',
             'renderer/browser_plugin/mock_browser_plugin.cc',
@@ -761,6 +805,9 @@
             'renderer/browser_plugin/mock_browser_plugin_manager.cc',
             'renderer/browser_plugin/browser_plugin_browsertest.h',
             'renderer/browser_plugin/browser_plugin_browsertest.cc',
+            'renderer/cpp_bound_class_unittest.cc',
+            'renderer/dom_operations_browsertest.cc',
+            'renderer/dom_serializer_browsertest.cc',
             'renderer/mouse_lock_dispatcher_browsertest.cc',
             'renderer/password_form_conversion_utils_browsertest.cc',
             'renderer/pepper/mock_renderer_ppapi_host.cc',
@@ -768,9 +815,11 @@
             'renderer/pepper/pepper_file_chooser_host_unittest.cc',
             'renderer/pepper/pepper_graphics_2d_host_unittest.cc',
             'renderer/pepper/pepper_url_request_unittest.cc',
+            'renderer/render_thread_impl_browsertest.cc',
             'renderer/render_view_browsertest.cc',
             'renderer/render_view_browsertest_mac.mm',
             'renderer/render_widget_browsertest.cc',
+            'renderer/resource_fetcher_browsertest.cc',
             'test/browser_test_message_pump_android.cc',
             'test/browser_test_message_pump_android.h',
             'test/content_browser_test.h',
@@ -784,12 +833,19 @@
             'test/layout_browsertest.h',
             'test/layout_test_http_server.cc',
             'test/layout_test_http_server.h',
+            '../webkit/glue/cpp_binding_example.cc',
+            '../webkit/glue/cpp_binding_example.h',
             '../webkit/plugins/ppapi/mock_platform_image_2d.cc',
             '../webkit/plugins/ppapi/mock_platform_image_2d.h',
             '../webkit/plugins/ppapi/mock_plugin_delegate.cc',
             '../webkit/plugins/ppapi/mock_plugin_delegate.h',
           ],
           'conditions': [
+            ['chromeos==0', {
+              'sources!': [
+                'browser/web_contents/touch_editable_impl_aura_browsertest.cc',
+              ],
+            }],
             ['OS=="win"', {
               'resource_include_dirs': [
                 '<(SHARED_INTERMEDIATE_DIR)/webkit',
@@ -843,11 +899,6 @@
             ['OS=="android"', {
               'sources!': [
                 'browser/accessibility/dump_accessibility_tree_browsertest.cc',
-                # These are included via dependency on content_common and hence
-                # we get multiple definition errors in a shared library build.
-                # Other builds need it as the symbols are not exported.
-                'common/content_constants_internal.cc',
-                'common/content_constants_internal.h',
               ],
               'sources': [
                 'shell/android/browsertests_apk/content_browser_tests_android.cc',
@@ -904,7 +955,7 @@
         },
       ],
     }],
-    ['chromeos==1 or OS=="win" or OS=="mac"', {
+    ['chromeos==1 or OS=="win"', {
       # TODO(felipeg): Make video_decode_accelerator_unittest work on Android.
       # http://crbug.com/178647
       'targets': [
@@ -924,7 +975,6 @@
             ],
             'sources': [
               'common/gpu/media/rendering_helper.h',
-              'common/gpu/media/rendering_helper_mac.mm',
               'common/gpu/media/rendering_helper_gl.cc',
               'common/gpu/media/video_decode_accelerator_unittest.cc',
             ],
@@ -934,11 +984,6 @@
                   '<(DEPTH)/third_party/openmax/il',
                 ],
               }],
-              ['OS=="mac"', {
-                'sources!': [
-                  'common/gpu/media/rendering_helper_gl.cc',
-                ],
-              }],
               ['OS=="win"', {
                 'dependencies': [
                   '../third_party/angle/src/build_angle.gyp:libEGL',
@@ -946,7 +991,7 @@
                 ],
               }],
               ['(OS=="win" and win_use_allocator_shim==1) or '
-               '(os_posix == 1 and OS != "mac" and OS != "android" and '
+               '(os_posix == 1 and OS != "android" and '
                ' linux_use_tcmalloc==1)', {
                 'dependencies': [
                   '../base/allocator/allocator.gyp:allocator',
@@ -1016,8 +1061,8 @@
           'variables': {
             'apk_name': 'content_browsertests',
             'java_in_dir': 'shell/android/browsertests_apk',
-            'resource_dir': 'res',
-            'native_libs_paths': ['<(SHARED_LIB_DIR)/<(SHARED_LIB_PREFIX)content_browsertests<(SHARED_LIB_SUFFIX)'],
+            'resource_dir': 'shell/android/browsertests_apk/res',
+            'native_lib_target': 'libcontent_browsertests',
             'additional_input_paths': ['<(PRODUCT_DIR)/content_shell/assets/content_shell.pak'],
             'asset_location': '<(ant_build_out)/content_shell/assets',
           },
@@ -1059,9 +1104,9 @@
           ],
           'variables': {
             'apk_name': 'ContentShellTest',
-            'java_in_dir': '../content/shell/android/javatests',
-            'additional_src_dirs': ['../content/public/android/javatests/',],
-            'resource_dir': '../shell_apk/res',
+            'java_in_dir': 'shell/android/javatests',
+            'resource_dir': 'shell/android/shell_apk/res',
+            'additional_src_dirs': ['public/android/javatests/',],
             'is_test_apk': 1,
           },
           'includes': [ '../build/java_apk.gypi' ],
diff --git a/content/content_unittests.isolate b/content/content_unittests.isolate
index 0038388..efcd163 100644
--- a/content/content_unittests.isolate
+++ b/content/content_unittests.isolate
@@ -2,19 +2,6 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 {
-  'variables': {
-    'isolate_dependency_tracked': [
-      '<(PRODUCT_DIR)/content_unittests<(EXECUTABLE_SUFFIX)',
-    ],
-    'isolate_dependency_untracked': [
-      'browser/gpu/gpu_driver_bug_list.json',
-      'browser/gpu/gpu_switching_list.json',
-      'browser/gpu/software_rendering_list.json',
-      'test/data/',
-      '../third_party/hyphen/hyph_en_US.dic',
-      '../webkit/data/',
-    ],
-  },
   'conditions': [
     ['OS=="linux"', {
       'variables': {
@@ -29,13 +16,20 @@
           '<(PRODUCT_DIR)/test_data/',
         ],
       },
-    }, {
+    }],
+    ['OS=="linux" or OS=="mac" or OS=="win"', {
       'variables': {
-        'command': [
-          '../testing/test_env.py',
-          '../tools/swarm_client/run_test_cases.py',
+        'isolate_dependency_tracked': [
           '<(PRODUCT_DIR)/content_unittests<(EXECUTABLE_SUFFIX)',
         ],
+        'isolate_dependency_untracked': [
+          '../third_party/hyphen/hyph_en_US.dic',
+          '../webkit/data/',
+          'browser/gpu/gpu_driver_bug_list.json',
+          'browser/gpu/gpu_switching_list.json',
+          'browser/gpu/software_rendering_list.json',
+          'test/data/',
+        ],
       },
     }],
     ['OS=="mac"', {
@@ -46,6 +40,15 @@
         ],
       },
     }],
+    ['OS=="mac" or OS=="win"', {
+      'variables': {
+        'command': [
+          '../testing/test_env.py',
+          '../tools/swarm_client/run_test_cases.py',
+          '<(PRODUCT_DIR)/content_unittests<(EXECUTABLE_SUFFIX)',
+        ],
+      },
+    }],
     ['OS=="win"', {
       'variables': {
         'isolate_dependency_untracked': [
diff --git a/content/content_utility.target.darwin-arm.mk b/content/content_utility.target.darwin-arm.mk
new file mode 100644
index 0000000..d67b4a3
--- /dev/null
+++ b/content/content_utility.target.darwin-arm.mk
@@ -0,0 +1,154 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := content_content_utility_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	content/public/utility/content_utility_client.cc \
+	content/public/utility/utility_thread.cc \
+	content/utility/utility_main.cc \
+	content/utility/utility_thread_impl.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-fno-tree-sra \
+	-fuse-ld=gold \
+	-Wno-psabi \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections
+
+MY_CFLAGS_C :=
+
+MY_DEFS := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DUSE_LINUX_BREAKPAD' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_GPU=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DENABLE_LANGUAGE_DETECTION=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+LOCAL_CFLAGS := $(MY_CFLAGS_C) $(MY_CFLAGS) $(MY_DEFS)
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES := \
+	$(LOCAL_PATH) \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(GYP_ABS_ANDROID_TOP_DIR)/frameworks/wilhelm/include \
+	$(GYP_ABS_ANDROID_TOP_DIR)/bionic \
+	$(GYP_ABS_ANDROID_TOP_DIR)/external/stlport/stlport
+
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES)
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-abi \
+	-Wno-error=c++0x-compat \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+### Rules for final target.
+
+LOCAL_LDFLAGS := \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-Wl,-z,relro \
+	-Wl,-z,now \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--icf=safe \
+	-Wl,--gc-sections \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_content_utility_gyp
+
+# Alias gyp target name.
+.PHONY: content_utility
+content_utility: content_content_utility_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/content/content_utility.target.darwin-x86.mk b/content/content_utility.target.darwin-x86.mk
new file mode 100644
index 0000000..837f0a1
--- /dev/null
+++ b/content/content_utility.target.darwin-x86.mk
@@ -0,0 +1,153 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := content_content_utility_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	content/public/utility/content_utility_client.cc \
+	content/public/utility/utility_thread.cc \
+	content/utility/utility_main.cc \
+	content/utility/utility_thread_impl.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS := \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-m32 \
+	-mmmx \
+	-march=pentium4 \
+	-msse2 \
+	-mfpmath=sse \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-fno-stack-protector \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections
+
+MY_CFLAGS_C :=
+
+MY_DEFS := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DUSE_LINUX_BREAKPAD' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_GPU=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DENABLE_LANGUAGE_DETECTION=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+LOCAL_CFLAGS := $(MY_CFLAGS_C) $(MY_CFLAGS) $(MY_DEFS)
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES := \
+	$(LOCAL_PATH) \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(GYP_ABS_ANDROID_TOP_DIR)/frameworks/wilhelm/include \
+	$(GYP_ABS_ANDROID_TOP_DIR)/bionic \
+	$(GYP_ABS_ANDROID_TOP_DIR)/external/stlport/stlport
+
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES)
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-error=c++0x-compat \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+### Rules for final target.
+
+LOCAL_LDFLAGS := \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m32 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_content_utility_gyp
+
+# Alias gyp target name.
+.PHONY: content_utility
+content_utility: content_content_utility_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/content/content_utility.target.linux-arm.mk b/content/content_utility.target.linux-arm.mk
index 4214e6c..d67b4a3 100644
--- a/content/content_utility.target.linux-arm.mk
+++ b/content/content_utility.target.linux-arm.mk
@@ -66,7 +66,6 @@
 
 MY_DEFS := \
 	'-DCONTENT_IMPLEMENTATION' \
-	'-DUSE_SKIA' \
 	'-D_FILE_OFFSET_BITS=64' \
 	'-DUSE_LINUX_BREAKPAD' \
 	'-DNO_TCMALLOC' \
@@ -74,7 +73,6 @@
 	'-DCHROMIUM_BUILD' \
 	'-DUSE_LIBJPEG_TURBO=1' \
 	'-DUSE_PROPRIETARY_CODECS' \
-	'-DENABLE_PEPPER_THREADING' \
 	'-DENABLE_GPU=1' \
 	'-DUSE_OPENSSL=1' \
 	'-DENABLE_EGLIMAGE=1' \
@@ -94,9 +92,10 @@
 
 # Include paths placed before CFLAGS/CPPFLAGS
 LOCAL_C_INCLUDES := \
+	$(LOCAL_PATH) \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
 	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
 	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
-	$(LOCAL_PATH) \
 	$(LOCAL_PATH)/third_party/khronos \
 	$(LOCAL_PATH)/gpu \
 	$(GYP_ABS_ANDROID_TOP_DIR)/frameworks/wilhelm/include \
@@ -130,9 +129,9 @@
 	-Wl,--no-undefined \
 	-Wl,--exclude-libs=ALL \
 	-Wl,--icf=safe \
+	-Wl,--gc-sections \
 	-Wl,-O1 \
-	-Wl,--as-needed \
-	-Wl,--gc-sections
+	-Wl,--as-needed
 
 
 LOCAL_STATIC_LIBRARIES :=
diff --git a/content/content_utility.target.linux-x86.mk b/content/content_utility.target.linux-x86.mk
index ea7ccbf..837f0a1 100644
--- a/content/content_utility.target.linux-x86.mk
+++ b/content/content_utility.target.linux-x86.mk
@@ -46,6 +46,7 @@
 	-march=pentium4 \
 	-msse2 \
 	-mfpmath=sse \
+	-fuse-ld=gold \
 	-ffunction-sections \
 	-funwind-tables \
 	-g \
@@ -67,7 +68,6 @@
 
 MY_DEFS := \
 	'-DCONTENT_IMPLEMENTATION' \
-	'-DUSE_SKIA' \
 	'-D_FILE_OFFSET_BITS=64' \
 	'-DUSE_LINUX_BREAKPAD' \
 	'-DNO_TCMALLOC' \
@@ -75,7 +75,6 @@
 	'-DCHROMIUM_BUILD' \
 	'-DUSE_LIBJPEG_TURBO=1' \
 	'-DUSE_PROPRIETARY_CODECS' \
-	'-DENABLE_PEPPER_THREADING' \
 	'-DENABLE_GPU=1' \
 	'-DUSE_OPENSSL=1' \
 	'-DENABLE_EGLIMAGE=1' \
@@ -95,9 +94,10 @@
 
 # Include paths placed before CFLAGS/CPPFLAGS
 LOCAL_C_INCLUDES := \
+	$(LOCAL_PATH) \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
 	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
 	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
-	$(LOCAL_PATH) \
 	$(LOCAL_PATH)/third_party/khronos \
 	$(LOCAL_PATH)/gpu \
 	$(GYP_ABS_ANDROID_TOP_DIR)/frameworks/wilhelm/include \
@@ -124,12 +124,13 @@
 	-Wl,-z,noexecstack \
 	-fPIC \
 	-m32 \
+	-fuse-ld=gold \
 	-nostdlib \
 	-Wl,--no-undefined \
 	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
 	-Wl,-O1 \
-	-Wl,--as-needed \
-	-Wl,--gc-sections
+	-Wl,--as-needed
 
 
 LOCAL_STATIC_LIBRARIES :=
diff --git a/content/content_worker.target.darwin-arm.mk b/content/content_worker.target.darwin-arm.mk
new file mode 100644
index 0000000..a5a8386
--- /dev/null
+++ b/content/content_worker.target.darwin-arm.mk
@@ -0,0 +1,187 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := content_content_worker_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_gyp)/skia_skia_gyp.a
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	content/worker/shared_worker_devtools_agent.cc \
+	content/worker/websharedworker_stub.cc \
+	content/worker/websharedworkerclient_proxy.cc \
+	content/worker/worker_main.cc \
+	content/worker/worker_thread.cc \
+	content/worker/worker_webapplicationcachehost_impl.cc \
+	content/worker/worker_webkitplatformsupport_impl.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-fno-tree-sra \
+	-fuse-ld=gold \
+	-Wno-psabi \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections
+
+MY_CFLAGS_C :=
+
+MY_DEFS := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DUSE_LINUX_BREAKPAD' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_GPU=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DENABLE_LANGUAGE_DETECTION=1' \
+	'-DSK_BUILD_NO_IMAGE_ENCODE' \
+	'-DSK_DEFERRED_CANVAS_USES_GPIPE=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DGR_AGGRESSIVE_SHADER_OPTS=1' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_BUILD_FOR_ANDROID_NDK' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+LOCAL_CFLAGS := $(MY_CFLAGS_C) $(MY_CFLAGS) $(MY_DEFS)
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES := \
+	$(LOCAL_PATH) \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/config \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/gpu/gl \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(LOCAL_PATH)/third_party/WebKit/Source/Platform/chromium \
+	$(LOCAL_PATH)/third_party/WebKit/Source/Platform/chromium \
+	$(GYP_ABS_ANDROID_TOP_DIR)/external/icu4c/common \
+	$(GYP_ABS_ANDROID_TOP_DIR)/external/icu4c/i18n \
+	$(LOCAL_PATH)/third_party/npapi \
+	$(LOCAL_PATH)/third_party/npapi/bindings \
+	$(LOCAL_PATH)/v8/include \
+	$(GYP_ABS_ANDROID_TOP_DIR)/frameworks/wilhelm/include \
+	$(GYP_ABS_ANDROID_TOP_DIR)/bionic \
+	$(GYP_ABS_ANDROID_TOP_DIR)/external/stlport/stlport
+
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES)
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-abi \
+	-Wno-error=c++0x-compat \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+### Rules for final target.
+
+LOCAL_LDFLAGS := \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-Wl,-z,relro \
+	-Wl,-z,now \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--icf=safe \
+	-Wl,--gc-sections \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_STATIC_LIBRARIES := \
+	skia_skia_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_content_worker_gyp
+
+# Alias gyp target name.
+.PHONY: content_worker
+content_worker: content_content_worker_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/content/content_worker.target.darwin-x86.mk b/content/content_worker.target.darwin-x86.mk
new file mode 100644
index 0000000..e1389e2
--- /dev/null
+++ b/content/content_worker.target.darwin-x86.mk
@@ -0,0 +1,186 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := content_content_worker_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_gyp)/skia_skia_gyp.a
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	content/worker/shared_worker_devtools_agent.cc \
+	content/worker/websharedworker_stub.cc \
+	content/worker/websharedworkerclient_proxy.cc \
+	content/worker/worker_main.cc \
+	content/worker/worker_thread.cc \
+	content/worker/worker_webapplicationcachehost_impl.cc \
+	content/worker/worker_webkitplatformsupport_impl.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS := \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-m32 \
+	-mmmx \
+	-march=pentium4 \
+	-msse2 \
+	-mfpmath=sse \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-fno-stack-protector \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections
+
+MY_CFLAGS_C :=
+
+MY_DEFS := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DUSE_LINUX_BREAKPAD' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_GPU=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DENABLE_LANGUAGE_DETECTION=1' \
+	'-DSK_BUILD_NO_IMAGE_ENCODE' \
+	'-DSK_DEFERRED_CANVAS_USES_GPIPE=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DGR_AGGRESSIVE_SHADER_OPTS=1' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_BUILD_FOR_ANDROID_NDK' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+LOCAL_CFLAGS := $(MY_CFLAGS_C) $(MY_CFLAGS) $(MY_DEFS)
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES := \
+	$(LOCAL_PATH) \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/config \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/gpu/gl \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(LOCAL_PATH)/third_party/WebKit/Source/Platform/chromium \
+	$(LOCAL_PATH)/third_party/WebKit/Source/Platform/chromium \
+	$(GYP_ABS_ANDROID_TOP_DIR)/external/icu4c/common \
+	$(GYP_ABS_ANDROID_TOP_DIR)/external/icu4c/i18n \
+	$(LOCAL_PATH)/third_party/npapi \
+	$(LOCAL_PATH)/third_party/npapi/bindings \
+	$(LOCAL_PATH)/v8/include \
+	$(GYP_ABS_ANDROID_TOP_DIR)/frameworks/wilhelm/include \
+	$(GYP_ABS_ANDROID_TOP_DIR)/bionic \
+	$(GYP_ABS_ANDROID_TOP_DIR)/external/stlport/stlport
+
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES)
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-error=c++0x-compat \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+### Rules for final target.
+
+LOCAL_LDFLAGS := \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m32 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_STATIC_LIBRARIES := \
+	skia_skia_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_content_worker_gyp
+
+# Alias gyp target name.
+.PHONY: content_worker
+content_worker: content_content_worker_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/content/content_worker.target.linux-arm.mk b/content/content_worker.target.linux-arm.mk
index 7142e39..a5a8386 100644
--- a/content/content_worker.target.linux-arm.mk
+++ b/content/content_worker.target.linux-arm.mk
@@ -70,7 +70,6 @@
 
 MY_DEFS := \
 	'-DCONTENT_IMPLEMENTATION' \
-	'-DUSE_SKIA' \
 	'-D_FILE_OFFSET_BITS=64' \
 	'-DUSE_LINUX_BREAKPAD' \
 	'-DNO_TCMALLOC' \
@@ -78,7 +77,6 @@
 	'-DCHROMIUM_BUILD' \
 	'-DUSE_LIBJPEG_TURBO=1' \
 	'-DUSE_PROPRIETARY_CODECS' \
-	'-DENABLE_PEPPER_THREADING' \
 	'-DENABLE_GPU=1' \
 	'-DUSE_OPENSSL=1' \
 	'-DENABLE_EGLIMAGE=1' \
@@ -106,9 +104,10 @@
 
 # Include paths placed before CFLAGS/CPPFLAGS
 LOCAL_C_INCLUDES := \
+	$(LOCAL_PATH) \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
 	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
 	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
-	$(LOCAL_PATH) \
 	$(LOCAL_PATH)/third_party/khronos \
 	$(LOCAL_PATH)/gpu \
 	$(LOCAL_PATH)/skia/config \
@@ -119,13 +118,13 @@
 	$(LOCAL_PATH)/third_party/skia/include/pdf \
 	$(LOCAL_PATH)/third_party/skia/include/gpu \
 	$(LOCAL_PATH)/third_party/skia/include/gpu/gl \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
 	$(LOCAL_PATH)/third_party/skia/include/pipe \
 	$(LOCAL_PATH)/third_party/skia/include/ports \
 	$(LOCAL_PATH)/third_party/skia/include/utils \
 	$(LOCAL_PATH)/skia/ext \
 	$(LOCAL_PATH)/third_party/WebKit/Source/Platform/chromium \
 	$(LOCAL_PATH)/third_party/WebKit/Source/Platform/chromium \
-	$(gyp_shared_intermediate_dir)/webcore_headers \
 	$(GYP_ABS_ANDROID_TOP_DIR)/external/icu4c/common \
 	$(GYP_ABS_ANDROID_TOP_DIR)/external/icu4c/i18n \
 	$(LOCAL_PATH)/third_party/npapi \
@@ -162,9 +161,9 @@
 	-Wl,--no-undefined \
 	-Wl,--exclude-libs=ALL \
 	-Wl,--icf=safe \
+	-Wl,--gc-sections \
 	-Wl,-O1 \
-	-Wl,--as-needed \
-	-Wl,--gc-sections
+	-Wl,--as-needed
 
 
 LOCAL_STATIC_LIBRARIES := \
diff --git a/content/content_worker.target.linux-x86.mk b/content/content_worker.target.linux-x86.mk
index dcfa778..e1389e2 100644
--- a/content/content_worker.target.linux-x86.mk
+++ b/content/content_worker.target.linux-x86.mk
@@ -50,6 +50,7 @@
 	-march=pentium4 \
 	-msse2 \
 	-mfpmath=sse \
+	-fuse-ld=gold \
 	-ffunction-sections \
 	-funwind-tables \
 	-g \
@@ -71,7 +72,6 @@
 
 MY_DEFS := \
 	'-DCONTENT_IMPLEMENTATION' \
-	'-DUSE_SKIA' \
 	'-D_FILE_OFFSET_BITS=64' \
 	'-DUSE_LINUX_BREAKPAD' \
 	'-DNO_TCMALLOC' \
@@ -79,7 +79,6 @@
 	'-DCHROMIUM_BUILD' \
 	'-DUSE_LIBJPEG_TURBO=1' \
 	'-DUSE_PROPRIETARY_CODECS' \
-	'-DENABLE_PEPPER_THREADING' \
 	'-DENABLE_GPU=1' \
 	'-DUSE_OPENSSL=1' \
 	'-DENABLE_EGLIMAGE=1' \
@@ -107,9 +106,10 @@
 
 # Include paths placed before CFLAGS/CPPFLAGS
 LOCAL_C_INCLUDES := \
+	$(LOCAL_PATH) \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
 	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
 	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
-	$(LOCAL_PATH) \
 	$(LOCAL_PATH)/third_party/khronos \
 	$(LOCAL_PATH)/gpu \
 	$(LOCAL_PATH)/skia/config \
@@ -120,13 +120,13 @@
 	$(LOCAL_PATH)/third_party/skia/include/pdf \
 	$(LOCAL_PATH)/third_party/skia/include/gpu \
 	$(LOCAL_PATH)/third_party/skia/include/gpu/gl \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
 	$(LOCAL_PATH)/third_party/skia/include/pipe \
 	$(LOCAL_PATH)/third_party/skia/include/ports \
 	$(LOCAL_PATH)/third_party/skia/include/utils \
 	$(LOCAL_PATH)/skia/ext \
 	$(LOCAL_PATH)/third_party/WebKit/Source/Platform/chromium \
 	$(LOCAL_PATH)/third_party/WebKit/Source/Platform/chromium \
-	$(gyp_shared_intermediate_dir)/webcore_headers \
 	$(GYP_ABS_ANDROID_TOP_DIR)/external/icu4c/common \
 	$(GYP_ABS_ANDROID_TOP_DIR)/external/icu4c/i18n \
 	$(LOCAL_PATH)/third_party/npapi \
@@ -156,12 +156,13 @@
 	-Wl,-z,noexecstack \
 	-fPIC \
 	-m32 \
+	-fuse-ld=gold \
 	-nostdlib \
 	-Wl,--no-undefined \
 	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
 	-Wl,-O1 \
-	-Wl,--as-needed \
-	-Wl,--gc-sections
+	-Wl,--as-needed
 
 
 LOCAL_STATIC_LIBRARIES := \
diff --git a/content/generate_content_resources.target.darwin-arm.mk b/content/generate_content_resources.target.darwin-arm.mk
new file mode 100644
index 0000000..4f77a75
--- /dev/null
+++ b/content/generate_content_resources.target.darwin-arm.mk
@@ -0,0 +1,54 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := content_generate_content_resources_gyp
+LOCAL_MODULE_STEM := generate_content_resources
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+### Rules for action "content_resources":
+$(gyp_shared_intermediate_dir)/content/grit/content_resources.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/grit/content_resources.h: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/grit/content_resources.h: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/grit/content_resources.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/grit/content_resources.h: $(LOCAL_PATH)/tools/gritsettings/resource_ids $(LOCAL_PATH)/content/content_resources.grd $(LOCAL_PATH)/content/browser/gpu/gpu_driver_bug_list.json $(LOCAL_PATH)/content/browser/gpu/gpu_switching_list.json $(LOCAL_PATH)/content/browser/gpu/software_rendering_list.json $(LOCAL_PATH)/content/browser/resources/accessibility/accessibility.css $(LOCAL_PATH)/content/browser/resources/accessibility/accessibility.html $(LOCAL_PATH)/content/browser/resources/accessibility/accessibility.js $(LOCAL_PATH)/content/browser/resources/gpu/browser_bridge.js $(LOCAL_PATH)/content/browser/resources/gpu/gpu_internals.html $(LOCAL_PATH)/content/browser/resources/gpu/gpu_internals.js $(LOCAL_PATH)/content/browser/resources/gpu/info_view.css $(LOCAL_PATH)/content/browser/resources/gpu/info_view.html $(LOCAL_PATH)/content/browser/resources/gpu/info_view.js $(LOCAL_PATH)/content/browser/resources/indexed_db/indexeddb_internals.css $(LOCAL_PATH)/content/browser/resources/indexed_db/indexeddb_internals.html $(LOCAL_PATH)/content/browser/resources/indexed_db/indexeddb_internals.js $(LOCAL_PATH)/content/browser/resources/media/cache_entry.js $(LOCAL_PATH)/content/browser/resources/media/data_series.js $(LOCAL_PATH)/content/browser/resources/media/disjoint_range_set.js $(LOCAL_PATH)/content/browser/resources/media/dump_creator.js $(LOCAL_PATH)/content/browser/resources/media/event_list.js $(LOCAL_PATH)/content/browser/resources/media/item_store.js $(LOCAL_PATH)/content/browser/resources/media/media_internals.css $(LOCAL_PATH)/content/browser/resources/media/media_internals.html $(LOCAL_PATH)/content/browser/resources/media/media_internals.js $(LOCAL_PATH)/content/browser/resources/media/media_player.js $(LOCAL_PATH)/content/browser/resources/media/metrics.js $(LOCAL_PATH)/content/browser/resources/media/peer_connection_update_table.js $(LOCAL_PATH)/content/browser/resources/media/ssrc_info_manager.js $(LOCAL_PATH)/content/browser/resources/media/stats_graph_helper.js $(LOCAL_PATH)/content/browser/resources/media/stats_table.js $(LOCAL_PATH)/content/browser/resources/media/timeline_graph_view.js $(LOCAL_PATH)/content/browser/resources/media/util.js $(LOCAL_PATH)/content/browser/resources/media/webrtc_internals.css $(LOCAL_PATH)/content/browser/resources/media/webrtc_internals.html $(LOCAL_PATH)/content/browser/resources/media/webrtc_internals.js $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/clique_unittest.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/c_format_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_writer_base_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/rc_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/rc_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/gather/txt_unittest.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grd_reader_unittest.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/grit_runner_unittest.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/lazy_re_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/base_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/include_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/io_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/message_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/misc_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/structure_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/pseudo_unittest.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/tclib_unittest.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/build_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb_unittest.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/util_unittest.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader_unittest.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: Generating resources from content_resources.grd ($@)"
+	$(hide)cd $(gyp_local_path)/content; mkdir -p $(gyp_shared_intermediate_dir)/content/grit $(gyp_shared_intermediate_dir)/content; python ../tools/grit/grit.py -i content_resources.grd build -f ../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/content" -D _chromium -E "CHROMIUM_BUILD=chromium" -D android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D use_concatenated_impulse_responses
+
+$(gyp_shared_intermediate_dir)/content/content_resources.pak: $(gyp_shared_intermediate_dir)/content/grit/content_resources.h ;
+$(gyp_shared_intermediate_dir)/content/content_resources.rc: $(gyp_shared_intermediate_dir)/content/grit/content_resources.h ;
+
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/content/grit/content_resources.h \
+	$(gyp_shared_intermediate_dir)/content/content_resources.pak \
+	$(gyp_shared_intermediate_dir)/content/content_resources.rc
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_generate_content_resources_gyp
+
+# Alias gyp target name.
+.PHONY: generate_content_resources
+generate_content_resources: content_generate_content_resources_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/content/generate_content_resources.target.darwin-x86.mk b/content/generate_content_resources.target.darwin-x86.mk
new file mode 100644
index 0000000..4f77a75
--- /dev/null
+++ b/content/generate_content_resources.target.darwin-x86.mk
@@ -0,0 +1,54 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := content_generate_content_resources_gyp
+LOCAL_MODULE_STEM := generate_content_resources
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+### Rules for action "content_resources":
+$(gyp_shared_intermediate_dir)/content/grit/content_resources.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/grit/content_resources.h: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/grit/content_resources.h: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/grit/content_resources.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/grit/content_resources.h: $(LOCAL_PATH)/tools/gritsettings/resource_ids $(LOCAL_PATH)/content/content_resources.grd $(LOCAL_PATH)/content/browser/gpu/gpu_driver_bug_list.json $(LOCAL_PATH)/content/browser/gpu/gpu_switching_list.json $(LOCAL_PATH)/content/browser/gpu/software_rendering_list.json $(LOCAL_PATH)/content/browser/resources/accessibility/accessibility.css $(LOCAL_PATH)/content/browser/resources/accessibility/accessibility.html $(LOCAL_PATH)/content/browser/resources/accessibility/accessibility.js $(LOCAL_PATH)/content/browser/resources/gpu/browser_bridge.js $(LOCAL_PATH)/content/browser/resources/gpu/gpu_internals.html $(LOCAL_PATH)/content/browser/resources/gpu/gpu_internals.js $(LOCAL_PATH)/content/browser/resources/gpu/info_view.css $(LOCAL_PATH)/content/browser/resources/gpu/info_view.html $(LOCAL_PATH)/content/browser/resources/gpu/info_view.js $(LOCAL_PATH)/content/browser/resources/indexed_db/indexeddb_internals.css $(LOCAL_PATH)/content/browser/resources/indexed_db/indexeddb_internals.html $(LOCAL_PATH)/content/browser/resources/indexed_db/indexeddb_internals.js $(LOCAL_PATH)/content/browser/resources/media/cache_entry.js $(LOCAL_PATH)/content/browser/resources/media/data_series.js $(LOCAL_PATH)/content/browser/resources/media/disjoint_range_set.js $(LOCAL_PATH)/content/browser/resources/media/dump_creator.js $(LOCAL_PATH)/content/browser/resources/media/event_list.js $(LOCAL_PATH)/content/browser/resources/media/item_store.js $(LOCAL_PATH)/content/browser/resources/media/media_internals.css $(LOCAL_PATH)/content/browser/resources/media/media_internals.html $(LOCAL_PATH)/content/browser/resources/media/media_internals.js $(LOCAL_PATH)/content/browser/resources/media/media_player.js $(LOCAL_PATH)/content/browser/resources/media/metrics.js $(LOCAL_PATH)/content/browser/resources/media/peer_connection_update_table.js $(LOCAL_PATH)/content/browser/resources/media/ssrc_info_manager.js $(LOCAL_PATH)/content/browser/resources/media/stats_graph_helper.js $(LOCAL_PATH)/content/browser/resources/media/stats_table.js $(LOCAL_PATH)/content/browser/resources/media/timeline_graph_view.js $(LOCAL_PATH)/content/browser/resources/media/util.js $(LOCAL_PATH)/content/browser/resources/media/webrtc_internals.css $(LOCAL_PATH)/content/browser/resources/media/webrtc_internals.html $(LOCAL_PATH)/content/browser/resources/media/webrtc_internals.js $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/clique_unittest.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/c_format_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_writer_base_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/rc_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/rc_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/gather/txt_unittest.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grd_reader_unittest.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/grit_runner_unittest.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/lazy_re_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/base_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/include_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/io_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/message_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/misc_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/structure_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/pseudo_unittest.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/tclib_unittest.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/build_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb_unittest.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/util_unittest.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader_unittest.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: Generating resources from content_resources.grd ($@)"
+	$(hide)cd $(gyp_local_path)/content; mkdir -p $(gyp_shared_intermediate_dir)/content/grit $(gyp_shared_intermediate_dir)/content; python ../tools/grit/grit.py -i content_resources.grd build -f ../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/content" -D _chromium -E "CHROMIUM_BUILD=chromium" -D android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D use_concatenated_impulse_responses
+
+$(gyp_shared_intermediate_dir)/content/content_resources.pak: $(gyp_shared_intermediate_dir)/content/grit/content_resources.h ;
+$(gyp_shared_intermediate_dir)/content/content_resources.rc: $(gyp_shared_intermediate_dir)/content/grit/content_resources.h ;
+
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/content/grit/content_resources.h \
+	$(gyp_shared_intermediate_dir)/content/content_resources.pak \
+	$(gyp_shared_intermediate_dir)/content/content_resources.rc
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_generate_content_resources_gyp
+
+# Alias gyp target name.
+.PHONY: generate_content_resources
+generate_content_resources: content_generate_content_resources_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/content/generate_content_resources.target.linux-arm.mk b/content/generate_content_resources.target.linux-arm.mk
index 9b8e909..4f77a75 100644
--- a/content/generate_content_resources.target.linux-arm.mk
+++ b/content/generate_content_resources.target.linux-arm.mk
@@ -18,9 +18,9 @@
 $(gyp_shared_intermediate_dir)/content/grit/content_resources.h: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
 $(gyp_shared_intermediate_dir)/content/grit/content_resources.h: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
 $(gyp_shared_intermediate_dir)/content/grit/content_resources.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
-$(gyp_shared_intermediate_dir)/content/grit/content_resources.h: $(LOCAL_PATH)/tools/gritsettings/resource_ids $(LOCAL_PATH)/content/content_resources.grd $(LOCAL_PATH)/content/browser/gpu/gpu_driver_bug_list.json $(LOCAL_PATH)/content/browser/gpu/gpu_switching_list.json $(LOCAL_PATH)/content/browser/gpu/software_rendering_list.json $(LOCAL_PATH)/content/browser/resources/accessibility/accessibility.css $(LOCAL_PATH)/content/browser/resources/accessibility/accessibility.html $(LOCAL_PATH)/content/browser/resources/accessibility/accessibility.js $(LOCAL_PATH)/content/browser/resources/gpu/browser_bridge.js $(LOCAL_PATH)/content/browser/resources/gpu/gpu_internals.html $(LOCAL_PATH)/content/browser/resources/gpu/gpu_internals.js $(LOCAL_PATH)/content/browser/resources/gpu/info_view.css $(LOCAL_PATH)/content/browser/resources/gpu/info_view.html $(LOCAL_PATH)/content/browser/resources/gpu/info_view.js $(LOCAL_PATH)/content/browser/resources/media/cache_entry.js $(LOCAL_PATH)/content/browser/resources/media/data_series.js $(LOCAL_PATH)/content/browser/resources/media/disjoint_range_set.js $(LOCAL_PATH)/content/browser/resources/media/event_list.js $(LOCAL_PATH)/content/browser/resources/media/item_store.js $(LOCAL_PATH)/content/browser/resources/media/media_internals.css $(LOCAL_PATH)/content/browser/resources/media/media_internals.html $(LOCAL_PATH)/content/browser/resources/media/media_internals.js $(LOCAL_PATH)/content/browser/resources/media/media_player.js $(LOCAL_PATH)/content/browser/resources/media/metrics.js $(LOCAL_PATH)/content/browser/resources/media/stats_graph_helper.js $(LOCAL_PATH)/content/browser/resources/media/timeline_graph_view.js $(LOCAL_PATH)/content/browser/resources/media/util.js $(LOCAL_PATH)/content/browser/resources/media/webrtc_internals.css $(LOCAL_PATH)/content/browser/resources/media/webrtc_internals.html $(LOCAL_PATH)/content/browser/resources/media/webrtc_internals.js $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/clique_unittest.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/c_format_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_writer_base_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/rc_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/rc_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/gather/txt_unittest.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grd_reader_unittest.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/grit_runner_unittest.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/lazy_re_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/base_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/include_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/io_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/message_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/misc_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/structure_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/pseudo_unittest.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/tclib_unittest.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/build_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb_unittest.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/util_unittest.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader_unittest.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
+$(gyp_shared_intermediate_dir)/content/grit/content_resources.h: $(LOCAL_PATH)/tools/gritsettings/resource_ids $(LOCAL_PATH)/content/content_resources.grd $(LOCAL_PATH)/content/browser/gpu/gpu_driver_bug_list.json $(LOCAL_PATH)/content/browser/gpu/gpu_switching_list.json $(LOCAL_PATH)/content/browser/gpu/software_rendering_list.json $(LOCAL_PATH)/content/browser/resources/accessibility/accessibility.css $(LOCAL_PATH)/content/browser/resources/accessibility/accessibility.html $(LOCAL_PATH)/content/browser/resources/accessibility/accessibility.js $(LOCAL_PATH)/content/browser/resources/gpu/browser_bridge.js $(LOCAL_PATH)/content/browser/resources/gpu/gpu_internals.html $(LOCAL_PATH)/content/browser/resources/gpu/gpu_internals.js $(LOCAL_PATH)/content/browser/resources/gpu/info_view.css $(LOCAL_PATH)/content/browser/resources/gpu/info_view.html $(LOCAL_PATH)/content/browser/resources/gpu/info_view.js $(LOCAL_PATH)/content/browser/resources/indexed_db/indexeddb_internals.css $(LOCAL_PATH)/content/browser/resources/indexed_db/indexeddb_internals.html $(LOCAL_PATH)/content/browser/resources/indexed_db/indexeddb_internals.js $(LOCAL_PATH)/content/browser/resources/media/cache_entry.js $(LOCAL_PATH)/content/browser/resources/media/data_series.js $(LOCAL_PATH)/content/browser/resources/media/disjoint_range_set.js $(LOCAL_PATH)/content/browser/resources/media/dump_creator.js $(LOCAL_PATH)/content/browser/resources/media/event_list.js $(LOCAL_PATH)/content/browser/resources/media/item_store.js $(LOCAL_PATH)/content/browser/resources/media/media_internals.css $(LOCAL_PATH)/content/browser/resources/media/media_internals.html $(LOCAL_PATH)/content/browser/resources/media/media_internals.js $(LOCAL_PATH)/content/browser/resources/media/media_player.js $(LOCAL_PATH)/content/browser/resources/media/metrics.js $(LOCAL_PATH)/content/browser/resources/media/peer_connection_update_table.js $(LOCAL_PATH)/content/browser/resources/media/ssrc_info_manager.js $(LOCAL_PATH)/content/browser/resources/media/stats_graph_helper.js $(LOCAL_PATH)/content/browser/resources/media/stats_table.js $(LOCAL_PATH)/content/browser/resources/media/timeline_graph_view.js $(LOCAL_PATH)/content/browser/resources/media/util.js $(LOCAL_PATH)/content/browser/resources/media/webrtc_internals.css $(LOCAL_PATH)/content/browser/resources/media/webrtc_internals.html $(LOCAL_PATH)/content/browser/resources/media/webrtc_internals.js $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/clique_unittest.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/c_format_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_writer_base_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/rc_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/rc_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/gather/txt_unittest.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grd_reader_unittest.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/grit_runner_unittest.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/lazy_re_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/base_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/include_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/io_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/message_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/misc_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/structure_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/pseudo_unittest.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/tclib_unittest.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/build_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb_unittest.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/util_unittest.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader_unittest.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
 	@echo "Gyp action: Generating resources from content_resources.grd ($@)"
-	$(hide)cd $(gyp_local_path)/content; mkdir -p $(gyp_shared_intermediate_dir)/content/grit $(gyp_shared_intermediate_dir)/content; python ../tools/grit/grit.py -i content_resources.grd build -f ../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/content" -D _chromium -E "CHROMIUM_BUILD=chromium" -D android
+	$(hide)cd $(gyp_local_path)/content; mkdir -p $(gyp_shared_intermediate_dir)/content/grit $(gyp_shared_intermediate_dir)/content; python ../tools/grit/grit.py -i content_resources.grd build -f ../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/content" -D _chromium -E "CHROMIUM_BUILD=chromium" -D android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D use_concatenated_impulse_responses
 
 $(gyp_shared_intermediate_dir)/content/content_resources.pak: $(gyp_shared_intermediate_dir)/content/grit/content_resources.h ;
 $(gyp_shared_intermediate_dir)/content/content_resources.rc: $(gyp_shared_intermediate_dir)/content/grit/content_resources.h ;
diff --git a/content/generate_content_resources.target.linux-x86.mk b/content/generate_content_resources.target.linux-x86.mk
index 9b8e909..4f77a75 100644
--- a/content/generate_content_resources.target.linux-x86.mk
+++ b/content/generate_content_resources.target.linux-x86.mk
@@ -18,9 +18,9 @@
 $(gyp_shared_intermediate_dir)/content/grit/content_resources.h: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
 $(gyp_shared_intermediate_dir)/content/grit/content_resources.h: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
 $(gyp_shared_intermediate_dir)/content/grit/content_resources.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
-$(gyp_shared_intermediate_dir)/content/grit/content_resources.h: $(LOCAL_PATH)/tools/gritsettings/resource_ids $(LOCAL_PATH)/content/content_resources.grd $(LOCAL_PATH)/content/browser/gpu/gpu_driver_bug_list.json $(LOCAL_PATH)/content/browser/gpu/gpu_switching_list.json $(LOCAL_PATH)/content/browser/gpu/software_rendering_list.json $(LOCAL_PATH)/content/browser/resources/accessibility/accessibility.css $(LOCAL_PATH)/content/browser/resources/accessibility/accessibility.html $(LOCAL_PATH)/content/browser/resources/accessibility/accessibility.js $(LOCAL_PATH)/content/browser/resources/gpu/browser_bridge.js $(LOCAL_PATH)/content/browser/resources/gpu/gpu_internals.html $(LOCAL_PATH)/content/browser/resources/gpu/gpu_internals.js $(LOCAL_PATH)/content/browser/resources/gpu/info_view.css $(LOCAL_PATH)/content/browser/resources/gpu/info_view.html $(LOCAL_PATH)/content/browser/resources/gpu/info_view.js $(LOCAL_PATH)/content/browser/resources/media/cache_entry.js $(LOCAL_PATH)/content/browser/resources/media/data_series.js $(LOCAL_PATH)/content/browser/resources/media/disjoint_range_set.js $(LOCAL_PATH)/content/browser/resources/media/event_list.js $(LOCAL_PATH)/content/browser/resources/media/item_store.js $(LOCAL_PATH)/content/browser/resources/media/media_internals.css $(LOCAL_PATH)/content/browser/resources/media/media_internals.html $(LOCAL_PATH)/content/browser/resources/media/media_internals.js $(LOCAL_PATH)/content/browser/resources/media/media_player.js $(LOCAL_PATH)/content/browser/resources/media/metrics.js $(LOCAL_PATH)/content/browser/resources/media/stats_graph_helper.js $(LOCAL_PATH)/content/browser/resources/media/timeline_graph_view.js $(LOCAL_PATH)/content/browser/resources/media/util.js $(LOCAL_PATH)/content/browser/resources/media/webrtc_internals.css $(LOCAL_PATH)/content/browser/resources/media/webrtc_internals.html $(LOCAL_PATH)/content/browser/resources/media/webrtc_internals.js $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/clique_unittest.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/c_format_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_writer_base_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/rc_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/rc_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/gather/txt_unittest.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grd_reader_unittest.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/grit_runner_unittest.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/lazy_re_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/base_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/include_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/io_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/message_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/misc_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/structure_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/pseudo_unittest.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/tclib_unittest.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/build_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb_unittest.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/util_unittest.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader_unittest.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
+$(gyp_shared_intermediate_dir)/content/grit/content_resources.h: $(LOCAL_PATH)/tools/gritsettings/resource_ids $(LOCAL_PATH)/content/content_resources.grd $(LOCAL_PATH)/content/browser/gpu/gpu_driver_bug_list.json $(LOCAL_PATH)/content/browser/gpu/gpu_switching_list.json $(LOCAL_PATH)/content/browser/gpu/software_rendering_list.json $(LOCAL_PATH)/content/browser/resources/accessibility/accessibility.css $(LOCAL_PATH)/content/browser/resources/accessibility/accessibility.html $(LOCAL_PATH)/content/browser/resources/accessibility/accessibility.js $(LOCAL_PATH)/content/browser/resources/gpu/browser_bridge.js $(LOCAL_PATH)/content/browser/resources/gpu/gpu_internals.html $(LOCAL_PATH)/content/browser/resources/gpu/gpu_internals.js $(LOCAL_PATH)/content/browser/resources/gpu/info_view.css $(LOCAL_PATH)/content/browser/resources/gpu/info_view.html $(LOCAL_PATH)/content/browser/resources/gpu/info_view.js $(LOCAL_PATH)/content/browser/resources/indexed_db/indexeddb_internals.css $(LOCAL_PATH)/content/browser/resources/indexed_db/indexeddb_internals.html $(LOCAL_PATH)/content/browser/resources/indexed_db/indexeddb_internals.js $(LOCAL_PATH)/content/browser/resources/media/cache_entry.js $(LOCAL_PATH)/content/browser/resources/media/data_series.js $(LOCAL_PATH)/content/browser/resources/media/disjoint_range_set.js $(LOCAL_PATH)/content/browser/resources/media/dump_creator.js $(LOCAL_PATH)/content/browser/resources/media/event_list.js $(LOCAL_PATH)/content/browser/resources/media/item_store.js $(LOCAL_PATH)/content/browser/resources/media/media_internals.css $(LOCAL_PATH)/content/browser/resources/media/media_internals.html $(LOCAL_PATH)/content/browser/resources/media/media_internals.js $(LOCAL_PATH)/content/browser/resources/media/media_player.js $(LOCAL_PATH)/content/browser/resources/media/metrics.js $(LOCAL_PATH)/content/browser/resources/media/peer_connection_update_table.js $(LOCAL_PATH)/content/browser/resources/media/ssrc_info_manager.js $(LOCAL_PATH)/content/browser/resources/media/stats_graph_helper.js $(LOCAL_PATH)/content/browser/resources/media/stats_table.js $(LOCAL_PATH)/content/browser/resources/media/timeline_graph_view.js $(LOCAL_PATH)/content/browser/resources/media/util.js $(LOCAL_PATH)/content/browser/resources/media/webrtc_internals.css $(LOCAL_PATH)/content/browser/resources/media/webrtc_internals.html $(LOCAL_PATH)/content/browser/resources/media/webrtc_internals.js $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/clique_unittest.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/c_format_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_writer_base_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/rc_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/rc_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/gather/txt_unittest.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grd_reader_unittest.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/grit_runner_unittest.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/lazy_re_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/base_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/include_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/io_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/message_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/misc_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/structure_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/pseudo_unittest.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/tclib_unittest.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/build_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb_unittest.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/util_unittest.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader_unittest.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
 	@echo "Gyp action: Generating resources from content_resources.grd ($@)"
-	$(hide)cd $(gyp_local_path)/content; mkdir -p $(gyp_shared_intermediate_dir)/content/grit $(gyp_shared_intermediate_dir)/content; python ../tools/grit/grit.py -i content_resources.grd build -f ../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/content" -D _chromium -E "CHROMIUM_BUILD=chromium" -D android
+	$(hide)cd $(gyp_local_path)/content; mkdir -p $(gyp_shared_intermediate_dir)/content/grit $(gyp_shared_intermediate_dir)/content; python ../tools/grit/grit.py -i content_resources.grd build -f ../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/content" -D _chromium -E "CHROMIUM_BUILD=chromium" -D android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D use_concatenated_impulse_responses
 
 $(gyp_shared_intermediate_dir)/content/content_resources.pak: $(gyp_shared_intermediate_dir)/content/grit/content_resources.h ;
 $(gyp_shared_intermediate_dir)/content/content_resources.rc: $(gyp_shared_intermediate_dir)/content/grit/content_resources.h ;
diff --git a/content/gpu/gpu_child_thread.cc b/content/gpu/gpu_child_thread.cc
index b8ce0a9..a4bc0ff 100644
--- a/content/gpu/gpu_child_thread.cc
+++ b/content/gpu/gpu_child_thread.cc
@@ -38,7 +38,7 @@
 
   // If we are not on main thread in child process, send through
   // the sync_message_filter; otherwise send directly.
-  if (MessageLoop::current() !=
+  if (base::MessageLoop::current() !=
       ChildProcess::current()->main_thread()->message_loop()) {
     ChildProcess::current()->main_thread()->sync_message_filter()->Send(
         new GpuHostMsg_OnLogMessage(severity, header, message));
@@ -82,6 +82,9 @@
 }
 
 GpuChildThread::~GpuChildThread() {
+}
+
+void GpuChildThread::Shutdown() {
   logging::SetLogMessageHandler(NULL);
 }
 
@@ -124,7 +127,7 @@
 
   if (dead_on_arrival_) {
     VLOG(1) << "Exiting GPU process due to errors during initialization";
-    MessageLoop::current()->Quit();
+    base::MessageLoop::current()->Quit();
     return;
   }
 
@@ -159,7 +162,7 @@
 }
 
 void GpuChildThread::StopWatchdog() {
-  if (watchdog_thread_.get()) {
+  if (watchdog_thread_) {
     watchdog_thread_->Stop();
   }
 }
@@ -190,14 +193,14 @@
 #if defined(OS_WIN)
   if (!in_browser_process_) {
     // The unsandboxed GPU process fulfilled its duty.  Rest in peace.
-    MessageLoop::current()->Quit();
+    base::MessageLoop::current()->Quit();
   }
 #endif  // OS_WIN
 }
 
 void GpuChildThread::OnGetVideoMemoryUsageStats() {
   GPUVideoMemoryUsageStats video_memory_usage_stats;
-  if (gpu_channel_manager_.get())
+  if (gpu_channel_manager_)
     gpu_channel_manager_->gpu_memory_manager()->GetVideoMemoryUsageStats(
         &video_memory_usage_stats);
   Send(new GpuHostMsg_VideoMemoryUsageStats(video_memory_usage_stats));
@@ -205,7 +208,7 @@
 
 void GpuChildThread::OnClean() {
   VLOG(1) << "GPU: Removing all contexts";
-  if (gpu_channel_manager_.get())
+  if (gpu_channel_manager_)
     gpu_channel_manager_->LoseAllContexts();
 }
 
@@ -226,7 +229,7 @@
 
 void GpuChildThread::OnDisableWatchdog() {
   VLOG(1) << "GPU: Disabling watchdog thread";
-  if (watchdog_thread_.get()) {
+  if (watchdog_thread_) {
     // Disarm the watchdog before shutting down the message loop. This prevents
     // the future posting of tasks to the message loop.
     if (watchdog_thread_->message_loop())
diff --git a/content/gpu/gpu_child_thread.h b/content/gpu/gpu_child_thread.h
index 58c6c10..0d4baeb 100644
--- a/content/gpu/gpu_child_thread.h
+++ b/content/gpu/gpu_child_thread.h
@@ -43,6 +43,8 @@
 
   virtual ~GpuChildThread();
 
+  virtual void Shutdown() OVERRIDE;
+
   void Init(const base::Time& process_start_time);
   void StopWatchdog();
 
diff --git a/content/gpu/gpu_info_collector.cc b/content/gpu/gpu_info_collector.cc
index 86fb0c5..0d51b69 100644
--- a/content/gpu/gpu_info_collector.cc
+++ b/content/gpu/gpu_info_collector.cc
@@ -7,10 +7,11 @@
 #include <string>
 #include <vector>
 
+#include "base/debug/trace_event.h"
 #include "base/logging.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/string_number_conversions.h"
-#include "base/string_piece.h"
+#include "base/strings/string_piece.h"
 #include "base/strings/string_split.h"
 #include "ui/gl/gl_bindings.h"
 #include "ui/gl/gl_context.h"
@@ -21,7 +22,7 @@
 scoped_refptr<gfx::GLSurface> InitializeGLSurface() {
   scoped_refptr<gfx::GLSurface> surface(
       gfx::GLSurface::CreateOffscreenGLSurface(false, gfx::Size(1, 1)));
-  if (!surface.get()) {
+  if (!surface) {
     LOG(ERROR) << "gfx::GLContext::CreateOffscreenGLSurface failed";
     return NULL;
   }
@@ -35,7 +36,7 @@
       gfx::GLContext::CreateGLContext(NULL,
                                       surface,
                                       gfx::PreferIntegratedGpu));
-  if (!context.get()) {
+  if (!context) {
     LOG(ERROR) << "gfx::GLContext::CreateGLContext failed";
     return NULL;
   }
@@ -53,7 +54,7 @@
       reinterpret_cast<const char*>(glGetString(pname));
   if (gl_string)
     return std::string(gl_string);
-  return "";
+  return std::string();
 }
 
 // Return a version string in the format of "major.minor".
@@ -71,7 +72,7 @@
     if (pieces.size() >= 2)
       return pieces[0] + "." + pieces[1];
   }
-  return "";
+  return std::string();
 }
 
 }  // namespace anonymous
@@ -79,17 +80,18 @@
 namespace gpu_info_collector {
 
 bool CollectGraphicsInfoGL(content::GPUInfo* gpu_info) {
+  TRACE_EVENT0("startup", "gpu_info_collector::CollectGraphicsInfoGL");
   if (!gfx::GLSurface::InitializeOneOff()) {
     LOG(ERROR) << "gfx::GLSurface::InitializeOneOff() failed";
     return false;
   }
 
   scoped_refptr<gfx::GLSurface> surface(InitializeGLSurface());
-  if (!surface.get())
+  if (!surface)
     return false;
 
   scoped_refptr<gfx::GLContext> context(InitializeGLContext(surface.get()));
-  if (!context.get())
+  if (!context)
     return false;
 
   gpu_info->gl_renderer = GetGLString(GL_RENDERER);
diff --git a/content/gpu/gpu_info_collector_android.cc b/content/gpu/gpu_info_collector_android.cc
index 157e5b6..a190c9d 100644
--- a/content/gpu/gpu_info_collector_android.cc
+++ b/content/gpu/gpu_info_collector_android.cc
@@ -8,8 +8,8 @@
 #include "base/command_line.h"
 #include "base/logging.h"
 #include "base/string_number_conversions.h"
-#include "base/string_piece.h"
 #include "base/string_util.h"
+#include "base/strings/string_piece.h"
 #include "base/strings/string_split.h"
 #include "cc/base/switches.h"
 #include "content/public/common/content_switches.h"
@@ -74,6 +74,8 @@
   bool is_arm = vendor.find("arm") != std::string::npos;
   bool is_qualcomm = vendor.find("qualcomm") != std::string::npos;
   bool is_mali_t604 = is_arm && renderer.find("mali-t604") != std::string::npos;
+  bool is_vivante = vendor.find("vivante") != std::string::npos;
+  is_vivante |= vendor.find("hisilicon") != std::string::npos;
 
   base::android::BuildInfo* build_info =
       base::android::BuildInfo::GetInstance();
@@ -82,10 +84,17 @@
   bool is_nexus7 = model.find("nexus 7") != std::string::npos;
   bool is_nexus10 = model.find("nexus 10") != std::string::npos;
 
+  // Virtual contexts crash when switching surfaces, but only on SDK 16,
+  // so we us full context switching for now. If virtual contexts can
+  // avoid some of it's extra surface switches, or Qualcomm gives us
+  // a more directed work-around, we can remove this.
+  int sdk_int = base::android::BuildInfo::GetInstance()->sdk_int();
+
   // IMG: avoid context switching perf problems, crashes with share groups
   // Mali-T604: http://crbug.com/154715
   // QualComm, NVIDIA: Crashes with share groups
-  if (is_img || is_mali_t604 || is_qualcomm || is_nexus7) {
+  if (is_vivante || is_img || is_mali_t604 || is_nexus7
+      || (is_qualcomm && sdk_int != 16)) {
     CommandLine::ForCurrentProcess()->AppendSwitch(
         switches::kEnableVirtualGLContexts);
   }
diff --git a/content/gpu/gpu_info_collector_mac.mm b/content/gpu/gpu_info_collector_mac.mm
index f8aefe1..b3ded51 100644
--- a/content/gpu/gpu_info_collector_mac.mm
+++ b/content/gpu/gpu_info_collector_mac.mm
@@ -12,9 +12,9 @@
 #include "base/mac/scoped_cftyperef.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/string_number_conversions.h"
-#include "base/string_piece.h"
 #include "base/string_util.h"
-#include "base/sys_string_conversions.h"
+#include "base/strings/string_piece.h"
+#include "base/strings/sys_string_conversions.h"
 #include "ui/gl/gl_bindings.h"
 #include "ui/gl/gl_context.h"
 #include "ui/gl/gl_implementation.h"
diff --git a/content/gpu/gpu_info_collector_win.cc b/content/gpu/gpu_info_collector_win.cc
index 462459b..402a4b1 100644
--- a/content/gpu/gpu_info_collector_win.cc
+++ b/content/gpu/gpu_info_collector_win.cc
@@ -189,15 +189,13 @@
 bool IsLenovoDCuteInstalled() {
   base::win::RegKey key;
 
-  if (FAILED(key.Open(
-      HKEY_LOCAL_MACHINE, L"SOFTWARE", KEY_READ | KEY_WOW64_64KEY))) {
-    return false;
-  }
-
-  if (FAILED(key.OpenKey(L"Lenovo", KEY_READ | KEY_WOW64_64KEY)))
+  if (key.Open(HKEY_LOCAL_MACHINE, L"SOFTWARE", KEY_READ | KEY_WOW64_64KEY))
     return false;
 
-  if (FAILED(key.OpenKey(L"Lenovo dCute", KEY_READ | KEY_WOW64_64KEY)))
+  if (key.OpenKey(L"Lenovo", KEY_READ | KEY_WOW64_64KEY))
+    return false;
+
+  if (key.OpenKey(L"Lenovo dCute", KEY_READ | KEY_WOW64_64KEY))
     return false;
 
   return true;
@@ -375,7 +373,7 @@
 
 #if !defined(GOOGLE_CHROME_BUILD)
 AMDVideoCardType GetAMDVideocardType() {
-  return UNKNOWN;
+  return STANDALONE;
 }
 #else
 // This function has a real implementation for official builds that can
@@ -606,7 +604,7 @@
   // Collect basic information about supported D3D11 features. Delay for 45
   // seconds so as not to regress performance tests.
   if (D3D11ShouldWork(*gpu_info)) {
-    MessageLoop::current()->PostDelayedTask(
+    base::MessageLoop::current()->PostDelayedTask(
         FROM_HERE,
         base::Bind(&CollectD3D11Support),
         base::TimeDelta::FromSeconds(45));
diff --git a/content/gpu/gpu_info_collector_linux.cc b/content/gpu/gpu_info_collector_x11.cc
similarity index 86%
rename from content/gpu/gpu_info_collector_linux.cc
rename to content/gpu/gpu_info_collector_x11.cc
index 56b3800..2d43167 100644
--- a/content/gpu/gpu_info_collector_linux.cc
+++ b/content/gpu/gpu_info_collector_x11.cc
@@ -13,8 +13,8 @@
 #include "base/logging.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/message_loop.h"
-#include "base/string_piece.h"
 #include "base/string_util.h"
+#include "base/strings/string_piece.h"
 #include "base/strings/string_split.h"
 #include "base/strings/string_tokenizer.h"
 #include "library_loaders/libpci.h"
@@ -130,34 +130,6 @@
     gpu.vendor_id = device->vendor_id;
     gpu.device_id = device->device_id;
 
-    const int buffer_size = 255;
-    scoped_array<char> buffer(new char[buffer_size]);
-    // The current implementation of pci_lookup_name returns the same pointer
-    // as the passed in upon success, and a different one (NULL or a pointer
-    // to an error message) upon failure.
-    if ((libpci_loader.pci_lookup_name)(access,
-                                        buffer.get(),
-                                        buffer_size,
-                                        1,
-                                        device->vendor_id) == buffer.get()) {
-      gpu.vendor_string = buffer.get();
-    }
-    if ((libpci_loader.pci_lookup_name)(access,
-                                        buffer.get(),
-                                        buffer_size,
-                                        2,
-                                        device->vendor_id,
-                                        device->device_id) == buffer.get()) {
-      std::string device_string = buffer.get();
-      size_t begin = device_string.find_first_of('[');
-      size_t end = device_string.find_last_of(']');
-      if (begin != std::string::npos && end != std::string::npos &&
-          begin < end) {
-        device_string = device_string.substr(begin + 1, end - begin - 1);
-      }
-      gpu.device_string = device_string;
-    }
-
     if (!primary_gpu_identified) {
       primary_gpu_identified = true;
       gpu_info->gpu = gpu;
diff --git a/content/gpu/gpu_main.cc b/content/gpu/gpu_main.cc
index 44d00dd..6c1045f 100644
--- a/content/gpu/gpu_main.cc
+++ b/content/gpu/gpu_main.cc
@@ -16,6 +16,7 @@
 #include "base/threading/platform_thread.h"
 #include "build/build_config.h"
 #include "content/common/gpu/gpu_config.h"
+#include "content/common/sandbox_linux.h"
 #include "content/gpu/gpu_child_thread.h"
 #include "content/gpu/gpu_info_collector.h"
 #include "content/gpu/gpu_process.h"
@@ -53,7 +54,12 @@
 
 namespace content {
 namespace {
-void WarmUpSandbox(const GPUInfo&, bool);
+void WarmUpSandbox();
+#if defined(OS_LINUX)
+bool StartSandboxLinux(const GPUInfo&, GpuWatchdogThread*, bool);
+#elif defined(OS_WIN)
+bool StartSandboxWindows(const sandbox::SandboxInterfaceInfo*);
+#endif
 }
 
 // Main function for starting the Gpu process.
@@ -101,7 +107,7 @@
   // GpuMsg_Initialize message from the browser.
   bool dead_on_arrival = false;
 
-  MessageLoop::Type message_loop_type = MessageLoop::TYPE_IO;
+  base::MessageLoop::Type message_loop_type = base::MessageLoop::TYPE_IO;
 #if defined(OS_WIN)
   // Unless we're running on desktop GL, we don't need a UI message
   // loop, so avoid its use to work around apparent problems with some
@@ -109,13 +115,13 @@
   if (command_line.HasSwitch(switches::kUseGL) &&
       command_line.GetSwitchValueASCII(switches::kUseGL) ==
           gfx::kGLImplementationDesktopName) {
-      message_loop_type = MessageLoop::TYPE_UI;
+    message_loop_type = base::MessageLoop::TYPE_UI;
   }
 #elif defined(OS_LINUX)
-  message_loop_type = MessageLoop::TYPE_DEFAULT;
+  message_loop_type = base::MessageLoop::TYPE_DEFAULT;
 #endif
 
-  MessageLoop main_message_loop(message_loop_type);
+  base::MessageLoop main_message_loop(message_loop_type);
   base::PlatformThread::SetName("CrGpuMain");
 
   // In addition to disabling the watchdog if the command line switch is
@@ -169,18 +175,39 @@
       command_line.GetSwitchValueASCII(switches::kGpuDriverVersion);
   GetContentClient()->SetGpuInfo(gpu_info);
 
-  // We need to track that information for the WarmUpSandbox function.
+  // Warm up resources that don't need access to GPUInfo.
+  WarmUpSandbox();
+
+#if defined(OS_LINUX)
+  bool initialized_sandbox = false;
   bool initialized_gl_context = false;
+  bool should_initialize_gl_context = false;
+#if defined(OS_CHROMEOS) && defined(ARCH_CPU_ARMEL)
+  // On Chrome OS ARM, GPU driver userspace creates threads when initializing
+  // a GL context, so start the sandbox early.
+  gpu_info.sandboxed = StartSandboxLinux(gpu_info, watchdog_thread.get(),
+                                         should_initialize_gl_context);
+  initialized_sandbox = true;
+#endif
+#endif  // defined(OS_LINUX)
+
   // Load and initialize the GL implementation and locate the GL entry points.
   if (gfx::GLSurface::InitializeOneOff()) {
+    // We need to collect GL strings (VENDOR, RENDERER) for blacklisting
+    // purposes. However, on Mac we don't actually use them. As documented in
+    // crbug.com/222934, due to some driver issues, glGetString could take
+    // multiple seconds to finish, which in turn cause the GPU process to crash.
+    // By skipping the following code on Mac, we don't really lose anything,
+    // because the basic GPU information is passed down from browser process
+    // and we already registered them through SetGpuInfo() above.
+#if !defined(OS_MACOSX)
     if (!gpu_info_collector::CollectContextGraphicsInfo(&gpu_info))
       VLOG(1) << "gpu_info_collector::CollectGraphicsInfo failed";
     GetContentClient()->SetGpuInfo(gpu_info);
 
-    // We know that CollectGraphicsInfo will initialize a GLContext.
+#if defined(OS_LINUX)
     initialized_gl_context = true;
-
-#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
+#if !defined(OS_CHROMEOS)
     if (gpu_info.gpu.vendor_id == 0x10de &&  // NVIDIA
         gpu_info.driver_vendor == "NVIDIA") {
       base::ThreadRestrictions::AssertIOAllowed();
@@ -190,7 +217,9 @@
         dead_on_arrival = true;
       }
     }
-#endif  // OS_CHROMEOS
+#endif  // !defined(OS_CHROMEOS)
+#endif  // defined(OS_LINUX)
+#endif  // !defined(OS_MACOSX)
   } else {
     VLOG(1) << "gfx::GLSurface::InitializeOneOff failed";
     gpu_info.gpu_accessible = false;
@@ -212,47 +241,15 @@
     watchdog_thread = NULL;
   }
 
-  {
-    const bool should_initialize_gl_context = !initialized_gl_context &&
-                                              !dead_on_arrival;
-    // Warm up the current process before enabling the sandbox.
-    WarmUpSandbox(gpu_info, should_initialize_gl_context);
-  }
-
 #if defined(OS_LINUX)
-  {
-    TRACE_EVENT0("gpu", "Initialize sandbox");
-    bool do_init_sandbox = true;
+  should_initialize_gl_context = !initialized_gl_context &&
+                                 !dead_on_arrival;
 
-#if defined(OS_CHROMEOS) && defined(NDEBUG)
-    // On Chrome OS and when not on a debug build, initialize
-    // the GPU process' sandbox only for Intel GPUs.
-    do_init_sandbox = gpu_info.gpu.vendor_id == 0x8086;   // Intel GPU.
-#endif
-
-    if (do_init_sandbox) {
-      if (watchdog_thread.get())
-        watchdog_thread->Stop();
-      gpu_info.sandboxed = InitializeSandbox();
-      if (watchdog_thread.get())
-        watchdog_thread->Start();
-    }
-  }
-#endif
-
-#if defined(OS_WIN)
-  {
-    TRACE_EVENT0("gpu", "Lower token");
-    // For windows, if the target_services interface is not zero, the process
-    // is sandboxed and we must call LowerToken() before rendering untrusted
-    // content.
-    sandbox::TargetServices* target_services =
-        parameters.sandbox_info->target_services;
-    if (target_services) {
-      target_services->LowerToken();
-      gpu_info.sandboxed = true;
-    }
-  }
+  if (!initialized_sandbox)
+    gpu_info.sandboxed = StartSandboxLinux(gpu_info, watchdog_thread.get(),
+                                           should_initialize_gl_context);
+#elif defined(OS_WIN)
+  gpu_info.sandboxed = StartSandboxWindows(parameters.sandbox_info);
 #endif
 
   GpuProcess gpu_process;
@@ -280,7 +277,7 @@
 void CreateDummyGlContext() {
   scoped_refptr<gfx::GLSurface> surface(
       gfx::GLSurface::CreateOffscreenGLSurface(false, gfx::Size(1, 1)));
-  if (!surface.get()) {
+  if (!surface) {
     VLOG(1) << "gfx::GLSurface::CreateOffscreenGLSurface failed";
     return;
   }
@@ -291,7 +288,7 @@
       gfx::GLContext::CreateGLContext(NULL,
                                       surface,
                                       gfx::PreferDiscreteGpu));
-  if (!context.get()) {
+  if (!context) {
     VLOG(1) << "gfx::GLContext::CreateGLContext failed";
     return;
   }
@@ -305,8 +302,7 @@
 }
 #endif
 
-void WarmUpSandbox(const GPUInfo& gpu_info,
-                   bool should_initialize_gl_context) {
+void WarmUpSandbox() {
   {
     TRACE_EVENT0("gpu", "Warm up rand");
     // Warm up the random subsystem, which needs to be done pre-sandbox on all
@@ -332,24 +328,8 @@
   VaapiVideoDecodeAccelerator::PreSandboxInitialization();
 #endif
 
-#if defined(OS_LINUX)
-  // We special case Optimus since the vendor_id we see may not be Nvidia.
-  bool uses_nvidia_driver = (gpu_info.gpu.vendor_id == 0x10de &&  // NVIDIA.
-                             gpu_info.driver_vendor == "NVIDIA") ||
-                            gpu_info.optimus;
-  if (uses_nvidia_driver && should_initialize_gl_context) {
-    // We need this on Nvidia to pre-open /dev/nvidiactl and /dev/nvidia0.
-    CreateDummyGlContext();
-  }
-#endif
-
 #if defined(OS_WIN)
   {
-    TRACE_EVENT0("gpu", "Initialize COM");
-    base::win::ScopedCOMInitializer com_initializer;
-  }
-
-  {
     TRACE_EVENT0("gpu", "Preload setupapi.dll");
     // Preload this DLL because the sandbox prevents it from loading.
     LoadLibrary(L"setupapi.dll");
@@ -363,6 +343,57 @@
 #endif
 }
 
+#if defined(OS_LINUX)
+void WarmUpSandboxNvidia(const GPUInfo& gpu_info,
+                         bool should_initialize_gl_context) {
+  // We special case Optimus since the vendor_id we see may not be Nvidia.
+  bool uses_nvidia_driver = (gpu_info.gpu.vendor_id == 0x10de &&  // NVIDIA.
+                             gpu_info.driver_vendor == "NVIDIA") ||
+                            gpu_info.optimus;
+  if (uses_nvidia_driver && should_initialize_gl_context) {
+    // We need this on Nvidia to pre-open /dev/nvidiactl and /dev/nvidia0.
+    CreateDummyGlContext();
+  }
+}
+
+bool StartSandboxLinux(const GPUInfo& gpu_info,
+                       GpuWatchdogThread* watchdog_thread,
+                       bool should_initialize_gl_context) {
+  TRACE_EVENT0("gpu", "Initialize sandbox");
+
+  bool res = false;
+
+  WarmUpSandboxNvidia(gpu_info, should_initialize_gl_context);
+
+  if (watchdog_thread)
+    watchdog_thread->Stop();
+  // LinuxSandbox::InitializeSandbox() must always be called
+  // with only one thread.
+  res = LinuxSandbox::InitializeSandbox();
+  if (watchdog_thread)
+    watchdog_thread->Start();
+
+  return res;
+}
+#endif  // defined(OS_LINUX)
+
+#if defined(OS_WIN)
+bool StartSandboxWindows(const sandbox::SandboxInterfaceInfo* sandbox_info) {
+  TRACE_EVENT0("gpu", "Lower token");
+
+  // For Windows, if the target_services interface is not zero, the process
+  // is sandboxed and we must call LowerToken() before rendering untrusted
+  // content.
+  sandbox::TargetServices* target_services = sandbox_info->target_services;
+  if (target_services) {
+    target_services->LowerToken();
+    return true;
+  }
+
+  return false;
+}
+#endif  // defined(OS_WIN)
+
 }  // namespace.
 
 }  // namespace content
diff --git a/content/gpu/gpu_watchdog_thread.cc b/content/gpu/gpu_watchdog_thread.cc
index 5557571..09e710e 100644
--- a/content/gpu/gpu_watchdog_thread.cc
+++ b/content/gpu/gpu_watchdog_thread.cc
@@ -25,15 +25,15 @@
 
 GpuWatchdogThread::GpuWatchdogThread(int timeout)
     : base::Thread("Watchdog"),
-      watched_message_loop_(MessageLoop::current()),
+      watched_message_loop_(base::MessageLoop::current()),
       timeout_(base::TimeDelta::FromMilliseconds(timeout)),
       armed_(false),
 #if defined(OS_WIN)
       watched_thread_handle_(0),
       arm_cpu_time_(),
 #endif
-      ALLOW_THIS_IN_INITIALIZER_LIST(task_observer_(this)),
-      ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) {
+      task_observer_(this),
+      weak_factory_(this) {
   DCHECK(timeout >= 0);
 
 #if defined(OS_WIN)
diff --git a/content/gpu/gpu_watchdog_thread.h b/content/gpu/gpu_watchdog_thread.h
index 49c6236..22cc887 100644
--- a/content/gpu/gpu_watchdog_thread.h
+++ b/content/gpu/gpu_watchdog_thread.h
@@ -38,7 +38,7 @@
 
   // An object of this type intercepts the reception and completion of all tasks
   // on the watched thread and checks whether the watchdog is armed.
-  class GpuWatchdogTaskObserver : public MessageLoop::TaskObserver {
+  class GpuWatchdogTaskObserver : public base::MessageLoop::TaskObserver {
    public:
     explicit GpuWatchdogTaskObserver(GpuWatchdogThread* watchdog);
     virtual ~GpuWatchdogTaskObserver();
@@ -62,7 +62,7 @@
   base::TimeDelta GetWatchedThreadTime();
 #endif
 
-  MessageLoop* watched_message_loop_;
+  base::MessageLoop* watched_message_loop_;
   base::TimeDelta timeout_;
   volatile bool armed_;
   GpuWatchdogTaskObserver task_observer_;
diff --git a/content/surface_jni_headers.target.linux-arm.mk b/content/java_set_jni_headers.target.darwin-arm.mk
similarity index 79%
rename from content/surface_jni_headers.target.linux-arm.mk
rename to content/java_set_jni_headers.target.darwin-arm.mk
index 6376b54..6c3483c 100644
--- a/content/surface_jni_headers.target.linux-arm.mk
+++ b/content/java_set_jni_headers.target.darwin-arm.mk
@@ -3,8 +3,8 @@
 include $(CLEAR_VARS)
 
 LOCAL_MODULE_CLASS := GYP
-LOCAL_MODULE := content_surface_jni_headers_gyp
-LOCAL_MODULE_STEM := surface_jni_headers
+LOCAL_MODULE := content_java_set_jni_headers_gyp
+LOCAL_MODULE_STEM := java_set_jni_headers
 LOCAL_MODULE_SUFFIX := .stamp
 LOCAL_MODULE_TAGS := optional
 gyp_intermediate_dir := $(call local-intermediates-dir)
@@ -14,24 +14,24 @@
 GYP_TARGET_DEPENDENCIES :=
 
 ### Rules for action "generate_jni_headers_from_jar_file":
-$(gyp_shared_intermediate_dir)/content/jni/Surface_jni.h: gyp_local_path := $(LOCAL_PATH)
-$(gyp_shared_intermediate_dir)/content/jni/Surface_jni.h: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
-$(gyp_shared_intermediate_dir)/content/jni/Surface_jni.h: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
-$(gyp_shared_intermediate_dir)/content/jni/Surface_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
-$(gyp_shared_intermediate_dir)/content/jni/Surface_jni.h: $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(GYP_ABS_ANDROID_TOP_DIR)/prebuilts/sdk/17/android.jar $(GYP_TARGET_DEPENDENCIES)
-	@echo "Gyp action: Generating JNI bindings from  $(GYP_ABS_ANDROID_TOP_DIR)/prebuilts/sdk/17/android.jar/android/view/Surface.class ($@)"
-	$(hide)cd $(gyp_local_path)/content; mkdir -p $(gyp_shared_intermediate_dir)/content/jni; ../base/android/jni_generator/jni_generator.py -j "$(GYP_ABS_ANDROID_TOP_DIR)/prebuilts/sdk/17/android.jar" --input_file android/view/Surface.class --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --optimize_generation 0
+$(gyp_shared_intermediate_dir)/content/jni/HashSet_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/HashSet_jni.h: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/HashSet_jni.h: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/HashSet_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/HashSet_jni.h: $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(GYP_ABS_ANDROID_TOP_DIR)/prebuilts/sdk/17/android.jar $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: Generating JNI bindings from  $(GYP_ABS_ANDROID_TOP_DIR)/prebuilts/sdk/17/android.jar/java/util/HashSet.class ($@)"
+	$(hide)cd $(gyp_local_path)/content; mkdir -p $(gyp_shared_intermediate_dir)/content/jni; ../base/android/jni_generator/jni_generator.py -j "$(GYP_ABS_ANDROID_TOP_DIR)/prebuilts/sdk/17/android.jar" --input_file java/util/HashSet.class --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --optimize_generation 0
 
 
 
 GYP_GENERATED_OUTPUTS := \
-	$(gyp_shared_intermediate_dir)/content/jni/Surface_jni.h
+	$(gyp_shared_intermediate_dir)/content/jni/HashSet_jni.h
 
 # Make sure our deps and generated files are built first.
 LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
 
 LOCAL_GENERATED_SOURCES := \
-	$(gyp_shared_intermediate_dir)/content/jni/Surface_jni.h
+	$(gyp_shared_intermediate_dir)/content/jni/HashSet_jni.h
 
 GYP_COPIED_SOURCE_ORIGIN_DIRS :=
 
@@ -75,7 +75,6 @@
 
 MY_DEFS := \
 	'-DCONTENT_IMPLEMENTATION' \
-	'-DUSE_SKIA' \
 	'-D_FILE_OFFSET_BITS=64' \
 	'-DUSE_LINUX_BREAKPAD' \
 	'-DNO_TCMALLOC' \
@@ -83,7 +82,6 @@
 	'-DCHROMIUM_BUILD' \
 	'-DUSE_LIBJPEG_TURBO=1' \
 	'-DUSE_PROPRIETARY_CODECS' \
-	'-DENABLE_PEPPER_THREADING' \
 	'-DENABLE_GPU=1' \
 	'-DUSE_OPENSSL=1' \
 	'-DENABLE_EGLIMAGE=1' \
@@ -123,11 +121,11 @@
 ### Rules for final target.
 # Add target alias to "gyp_all_modules" target.
 .PHONY: gyp_all_modules
-gyp_all_modules: content_surface_jni_headers_gyp
+gyp_all_modules: content_java_set_jni_headers_gyp
 
 # Alias gyp target name.
-.PHONY: surface_jni_headers
-surface_jni_headers: content_surface_jni_headers_gyp
+.PHONY: java_set_jni_headers
+java_set_jni_headers: content_java_set_jni_headers_gyp
 
 LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
 LOCAL_UNINSTALLABLE_MODULE := true
diff --git a/content/surface_jni_headers.target.linux-x86.mk b/content/java_set_jni_headers.target.darwin-x86.mk
similarity index 78%
rename from content/surface_jni_headers.target.linux-x86.mk
rename to content/java_set_jni_headers.target.darwin-x86.mk
index 9ce34f2..502136f 100644
--- a/content/surface_jni_headers.target.linux-x86.mk
+++ b/content/java_set_jni_headers.target.darwin-x86.mk
@@ -3,8 +3,8 @@
 include $(CLEAR_VARS)
 
 LOCAL_MODULE_CLASS := GYP
-LOCAL_MODULE := content_surface_jni_headers_gyp
-LOCAL_MODULE_STEM := surface_jni_headers
+LOCAL_MODULE := content_java_set_jni_headers_gyp
+LOCAL_MODULE_STEM := java_set_jni_headers
 LOCAL_MODULE_SUFFIX := .stamp
 LOCAL_MODULE_TAGS := optional
 gyp_intermediate_dir := $(call local-intermediates-dir)
@@ -14,24 +14,24 @@
 GYP_TARGET_DEPENDENCIES :=
 
 ### Rules for action "generate_jni_headers_from_jar_file":
-$(gyp_shared_intermediate_dir)/content/jni/Surface_jni.h: gyp_local_path := $(LOCAL_PATH)
-$(gyp_shared_intermediate_dir)/content/jni/Surface_jni.h: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
-$(gyp_shared_intermediate_dir)/content/jni/Surface_jni.h: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
-$(gyp_shared_intermediate_dir)/content/jni/Surface_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
-$(gyp_shared_intermediate_dir)/content/jni/Surface_jni.h: $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(GYP_ABS_ANDROID_TOP_DIR)/prebuilts/sdk/17/android.jar $(GYP_TARGET_DEPENDENCIES)
-	@echo "Gyp action: Generating JNI bindings from  $(GYP_ABS_ANDROID_TOP_DIR)/prebuilts/sdk/17/android.jar/android/view/Surface.class ($@)"
-	$(hide)cd $(gyp_local_path)/content; mkdir -p $(gyp_shared_intermediate_dir)/content/jni; ../base/android/jni_generator/jni_generator.py -j "$(GYP_ABS_ANDROID_TOP_DIR)/prebuilts/sdk/17/android.jar" --input_file android/view/Surface.class --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --optimize_generation 0
+$(gyp_shared_intermediate_dir)/content/jni/HashSet_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/HashSet_jni.h: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/HashSet_jni.h: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
+$(gyp_shared_intermediate_dir)/content/jni/HashSet_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/HashSet_jni.h: $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(GYP_ABS_ANDROID_TOP_DIR)/prebuilts/sdk/17/android.jar $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: Generating JNI bindings from  $(GYP_ABS_ANDROID_TOP_DIR)/prebuilts/sdk/17/android.jar/java/util/HashSet.class ($@)"
+	$(hide)cd $(gyp_local_path)/content; mkdir -p $(gyp_shared_intermediate_dir)/content/jni; ../base/android/jni_generator/jni_generator.py -j "$(GYP_ABS_ANDROID_TOP_DIR)/prebuilts/sdk/17/android.jar" --input_file java/util/HashSet.class --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --optimize_generation 0
 
 
 
 GYP_GENERATED_OUTPUTS := \
-	$(gyp_shared_intermediate_dir)/content/jni/Surface_jni.h
+	$(gyp_shared_intermediate_dir)/content/jni/HashSet_jni.h
 
 # Make sure our deps and generated files are built first.
 LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
 
 LOCAL_GENERATED_SOURCES := \
-	$(gyp_shared_intermediate_dir)/content/jni/Surface_jni.h
+	$(gyp_shared_intermediate_dir)/content/jni/HashSet_jni.h
 
 GYP_COPIED_SOURCE_ORIGIN_DIRS :=
 
@@ -55,6 +55,7 @@
 	-march=pentium4 \
 	-msse2 \
 	-mfpmath=sse \
+	-fuse-ld=gold \
 	-ffunction-sections \
 	-funwind-tables \
 	-g \
@@ -76,7 +77,6 @@
 
 MY_DEFS := \
 	'-DCONTENT_IMPLEMENTATION' \
-	'-DUSE_SKIA' \
 	'-D_FILE_OFFSET_BITS=64' \
 	'-DUSE_LINUX_BREAKPAD' \
 	'-DNO_TCMALLOC' \
@@ -84,7 +84,6 @@
 	'-DCHROMIUM_BUILD' \
 	'-DUSE_LIBJPEG_TURBO=1' \
 	'-DUSE_PROPRIETARY_CODECS' \
-	'-DENABLE_PEPPER_THREADING' \
 	'-DENABLE_GPU=1' \
 	'-DUSE_OPENSSL=1' \
 	'-DENABLE_EGLIMAGE=1' \
@@ -123,11 +122,11 @@
 ### Rules for final target.
 # Add target alias to "gyp_all_modules" target.
 .PHONY: gyp_all_modules
-gyp_all_modules: content_surface_jni_headers_gyp
+gyp_all_modules: content_java_set_jni_headers_gyp
 
 # Alias gyp target name.
-.PHONY: surface_jni_headers
-surface_jni_headers: content_surface_jni_headers_gyp
+.PHONY: java_set_jni_headers
+java_set_jni_headers: content_java_set_jni_headers_gyp
 
 LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
 LOCAL_UNINSTALLABLE_MODULE := true
diff --git a/content/java_set_jni_headers.target.linux-arm.mk b/content/java_set_jni_headers.target.linux-arm.mk
index 1123ac9..6c3483c 100644
--- a/content/java_set_jni_headers.target.linux-arm.mk
+++ b/content/java_set_jni_headers.target.linux-arm.mk
@@ -75,7 +75,6 @@
 
 MY_DEFS := \
 	'-DCONTENT_IMPLEMENTATION' \
-	'-DUSE_SKIA' \
 	'-D_FILE_OFFSET_BITS=64' \
 	'-DUSE_LINUX_BREAKPAD' \
 	'-DNO_TCMALLOC' \
@@ -83,7 +82,6 @@
 	'-DCHROMIUM_BUILD' \
 	'-DUSE_LIBJPEG_TURBO=1' \
 	'-DUSE_PROPRIETARY_CODECS' \
-	'-DENABLE_PEPPER_THREADING' \
 	'-DENABLE_GPU=1' \
 	'-DUSE_OPENSSL=1' \
 	'-DENABLE_EGLIMAGE=1' \
diff --git a/content/java_set_jni_headers.target.linux-x86.mk b/content/java_set_jni_headers.target.linux-x86.mk
index bf53480..502136f 100644
--- a/content/java_set_jni_headers.target.linux-x86.mk
+++ b/content/java_set_jni_headers.target.linux-x86.mk
@@ -55,6 +55,7 @@
 	-march=pentium4 \
 	-msse2 \
 	-mfpmath=sse \
+	-fuse-ld=gold \
 	-ffunction-sections \
 	-funwind-tables \
 	-g \
@@ -76,7 +77,6 @@
 
 MY_DEFS := \
 	'-DCONTENT_IMPLEMENTATION' \
-	'-DUSE_SKIA' \
 	'-D_FILE_OFFSET_BITS=64' \
 	'-DUSE_LINUX_BREAKPAD' \
 	'-DNO_TCMALLOC' \
@@ -84,7 +84,6 @@
 	'-DCHROMIUM_BUILD' \
 	'-DUSE_LIBJPEG_TURBO=1' \
 	'-DUSE_PROPRIETARY_CODECS' \
-	'-DENABLE_PEPPER_THREADING' \
 	'-DENABLE_GPU=1' \
 	'-DUSE_OPENSSL=1' \
 	'-DENABLE_EGLIMAGE=1' \
diff --git a/content/page_transition_types_java.target.darwin-arm.mk b/content/page_transition_types_java.target.darwin-arm.mk
new file mode 100644
index 0000000..739f25a
--- /dev/null
+++ b/content/page_transition_types_java.target.darwin-arm.mk
@@ -0,0 +1,142 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := content_page_transition_types_java_gyp
+LOCAL_MODULE_STEM := page_transition_types_java
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+
+### Generated for rule "content_content_gyp_page_transition_types_java_target_generate_java_constants":
+# "{'inputs': ['../build/android/gyp/util/build_utils.py', '../build/android/gyp/gcc_preprocess.py', 'public/common/page_transition_types_list.h'], 'extension': 'template', 'outputs': ['$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/%(INPUT_ROOT)s.java'], 'variables': {'output_path': '$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/%(INPUT_ROOT)s.java'}, 'rule_name': 'generate_java_constants', 'rule_sources': ['public/android/java/src/org/chromium/content/browser/PageTransitionTypes.template'], 'action': ['python', '../build/android/gyp/gcc_preprocess.py', '--include-path=..', '--output=$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/%(INPUT_ROOT)s.java', '--template=$(RULE_SOURCES)'], 'message': 'Generating Java from cpp template $(RULE_SOURCES)'}":
+$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/PageTransitionTypes.java: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/PageTransitionTypes.java: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
+$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/PageTransitionTypes.java: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
+$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/PageTransitionTypes.java: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/PageTransitionTypes.java: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/PageTransitionTypes.template $(LOCAL_PATH)/build/android/gyp/util/build_utils.py $(LOCAL_PATH)/build/android/gyp/gcc_preprocess.py $(LOCAL_PATH)/content/public/common/page_transition_types_list.h $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser; cd $(gyp_local_path)/content; python ../build/android/gyp/gcc_preprocess.py "--include-path=.." "--output=$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/PageTransitionTypes.java" "--template=public/android/java/src/org/chromium/content/browser/PageTransitionTypes.template"
+
+.PHONY: content_page_transition_types_java_gyp_rule_trigger
+content_page_transition_types_java_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/PageTransitionTypes.java
+
+### Finished generating for all rules
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/PageTransitionTypes.java
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES := \
+	content_page_transition_types_java_gyp_rule_trigger
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-fno-tree-sra \
+	-fuse-ld=gold \
+	-Wno-psabi \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections
+
+MY_CFLAGS_C :=
+
+MY_DEFS := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DUSE_LINUX_BREAKPAD' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_GPU=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DENABLE_LANGUAGE_DETECTION=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+LOCAL_CFLAGS := $(MY_CFLAGS_C) $(MY_CFLAGS) $(MY_DEFS)
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES := \
+	$(GYP_ABS_ANDROID_TOP_DIR)/frameworks/wilhelm/include \
+	$(GYP_ABS_ANDROID_TOP_DIR)/bionic \
+	$(GYP_ABS_ANDROID_TOP_DIR)/external/stlport/stlport
+
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES)
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-abi \
+	-Wno-error=c++0x-compat \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_page_transition_types_java_gyp
+
+# Alias gyp target name.
+.PHONY: page_transition_types_java
+page_transition_types_java: content_page_transition_types_java_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/content/page_transition_types_java.target.darwin-x86.mk b/content/page_transition_types_java.target.darwin-x86.mk
new file mode 100644
index 0000000..cf3edd3
--- /dev/null
+++ b/content/page_transition_types_java.target.darwin-x86.mk
@@ -0,0 +1,143 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := content_page_transition_types_java_gyp
+LOCAL_MODULE_STEM := page_transition_types_java
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+
+### Generated for rule "content_content_gyp_page_transition_types_java_target_generate_java_constants":
+# "{'inputs': ['../build/android/gyp/util/build_utils.py', '../build/android/gyp/gcc_preprocess.py', 'public/common/page_transition_types_list.h'], 'extension': 'template', 'outputs': ['$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/%(INPUT_ROOT)s.java'], 'variables': {'output_path': '$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/%(INPUT_ROOT)s.java'}, 'rule_name': 'generate_java_constants', 'rule_sources': ['public/android/java/src/org/chromium/content/browser/PageTransitionTypes.template'], 'action': ['python', '../build/android/gyp/gcc_preprocess.py', '--include-path=..', '--output=$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/%(INPUT_ROOT)s.java', '--template=$(RULE_SOURCES)'], 'message': 'Generating Java from cpp template $(RULE_SOURCES)'}":
+$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/PageTransitionTypes.java: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/PageTransitionTypes.java: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
+$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/PageTransitionTypes.java: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
+$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/PageTransitionTypes.java: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/PageTransitionTypes.java: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/PageTransitionTypes.template $(LOCAL_PATH)/build/android/gyp/util/build_utils.py $(LOCAL_PATH)/build/android/gyp/gcc_preprocess.py $(LOCAL_PATH)/content/public/common/page_transition_types_list.h $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser; cd $(gyp_local_path)/content; python ../build/android/gyp/gcc_preprocess.py "--include-path=.." "--output=$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/PageTransitionTypes.java" "--template=public/android/java/src/org/chromium/content/browser/PageTransitionTypes.template"
+
+.PHONY: content_page_transition_types_java_gyp_rule_trigger
+content_page_transition_types_java_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/PageTransitionTypes.java
+
+### Finished generating for all rules
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/PageTransitionTypes.java
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES := \
+	content_page_transition_types_java_gyp_rule_trigger
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS := \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-m32 \
+	-mmmx \
+	-march=pentium4 \
+	-msse2 \
+	-mfpmath=sse \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-fno-stack-protector \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections
+
+MY_CFLAGS_C :=
+
+MY_DEFS := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DUSE_LINUX_BREAKPAD' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_GPU=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DENABLE_LANGUAGE_DETECTION=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+LOCAL_CFLAGS := $(MY_CFLAGS_C) $(MY_CFLAGS) $(MY_DEFS)
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES := \
+	$(GYP_ABS_ANDROID_TOP_DIR)/frameworks/wilhelm/include \
+	$(GYP_ABS_ANDROID_TOP_DIR)/bionic \
+	$(GYP_ABS_ANDROID_TOP_DIR)/external/stlport/stlport
+
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES)
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-error=c++0x-compat \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_page_transition_types_java_gyp
+
+# Alias gyp target name.
+.PHONY: page_transition_types_java
+page_transition_types_java: content_page_transition_types_java_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/content/page_transition_types_java.target.linux-arm.mk b/content/page_transition_types_java.target.linux-arm.mk
index 831a616..739f25a 100644
--- a/content/page_transition_types_java.target.linux-arm.mk
+++ b/content/page_transition_types_java.target.linux-arm.mk
@@ -15,13 +15,13 @@
 
 
 ### Generated for rule "content_content_gyp_page_transition_types_java_target_generate_java_constants":
-# "{'inputs': ['public/common/page_transition_types_list.h'], 'extension': 'template', 'outputs': ['$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/%(INPUT_ROOT)s.java'], 'rule_name': 'generate_java_constants', 'rule_sources': ['public/android/java/src/org/chromium/content/browser/PageTransitionTypes.template'], 'action': ['gcc', '-E', '-D', 'ANDROID', '-x', 'c-header', '-P', '-I', '..', '-o', '$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/%(INPUT_ROOT)s.java', '$(RULE_SOURCES)'], 'message': 'Generating Java from cpp template $(RULE_SOURCES)'}":
+# "{'inputs': ['../build/android/gyp/util/build_utils.py', '../build/android/gyp/gcc_preprocess.py', 'public/common/page_transition_types_list.h'], 'extension': 'template', 'outputs': ['$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/%(INPUT_ROOT)s.java'], 'variables': {'output_path': '$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/%(INPUT_ROOT)s.java'}, 'rule_name': 'generate_java_constants', 'rule_sources': ['public/android/java/src/org/chromium/content/browser/PageTransitionTypes.template'], 'action': ['python', '../build/android/gyp/gcc_preprocess.py', '--include-path=..', '--output=$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/%(INPUT_ROOT)s.java', '--template=$(RULE_SOURCES)'], 'message': 'Generating Java from cpp template $(RULE_SOURCES)'}":
 $(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/PageTransitionTypes.java: gyp_local_path := $(LOCAL_PATH)
 $(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/PageTransitionTypes.java: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
 $(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/PageTransitionTypes.java: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
 $(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/PageTransitionTypes.java: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
-$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/PageTransitionTypes.java: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/PageTransitionTypes.template $(LOCAL_PATH)/content/public/common/page_transition_types_list.h $(GYP_TARGET_DEPENDENCIES)
-	mkdir -p $(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser; cd $(gyp_local_path)/content; gcc -E -D ANDROID -x c-header -P -I .. -o "$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/PageTransitionTypes.java" public/android/java/src/org/chromium/content/browser/PageTransitionTypes.template
+$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/PageTransitionTypes.java: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/PageTransitionTypes.template $(LOCAL_PATH)/build/android/gyp/util/build_utils.py $(LOCAL_PATH)/build/android/gyp/gcc_preprocess.py $(LOCAL_PATH)/content/public/common/page_transition_types_list.h $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser; cd $(gyp_local_path)/content; python ../build/android/gyp/gcc_preprocess.py "--include-path=.." "--output=$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/PageTransitionTypes.java" "--template=public/android/java/src/org/chromium/content/browser/PageTransitionTypes.template"
 
 .PHONY: content_page_transition_types_java_gyp_rule_trigger
 content_page_transition_types_java_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/PageTransitionTypes.java
@@ -79,7 +79,6 @@
 
 MY_DEFS := \
 	'-DCONTENT_IMPLEMENTATION' \
-	'-DUSE_SKIA' \
 	'-D_FILE_OFFSET_BITS=64' \
 	'-DUSE_LINUX_BREAKPAD' \
 	'-DNO_TCMALLOC' \
@@ -87,7 +86,6 @@
 	'-DCHROMIUM_BUILD' \
 	'-DUSE_LIBJPEG_TURBO=1' \
 	'-DUSE_PROPRIETARY_CODECS' \
-	'-DENABLE_PEPPER_THREADING' \
 	'-DENABLE_GPU=1' \
 	'-DUSE_OPENSSL=1' \
 	'-DENABLE_EGLIMAGE=1' \
diff --git a/content/page_transition_types_java.target.linux-x86.mk b/content/page_transition_types_java.target.linux-x86.mk
index 8b82a3e..cf3edd3 100644
--- a/content/page_transition_types_java.target.linux-x86.mk
+++ b/content/page_transition_types_java.target.linux-x86.mk
@@ -15,13 +15,13 @@
 
 
 ### Generated for rule "content_content_gyp_page_transition_types_java_target_generate_java_constants":
-# "{'inputs': ['public/common/page_transition_types_list.h'], 'extension': 'template', 'outputs': ['$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/%(INPUT_ROOT)s.java'], 'rule_name': 'generate_java_constants', 'rule_sources': ['public/android/java/src/org/chromium/content/browser/PageTransitionTypes.template'], 'action': ['gcc', '-E', '-D', 'ANDROID', '-x', 'c-header', '-P', '-I', '..', '-o', '$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/%(INPUT_ROOT)s.java', '$(RULE_SOURCES)'], 'message': 'Generating Java from cpp template $(RULE_SOURCES)'}":
+# "{'inputs': ['../build/android/gyp/util/build_utils.py', '../build/android/gyp/gcc_preprocess.py', 'public/common/page_transition_types_list.h'], 'extension': 'template', 'outputs': ['$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/%(INPUT_ROOT)s.java'], 'variables': {'output_path': '$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/%(INPUT_ROOT)s.java'}, 'rule_name': 'generate_java_constants', 'rule_sources': ['public/android/java/src/org/chromium/content/browser/PageTransitionTypes.template'], 'action': ['python', '../build/android/gyp/gcc_preprocess.py', '--include-path=..', '--output=$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/%(INPUT_ROOT)s.java', '--template=$(RULE_SOURCES)'], 'message': 'Generating Java from cpp template $(RULE_SOURCES)'}":
 $(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/PageTransitionTypes.java: gyp_local_path := $(LOCAL_PATH)
 $(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/PageTransitionTypes.java: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
 $(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/PageTransitionTypes.java: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
 $(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/PageTransitionTypes.java: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
-$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/PageTransitionTypes.java: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/PageTransitionTypes.template $(LOCAL_PATH)/content/public/common/page_transition_types_list.h $(GYP_TARGET_DEPENDENCIES)
-	mkdir -p $(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser; cd $(gyp_local_path)/content; gcc -E -D ANDROID -x c-header -P -I .. -o "$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/PageTransitionTypes.java" public/android/java/src/org/chromium/content/browser/PageTransitionTypes.template
+$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/PageTransitionTypes.java: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/PageTransitionTypes.template $(LOCAL_PATH)/build/android/gyp/util/build_utils.py $(LOCAL_PATH)/build/android/gyp/gcc_preprocess.py $(LOCAL_PATH)/content/public/common/page_transition_types_list.h $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser; cd $(gyp_local_path)/content; python ../build/android/gyp/gcc_preprocess.py "--include-path=.." "--output=$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/PageTransitionTypes.java" "--template=public/android/java/src/org/chromium/content/browser/PageTransitionTypes.template"
 
 .PHONY: content_page_transition_types_java_gyp_rule_trigger
 content_page_transition_types_java_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/PageTransitionTypes.java
@@ -59,6 +59,7 @@
 	-march=pentium4 \
 	-msse2 \
 	-mfpmath=sse \
+	-fuse-ld=gold \
 	-ffunction-sections \
 	-funwind-tables \
 	-g \
@@ -80,7 +81,6 @@
 
 MY_DEFS := \
 	'-DCONTENT_IMPLEMENTATION' \
-	'-DUSE_SKIA' \
 	'-D_FILE_OFFSET_BITS=64' \
 	'-DUSE_LINUX_BREAKPAD' \
 	'-DNO_TCMALLOC' \
@@ -88,7 +88,6 @@
 	'-DCHROMIUM_BUILD' \
 	'-DUSE_LIBJPEG_TURBO=1' \
 	'-DUSE_PROPRIETARY_CODECS' \
-	'-DENABLE_PEPPER_THREADING' \
 	'-DENABLE_GPU=1' \
 	'-DUSE_OPENSSL=1' \
 	'-DENABLE_EGLIMAGE=1' \
diff --git a/content/plugin/plugin_channel.cc b/content/plugin/plugin_channel.cc
index 8569a3d..781ca00 100644
--- a/content/plugin/plugin_channel.cc
+++ b/content/plugin/plugin_channel.cc
@@ -67,7 +67,7 @@
       return;
 
     // Delete the event when the stack unwinds as it could be in use now.
-    MessageLoop::current()->DeleteSoon(
+    base::MessageLoop::current()->DeleteSoon(
         FROM_HERE, modal_dialog_event_map_[render_view_id].event);
     modal_dialog_event_map_.erase(render_view_id);
   }
@@ -200,7 +200,7 @@
 }
 
 PluginChannel::~PluginChannel() {
-  MessageLoop::current()->PostDelayedTask(
+  base::MessageLoop::current()->PostDelayedTask(
       FROM_HERE,
       base::Bind(&PluginReleaseCallback),
       base::TimeDelta::FromMinutes(kPluginReleaseTimeMinutes));
@@ -280,9 +280,11 @@
       // Don't release the modal dialog event right away, but do it after the
       // stack unwinds since the plugin can be destroyed later if it's in use
       // right now.
-      MessageLoop::current()->PostNonNestableTask(FROM_HERE, base::Bind(
-          &MessageFilter::ReleaseModalDialogEvent, filter.get(),
-          render_view_id));
+      base::MessageLoop::current()->PostNonNestableTask(
+          FROM_HERE,
+          base::Bind(&MessageFilter::ReleaseModalDialogEvent,
+                     filter.get(),
+                     render_view_id));
       return;
     }
   }
@@ -302,7 +304,7 @@
   base::FilePath path = command_line->GetSwitchValuePath(switches::kPluginPath);
   scoped_refptr<webkit::npapi::PluginLib> plugin_lib(
       webkit::npapi::PluginLib::CreatePluginLib(path));
-  if (plugin_lib.get()) {
+  if (plugin_lib) {
     NPError err = plugin_lib->NP_Initialize();
     if (err == NPERR_NO_ERROR) {
       const char* site_str = site.empty() ? NULL : site.c_str();
diff --git a/content/plugin/plugin_main.cc b/content/plugin/plugin_main.cc
index 971e308..298fbd4 100644
--- a/content/plugin/plugin_main.cc
+++ b/content/plugin/plugin_main.cc
@@ -13,7 +13,7 @@
 #include "base/hi_res_timer_manager.h"
 #include "base/message_loop.h"
 #include "base/string_util.h"
-#include "base/system_monitor/system_monitor.h"
+#include "base/power_monitor/power_monitor.h"
 #include "base/threading/platform_thread.h"
 #include "content/common/child_process.h"
 #include "content/plugin/plugin_thread.h"
@@ -52,10 +52,10 @@
 #endif
   InitializeChromeApplication();
 #endif
-  MessageLoop main_message_loop(MessageLoop::TYPE_UI);
+  base::MessageLoop main_message_loop(base::MessageLoop::TYPE_UI);
   base::PlatformThread::SetName("CrPluginMain");
 
-  base::SystemMonitor system_monitor;
+  base::PowerMonitor power_monitor;
   HighResolutionTimerManager high_resolution_timer_manager;
 
   const CommandLine& parsed_command_line = parameters.command_line;
@@ -77,7 +77,7 @@
   {
     ChildProcess plugin_process;
     plugin_process.set_main_thread(new PluginThread());
-    MessageLoop::current()->Run();
+    base::MessageLoop::current()->Run();
   }
 
   return 0;
diff --git a/content/plugin/plugin_thread.cc b/content/plugin/plugin_thread.cc
index ea0cbc1..8256ef6 100644
--- a/content/plugin/plugin_thread.cc
+++ b/content/plugin/plugin_thread.cc
@@ -58,7 +58,7 @@
     // Ensure that we don't wait indefinitely for the plugin to shutdown.
     // as the browser does not terminate plugin processes on shutdown.
     // We achieve this by posting an exit process task on the IO thread.
-    MessageLoop::current()->PostDelayedTask(
+    base::MessageLoop::current()->PostDelayedTask(
         FROM_HERE,
         base::Bind(&EnsureTerminateMessageFilter::Terminate, this),
         kPluginProcessTerminateTimeout);
@@ -117,7 +117,7 @@
 
   scoped_refptr<webkit::npapi::PluginLib> plugin(
       webkit::npapi::PluginLib::CreatePluginLib(plugin_path));
-  if (plugin.get()) {
+  if (plugin) {
     plugin->NP_Initialize();
     // For OOP plugins the plugin dll will be unloaded during process shutdown
     // time.
@@ -137,6 +137,9 @@
 }
 
 PluginThread::~PluginThread() {
+}
+
+void PluginThread::Shutdown() {
   if (preloaded_plugin_module_) {
     base::UnloadNativeLibrary(preloaded_plugin_module_);
     preloaded_plugin_module_ = NULL;
@@ -170,7 +173,7 @@
   scoped_refptr<PluginChannel> channel(PluginChannel::GetPluginChannel(
       renderer_id, ChildProcess::current()->io_message_loop_proxy()));
   IPC::ChannelHandle channel_handle;
-  if (channel.get()) {
+  if (channel) {
     channel_handle.name = channel->channel_handle().name;
 #if defined(OS_POSIX)
     // On POSIX, pass the renderer-side FD.
diff --git a/content/plugin/plugin_thread.h b/content/plugin/plugin_thread.h
index f967126..86c9b2d 100644
--- a/content/plugin/plugin_thread.h
+++ b/content/plugin/plugin_thread.h
@@ -25,6 +25,7 @@
  public:
   PluginThread();
   virtual ~PluginThread();
+  virtual void Shutdown() OVERRIDE;
 
   // Returns the one plugin thread.
   static PluginThread* current();
diff --git a/content/plugin/webplugin_delegate_stub.cc b/content/plugin/webplugin_delegate_stub.cc
index 0adb0f9..5c25961 100644
--- a/content/plugin/webplugin_delegate_stub.cc
+++ b/content/plugin/webplugin_delegate_stub.cc
@@ -38,7 +38,7 @@
     WebPlugin* webplugin) {
   // The plugin may not expect us to try to release the scriptable object
   // after calling NPP_Destroy on the instance, so delete the stub now.
-  if (scriptable_object.get())
+  if (scriptable_object)
     scriptable_object->DeleteSoon();
   // WebPlugin must outlive WebPluginDelegate.
   if (delegate)
@@ -65,9 +65,12 @@
   if (channel_->in_send()) {
     // The delegate or an npobject is in the callstack, so don't delete it
     // right away.
-    MessageLoop::current()->PostNonNestableTask(FROM_HERE,
-        base::Bind(&DestroyWebPluginAndDelegate, plugin_scriptable_object_,
-                   delegate_, webplugin_));
+    base::MessageLoop::current()->PostNonNestableTask(
+        FROM_HERE,
+        base::Bind(&DestroyWebPluginAndDelegate,
+                   plugin_scriptable_object_,
+                   delegate_,
+                   webplugin_));
   } else {
     // Safe to delete right away.
     DestroyWebPluginAndDelegate(
diff --git a/content/plugin/webplugin_proxy.cc b/content/plugin/webplugin_proxy.cc
index 5ac898d..43e177c 100644
--- a/content/plugin/webplugin_proxy.cc
+++ b/content/plugin/webplugin_proxy.cc
@@ -69,7 +69,7 @@
       page_url_(page_url),
       windowless_buffer_index_(0),
       host_render_view_routing_id_(host_render_view_routing_id),
-      ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) {
+      weak_factory_(this) {
 #if defined(USE_X11)
   windowless_shm_pixmaps_[0] = None;
   windowless_shm_pixmaps_[1] = None;
@@ -102,7 +102,7 @@
 
 #if defined(OS_MACOSX)
   // Destroy the surface early, since it may send messages during cleanup.
-  if (accelerated_surface_.get())
+  if (accelerated_surface_)
     accelerated_surface_.reset();
 #endif
 
@@ -199,9 +199,11 @@
     waiting_for_paint_ = true;
     // Invalidates caused by calls to NPN_InvalidateRect/NPN_InvalidateRgn
     // need to be painted asynchronously as per the NPAPI spec.
-    MessageLoop::current()->PostTask(FROM_HERE,
-        base::Bind(&WebPluginProxy::OnPaint, weak_factory_.GetWeakPtr(),
-            damaged_rect_));
+    base::MessageLoop::current()->PostTask(
+        FROM_HERE,
+        base::Bind(&WebPluginProxy::OnPaint,
+                   weak_factory_.GetWeakPtr(),
+                   damaged_rect_));
     damaged_rect_ = gfx::Rect();
   }
 }
@@ -275,7 +277,7 @@
 }
 
 int WebPluginProxy::GetRendererId() {
-  if (channel_.get())
+  if (channel_)
     return channel_->renderer_id();
   return -1;
 }
@@ -629,7 +631,7 @@
 
 WebPluginAcceleratedSurface* WebPluginProxy::GetAcceleratedSurface(
     gfx::GpuPreference gpu_preference) {
-  if (!accelerated_surface_.get())
+  if (!accelerated_surface_)
     accelerated_surface_.reset(
         WebPluginAcceleratedSurfaceProxy::Create(this, gpu_preference));
   return accelerated_surface_.get();
diff --git a/content/port/browser/render_view_host_delegate_view.h b/content/port/browser/render_view_host_delegate_view.h
index 85ef3da..9eced8c 100644
--- a/content/port/browser/render_view_host_delegate_view.h
+++ b/content/port/browser/render_view_host_delegate_view.h
@@ -50,7 +50,9 @@
 
   // The user started dragging content of the specified type within the
   // RenderView. Contextual information about the dragged content is supplied
-  // by WebDropData.
+  // by WebDropData. If the delegate's view cannot start the drag for /any/
+  // reason, it must inform the renderer that the drag has ended; otherwise,
+  // this results in bugs like http://crbug.com/157134.
   virtual void StartDragging(const WebDropData& drop_data,
                              WebKit::WebDragOperationsMask allowed_ops,
                              const gfx::ImageSkia& image,
diff --git a/content/port/browser/render_widget_host_view_frame_subscriber.h b/content/port/browser/render_widget_host_view_frame_subscriber.h
index de1ee089..fb88860 100644
--- a/content/port/browser/render_widget_host_view_frame_subscriber.h
+++ b/content/port/browser/render_widget_host_view_frame_subscriber.h
@@ -44,8 +44,9 @@
       base::Time /* timestamp */,
       bool /* frame_captured */)> DeliverFrameCallback;
 
-  // Called when a new frame is going to be presented. Implementation can
-  // decide whether the current frame should be captured or not.
+  // Called when a new frame is going to be presented at time
+  // |present_time|. Implementation can decide whether the current frame should
+  // be captured or not.
   //
   // Return true if the current frame should be captured. If so, |storage|
   // should will be set to hold an appropriately sized and allocated buffer
@@ -61,6 +62,7 @@
   //
   // Return false if the current frame should not be captured.
   virtual bool ShouldCaptureFrame(
+      base::Time present_time,
       scoped_refptr<media::VideoFrame>* storage,
       DeliverFrameCallback* callback) = 0;
 };
diff --git a/content/port/browser/render_widget_host_view_port.h b/content/port/browser/render_widget_host_view_port.h
index 397d71d..46a96c2 100644
--- a/content/port/browser/render_widget_host_view_port.h
+++ b/content/port/browser/render_widget_host_view_port.h
@@ -280,6 +280,8 @@
   virtual InputEventAckState FilterInputEvent(
       const WebKit::WebInputEvent& input_event) = 0;
 
+  virtual void GestureEventAck(int gesture_event_type) = 0;
+
   virtual void SetPopupType(WebKit::WebPopupType popup_type) = 0;
   virtual WebKit::WebPopupType GetPopupType() = 0;
 
@@ -303,13 +305,6 @@
 #if defined(OS_ANDROID)
   virtual void ShowDisambiguationPopup(const gfx::Rect& target_rect,
                                        const SkBitmap& zoomed_bitmap) = 0;
-  virtual void UpdateFrameInfo(const gfx::Vector2dF& scroll_offset,
-                               float page_scale_factor,
-                               const gfx::Vector2dF& page_scale_factor_limits,
-                               const gfx::SizeF& content_size,
-                               const gfx::SizeF& viewport_size,
-                               const gfx::Vector2dF& controls_offset,
-                               const gfx::Vector2dF& content_offset) = 0;
   virtual void HasTouchEventHandlers(bool need_touch_events) = 0;
 #endif
 
diff --git a/content/ppapi_plugin/broker_process_dispatcher.cc b/content/ppapi_plugin/broker_process_dispatcher.cc
index d9dd974..68b6746 100644
--- a/content/ppapi_plugin/broker_process_dispatcher.cc
+++ b/content/ppapi_plugin/broker_process_dispatcher.cc
@@ -105,7 +105,7 @@
   // plugin. This is the case for common plugins where they may be used on a
   // source and destination page of a navigation. We don't want to tear down
   // and re-start processes each time in these cases.
-  MessageLoop::current()->PostDelayedTask(
+  base::MessageLoop::current()->PostDelayedTask(
       FROM_HERE,
       base::Bind(&ChildProcess::ReleaseProcess,
                  base::Unretained(ChildProcess::current())),
@@ -304,7 +304,7 @@
     return true;
 
   std::string data_str = ConvertPluginDataPath(plugin_data_path);
-  scoped_array<PP_Flash_BrowserOperations_SiteSetting> site_array(
+  scoped_ptr<PP_Flash_BrowserOperations_SiteSetting[]> site_array(
       new PP_Flash_BrowserOperations_SiteSetting[sites.size()]);
 
   for (size_t i = 0; i < sites.size(); ++i) {
diff --git a/content/ppapi_plugin/plugin_process_dispatcher.cc b/content/ppapi_plugin/plugin_process_dispatcher.cc
index 34d46ab..12fe91b 100644
--- a/content/ppapi_plugin/plugin_process_dispatcher.cc
+++ b/content/ppapi_plugin/plugin_process_dispatcher.cc
@@ -32,7 +32,7 @@
   // plugin. This is the case for common plugins where they may be used on a
   // source and destination page of a navigation. We don't want to tear down
   // and re-start processes each time in these cases.
-  MessageLoop::current()->PostDelayedTask(
+  base::MessageLoop::current()->PostDelayedTask(
       FROM_HERE,
       base::Bind(&ChildProcess::ReleaseProcess,
                  base::Unretained(ChildProcess::current())),
diff --git a/content/ppapi_plugin/ppapi_broker_main.cc b/content/ppapi_plugin/ppapi_broker_main.cc
index 04315f5..e2c6097 100644
--- a/content/ppapi_plugin/ppapi_broker_main.cc
+++ b/content/ppapi_plugin/ppapi_broker_main.cc
@@ -19,7 +19,7 @@
     ChildProcess::WaitForDebugger("PpapiBroker");
   }
 
-  MessageLoop main_message_loop(MessageLoop::TYPE_DEFAULT);
+  base::MessageLoop main_message_loop(base::MessageLoop::TYPE_DEFAULT);
   base::PlatformThread::SetName("CrPPAPIBrokerMain");
 
   ChildProcess ppapi_broker_process;
diff --git a/content/ppapi_plugin/ppapi_plugin_main.cc b/content/ppapi_plugin/ppapi_plugin_main.cc
index 9db7f2f..25ea26e 100644
--- a/content/ppapi_plugin/ppapi_plugin_main.cc
+++ b/content/ppapi_plugin/ppapi_plugin_main.cc
@@ -9,6 +9,7 @@
 #include "base/threading/platform_thread.h"
 #include "build/build_config.h"
 #include "content/common/child_process.h"
+#include "content/common/sandbox_linux.h"
 #include "content/ppapi_plugin/ppapi_thread.h"
 #include "content/public/common/content_client.h"
 #include "content/public/common/content_switches.h"
@@ -78,7 +79,7 @@
 #endif
   }
 
-  MessageLoop main_message_loop;
+  base::MessageLoop main_message_loop;
   base::PlatformThread::SetName("CrPPAPIMain");
 
 #if defined(OS_LINUX) && defined(USE_NSS)
@@ -93,7 +94,7 @@
     GetContentClient()->plugin()->PreSandboxInitialization();
 
 #if defined(OS_LINUX)
-  InitializeSandbox();
+  LinuxSandbox::InitializeSandbox();
 #endif
 
   ChildProcess ppapi_process;
diff --git a/content/ppapi_plugin/ppapi_thread.cc b/content/ppapi_plugin/ppapi_thread.cc
index e0bfb78..4f4be32 100644
--- a/content/ppapi_plugin/ppapi_thread.cc
+++ b/content/ppapi_plugin/ppapi_thread.cc
@@ -9,6 +9,7 @@
 #include "base/command_line.h"
 #include "base/debug/crash_logging.h"
 #include "base/logging.h"
+#include "base/metrics/histogram.h"
 #include "base/process_util.h"
 #include "base/rand_util.h"
 #include "base/stringprintf.h"
@@ -88,13 +89,11 @@
       local_pp_module_(
           base::RandInt(0, std::numeric_limits<PP_Module>::max())),
       next_plugin_dispatcher_id_(1),
-      ALLOW_THIS_IN_INITIALIZER_LIST(dispatcher_message_listener_(this)) {
+      dispatcher_message_listener_(this) {
   ppapi::proxy::PluginGlobals* globals = ppapi::proxy::PluginGlobals::Get();
   globals->set_plugin_proxy_delegate(this);
   globals->set_command_line(
       command_line.GetSwitchValueASCII(switches::kPpapiFlashArgs));
-  globals->set_enable_threading(
-      !command_line.HasSwitch(switches::kDisablePepperThreading));
 
   webkit_platform_support_.reset(new PpapiWebKitPlatformSupportImpl);
   WebKit::initialize(webkit_platform_support_.get());
@@ -114,6 +113,9 @@
 }
 
 PpapiThread::~PpapiThread() {
+}
+
+void PpapiThread::Shutdown() {
   ppapi::proxy::PluginGlobals::Get()->set_plugin_proxy_delegate(NULL);
   if (plugin_entry_points_.shutdown_module)
     plugin_entry_points_.shutdown_module();
@@ -127,7 +129,7 @@
 
 bool PpapiThread::Send(IPC::Message* msg) {
   // Allow access from multiple threads.
-  if (MessageLoop::current() == message_loop())
+  if (base::MessageLoop::current() == message_loop())
     return ChildThread::Send(msg);
 
   return sync_message_filter()->Send(msg);
@@ -261,6 +263,7 @@
     if (!library.is_valid()) {
       LOG(ERROR) << "Failed to load Pepper module from "
         << path.value() << " (error: " << error << ")";
+      ReportLoadResult(path, LOAD_FAILED);
       return;
     }
 
@@ -270,6 +273,7 @@
             library.GetFunctionPointer("PPP_GetInterface"));
     if (!plugin_entry_points_.get_interface) {
       LOG(WARNING) << "No PPP_GetInterface in plugin library";
+      ReportLoadResult(path, ENTRY_POINT_MISSING);
       return;
     }
 
@@ -288,6 +292,7 @@
               library.GetFunctionPointer("PPP_InitializeModule"));
       if (!plugin_entry_points_.initialize_module) {
         LOG(WARNING) << "No PPP_InitializeModule in plugin library";
+        ReportLoadResult(path, ENTRY_POINT_MISSING);
         return;
       }
     }
@@ -325,16 +330,19 @@
             library.GetFunctionPointer("PPP_InitializeBroker"));
     if (!init_broker) {
       LOG(WARNING) << "No PPP_InitializeBroker in plugin library";
+      ReportLoadResult(path, ENTRY_POINT_MISSING);
       return;
     }
 
     int32_t init_error = init_broker(&connect_instance_func_);
     if (init_error != PP_OK) {
       LOG(WARNING) << "InitBroker failed with error " << init_error;
+      ReportLoadResult(path, INIT_FAILED);
       return;
     }
     if (!connect_instance_func_) {
       LOG(WARNING) << "InitBroker did not provide PP_ConnectInstance_Func";
+      ReportLoadResult(path, INIT_FAILED);
       return;
     }
   } else {
@@ -350,12 +358,15 @@
         &ppapi::proxy::PluginDispatcher::GetBrowserInterface);
     if (init_error != PP_OK) {
       LOG(WARNING) << "InitModule failed with error " << init_error;
+      ReportLoadResult(path, INIT_FAILED);
       return;
     }
   }
 
   // Initialization succeeded, so keep the plugin DLL loaded.
   library_.Reset(library.Release());
+
+  ReportLoadResult(path, LOAD_SUCCESS);
 }
 
 void PpapiThread::OnCreateChannel(base::ProcessId renderer_pid,
@@ -461,7 +472,7 @@
   ppapi::proxy::PluginGlobals::Get()->set_plugin_name(
       path.BaseName().AsUTF8Unsafe());
 
-  // plugin() is NULL when in-process.  Which is fine, because this is
+  // plugin() is NULL when in-process, which is fine, because this is
   // just a hook for setting the process name.
   if (GetContentClient()->plugin()) {
     GetContentClient()->plugin()->PluginProcessStarted(
@@ -469,4 +480,24 @@
   }
 }
 
+void PpapiThread::ReportLoadResult(const base::FilePath& path,
+                                   LoadResult result) {
+  DCHECK_LT(result, LOAD_RESULT_MAX);
+
+  std::ostringstream histogram_name;
+  histogram_name << "Plugin.Ppapi" << (is_broker_ ? "Broker" : "Plugin")
+                 << "LoadResult_" << path.BaseName().MaybeAsASCII();
+
+  // Note: This leaks memory, which is expected behavior.
+  base::HistogramBase* histogram =
+      base::LinearHistogram::FactoryGet(
+          histogram_name.str(),
+          1,
+          LOAD_RESULT_MAX,
+          LOAD_RESULT_MAX + 1,
+          base::HistogramBase::kUmaTargetedHistogramFlag);
+
+  histogram->Add(result);
+}
+
 }  // namespace content
diff --git a/content/ppapi_plugin/ppapi_thread.h b/content/ppapi_plugin/ppapi_thread.h
index 0e21d56..7faff6b 100644
--- a/content/ppapi_plugin/ppapi_thread.h
+++ b/content/ppapi_plugin/ppapi_thread.h
@@ -47,8 +47,20 @@
  public:
   PpapiThread(const CommandLine& command_line, bool is_broker);
   virtual ~PpapiThread();
+  virtual void Shutdown() OVERRIDE;
 
  private:
+  // Make sure the enum list in tools/histogram/histograms.xml is updated with
+  // any change in this list.
+  enum LoadResult {
+    LOAD_SUCCESS,
+    LOAD_FAILED,
+    ENTRY_POINT_MISSING,
+    INIT_FAILED,
+    // NOTE: Add new values only immediately above this line.
+    LOAD_RESULT_MAX  // Boundary value for UMA_HISTOGRAM_ENUMERATION.
+  };
+
   // This class finds the target PluginDispatcher for each message it receives
   // and forwards the message.
   class DispatcherMessageListener : public IPC::Listener {
@@ -113,6 +125,8 @@
   // Sets up the name of the plugin for logging using the given path.
   void SavePluginName(const base::FilePath& path);
 
+  void ReportLoadResult(const base::FilePath& path, LoadResult result);
+
   // True if running in a broker process rather than a normal plugin process.
   bool is_broker_;
 
diff --git a/content/public/android/java/res/values/official-command-line.xml b/content/public/android/java/res/values/official-command-line.xml
deleted file mode 100644
index 4589501..0000000
--- a/content/public/android/java/res/values/official-command-line.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (c) 2012 The Chromium Authors. All rights reserved.
-
-     Use of this source code is governed by a BSD-style license that can be
-     found in the LICENSE file.
--->
-
-<resources>
-  <string-array name="official_command_line">
-  <!-- Note: this value will be overridden by the identically named resource (if
-       one exists) in the apk that is being built. -->
-  <!-- Format: double-dashed command-line flags within <item></item> blocks. -->
-  </string-array>
-</resources>
diff --git a/content/public/android/java/resource_map/org/chromium/content/R.java b/content/public/android/java/resource_map/org/chromium/content/R.java
index 47653c2..daa8a77 100644
--- a/content/public/android/java/resource_map/org/chromium/content/R.java
+++ b/content/public/android/java/resource_map/org/chromium/content/R.java
@@ -16,9 +16,6 @@
  * com.android.internal.R.
  */
 public final class R {
-    public static final class array {
-        public static int official_command_line;
-    }
     public static final class dimen {
         public static int link_preview_overlay_radius;
     }
diff --git a/content/public/android/java/src/org/chromium/content/app/ChildProcessService.java b/content/public/android/java/src/org/chromium/content/app/ChildProcessService.java
index 240cf5b..3d85310 100644
--- a/content/public/android/java/src/org/chromium/content/app/ChildProcessService.java
+++ b/content/public/android/java/src/org/chromium/content/app/ChildProcessService.java
@@ -46,7 +46,6 @@
     // This is the native "Main" thread for the renderer / utility process.
     private Thread mMainThread;
     // Parameters received via IPC, only accessed while holding the mMainThread monitor.
-    private String mNativeLibraryName;  // Must be passed in via the bind command.
     private String[] mCommandLineParams;
     private int mCpuCount;
     private long mCpuFeatures;
@@ -113,12 +112,6 @@
             @Override
             public void run()  {
                 try {
-                    synchronized (mMainThread) {
-                        while (mNativeLibraryName == null) {
-                            mMainThread.wait();
-                        }
-                    }
-                    LibraryLoader.setLibraryToLoad(mNativeLibraryName);
                     try {
                         LibraryLoader.loadNow();
                     } catch (ProcessInitException e) {
@@ -193,8 +186,6 @@
         stopSelf();
 
         synchronized (mMainThread) {
-            mNativeLibraryName = intent.getStringExtra(
-                    ChildProcessConnection.EXTRA_NATIVE_LIBRARY_NAME);
             mCommandLineParams = intent.getStringArrayExtra(
                     ChildProcessConnection.EXTRA_COMMAND_LINE);
             mMainThread.notifyAll();
diff --git a/content/public/android/java/src/org/chromium/content/app/LibraryLoader.java b/content/public/android/java/src/org/chromium/content/app/LibraryLoader.java
index abd1ef1..38cd2df 100644
--- a/content/public/android/java/src/org/chromium/content/app/LibraryLoader.java
+++ b/content/public/android/java/src/org/chromium/content/app/LibraryLoader.java
@@ -14,17 +14,15 @@
 import org.chromium.content.common.TraceEvent;
 
 /**
- * This class provides functionality to load and register the native library.
- * Callers are allowed to separate loading the library from initializing it.
- * This may be an advantage for Android Webview, where the library can be loaded
+ * This class provides functionality to load and register the native libraries.
+ * Callers are allowed to separate loading the libraries from initializing them.
+ * This may be an advantage for Android Webview, where the libraries can be loaded
  * by the zygote process, but then needs per process initialization after the
  * application processes are forked from the zygote process.
  *
- * The library may be loaded and initialized from any thread. Synchronization
+ * The libraries may be loaded and initialized from any thread. Synchronization
  * primitives are used to ensure that overlapping requests from different
- * threads are handled sequentially; however, care must still be taken to
- * ensure that {@link #setLibraryToLoad(String)} is called prior to invoking
- * {@link #loadNow()} or {@link #ensureInitialized()}.
+ * threads are handled sequentially.
  *
  * See also content/app/android/library_loader_hooks.cc, which contains
  * the native counterpart to this class.
@@ -33,45 +31,23 @@
 public class LibraryLoader {
     private static final String TAG = "LibraryLoader";
 
-    // The name of the library that will be loaded. Ideally this is a
-    // write-once, read-many value, but for the sake of unit tests
-    // we allow it to be mutated arbitrarily.
-    private static String sLibrary = null;
-
-    // Guards all access to the library
+    // Guards all access to the libraries
     private static final Object sLock = new Object();
 
-    // One-way switch becomes true when the library is loaded.
+    // One-way switch becomes true when the libraries are loaded.
     private static boolean sLoaded = false;
 
-    // One-way switch becomes true when the library is initialized (
+    // One-way switch becomes true when the libraries are initialized (
     // by calling nativeLibraryLoaded, which forwards to LibraryLoaded(...) in
     // library_loader_hooks.cc).
     private static boolean sInitialized = false;
 
-
+    // TODO(cjhopman): Remove this once it's unused.
     /**
-     * Sets the library name that is to be loaded.  This must be called prior to the library being
-     * loaded the first time. Outside of testing, this should only be called once.
-     *
-     * @param library The name of the library to be loaded (without the lib prefix).
+     * Doesn't do anything.
      */
+    @Deprecated
     public static void setLibraryToLoad(String library) {
-        synchronized(sLock) {
-            if (TextUtils.equals(sLibrary, library)) return;
-
-            assert !sLoaded : "Setting the library must happen before load is called.";
-            sLibrary = library;
-        }
-    }
-
-    /**
-     * @return The name of the native library set to be loaded.
-     */
-    public static String getLibraryToLoad() {
-        synchronized(sLock) {
-            return sLibrary;
-        }
     }
 
     /**
@@ -121,15 +97,14 @@
 
     // Invoke System.loadLibrary(...), triggering JNI_OnLoad in native code
     private static void loadAlreadyLocked() throws ProcessInitException {
-        if (sLibrary == null) {
-            assert false : "No library specified to load.  Call setLibraryToLoad before first.";
-        }
         try {
             if (!sLoaded) {
                 assert !sInitialized;
-                Log.i(TAG, "loading: " + sLibrary);
-                System.loadLibrary(sLibrary);
-                Log.i(TAG, "loaded: " + sLibrary);
+                for (String sLibrary : NativeLibraries.libraries) {
+                    Log.i(TAG, "loading: " + sLibrary);
+                    System.loadLibrary(sLibrary);
+                    Log.i(TAG, "loaded: " + sLibrary);
+                }
                 sLoaded = true;
             }
         } catch (UnsatisfiedLinkError e) {
diff --git a/content/public/android/java/src/org/chromium/content/browser/ChildProcessConnection.java b/content/public/android/java/src/org/chromium/content/browser/ChildProcessConnection.java
index ce9a164..cfd5f54 100644
--- a/content/public/android/java/src/org/chromium/content/browser/ChildProcessConnection.java
+++ b/content/public/android/java/src/org/chromium/content/browser/ChildProcessConnection.java
@@ -36,8 +36,6 @@
     // Names of items placed in the bind intent or connection bundle.
     public static final String EXTRA_COMMAND_LINE =
             "com.google.android.apps.chrome.extra.command_line";
-    public static final String EXTRA_NATIVE_LIBRARY_NAME =
-            "com.google.android.apps.chrome.extra.native_library_name";
     // Note the FDs may only be passed in the connection bundle.
     public static final String EXTRA_FILES_PREFIX =
             "com.google.android.apps.chrome.extra.extraFile_";
@@ -128,19 +126,16 @@
      * to setup the connection parameters. (These methods are separated to allow the client
      * to pass whatever parameters they have available here, and complete the remainder
      * later while reducing the connection setup latency).
-     * @param nativeLibraryName The name of the shared native library to be loaded for the
-     *                          child process.
      * @param commandLine (Optional) Command line for the child process. If omitted, then
      *                    the command line parameters must instead be passed to setupConnection().
      */
-    void bind(String nativeLibraryName, String[] commandLine) {
+    void bind(String[] commandLine) {
         synchronized(mUiThreadLock) {
             TraceEvent.begin();
             assert !ThreadUtils.runningOnUiThread();
 
             final Intent intent = createServiceBindIntent();
 
-            intent.putExtra(EXTRA_NATIVE_LIBRARY_NAME, nativeLibraryName);
             if (commandLine != null) {
                 intent.putExtra(EXTRA_COMMAND_LINE, commandLine);
             }
diff --git a/content/public/android/java/src/org/chromium/content/browser/ChildProcessLauncher.java b/content/public/android/java/src/org/chromium/content/browser/ChildProcessLauncher.java
index 5ddc008..92669a6 100644
--- a/content/public/android/java/src/org/chromium/content/browser/ChildProcessLauncher.java
+++ b/content/public/android/java/src/org/chromium/content/browser/ChildProcessLauncher.java
@@ -18,7 +18,6 @@
 import org.chromium.content.app.ChildProcessService;
 import org.chromium.content.app.PrivilegedProcessService;
 import org.chromium.content.app.SandboxedProcessService;
-import org.chromium.content.app.LibraryLoader;
 import org.chromium.content.common.IChildProcessCallback;
 import org.chromium.content.common.IChildProcessService;
 
@@ -155,10 +154,7 @@
             String[] commandLine, boolean inSandbox) {
         ChildProcessConnection connection = allocateConnection(context, inSandbox);
         if (connection != null) {
-            String libraryName = LibraryLoader.getLibraryToLoad();
-            assert libraryName != null : "Attempting to launch a child process without first "
-                    + "calling LibraryLoader.setLibraryToLoad";
-            connection.bind(libraryName, commandLine);
+            connection.bind(commandLine);
         }
         return connection;
     }
diff --git a/content/public/android/java/src/org/chromium/content/browser/ContainerViewDelegate.java b/content/public/android/java/src/org/chromium/content/browser/ContainerViewDelegate.java
deleted file mode 100644
index 8417345..0000000
--- a/content/public/android/java/src/org/chromium/content/browser/ContainerViewDelegate.java
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.content.browser;
-
-import android.view.View;
-
-/**
- * Interface to add and remove views from the implementing view.
- */
-public interface ContainerViewDelegate {
-
-    /**
-     * Add the view.
-     * @param view The view to be added.
-     */
-    public void addViewToContainerView(View view);
-
-    /**
-     * Remove the view if it is present, otherwise do nothing.
-     * @param view The view to be removed.
-     */
-    public void removeViewFromContainerView(View view);
-}
\ No newline at end of file
diff --git a/content/public/android/java/src/org/chromium/content/browser/ContentSettings.java b/content/public/android/java/src/org/chromium/content/browser/ContentSettings.java
index 5f3e8d3..df03f00 100644
--- a/content/public/android/java/src/org/chromium/content/browser/ContentSettings.java
+++ b/content/public/android/java/src/org/chromium/content/browser/ContentSettings.java
@@ -7,13 +7,13 @@
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
-import android.webkit.WebSettings.PluginState;
-import android.webkit.WebView;
 
 import org.chromium.base.CalledByNative;
 import org.chromium.base.JNINamespace;
 import org.chromium.base.ThreadUtils;
 
+import java.util.concurrent.Callable;
+
 /**
  * Manages settings state for a ContentView. A ContentSettings instance is obtained
  * from ContentView.getContentSettings(). If ContentView is used in the
@@ -22,14 +22,6 @@
  */
 @JNINamespace("content")
 public class ContentSettings {
-    // This enum corresponds to WebSettings.LayoutAlgorithm. We use our own to be
-    // able to extend it.
-    public enum LayoutAlgorithm {
-        NORMAL,
-        SINGLE_COLUMN,
-        NARROW_COLUMNS,
-        TEXT_AUTOSIZING,
-    }
 
     private static final String TAG = "ContentSettings";
 
@@ -43,164 +35,40 @@
 
     private ContentViewCore mContentViewCore;
 
-    // When ContentView is used in PERSONALITY_CHROME mode, settings can't
-    // be modified through the ContentSettings instance.
-    private boolean mCanModifySettings;
-
-    // A flag to avoid sending superfluous synchronization messages.
-    private boolean mIsSyncMessagePending = false;
     // Custom handler that queues messages to call native code on the UI thread.
     private final EventHandler mEventHandler;
 
     // Protects access to settings fields.
     private final Object mContentSettingsLock = new Object();
 
-    private static final int MINIMUM_FONT_SIZE = 1;
-    private static final int MAXIMUM_FONT_SIZE = 72;
-
-    // Private settings so we don't have to go into native code to
-    // retrieve the values. After setXXX, mEventHandler.syncSettingsLocked() needs to be called.
-    //
-    // TODO(mnaganov): populate with the complete set of legacy WebView settings.
-    // Note: If adding a new setting to this class, make sure to add it to the initFrom()
-    // method defined below.
-
-    private LayoutAlgorithm mLayoutAlgorithm = LayoutAlgorithm.NARROW_COLUMNS;
-    private int mTextSizePercent = 100;
-    private String mStandardFontFamily = "sans-serif";
-    private String mFixedFontFamily = "monospace";
-    private String mSansSerifFontFamily = "sans-serif";
-    private String mSerifFontFamily = "serif";
-    private String mCursiveFontFamily = "cursive";
-    private String mFantasyFontFamily = "fantasy";
-    // FIXME: Should be obtained from Android. Problem: it is hidden.
-    private String mDefaultTextEncoding = "Latin-1";
-    private String mUserAgent;
-    private int mMinimumFontSize = 8;
-    private int mMinimumLogicalFontSize = 8;
-    private int mDefaultFontSize = 16;
-    private int mDefaultFixedFontSize = 13;
-    private boolean mLoadsImagesAutomatically = true;
-    private boolean mImagesEnabled = true;
-    private boolean mJavaScriptEnabled = false;
-    private boolean mAllowUniversalAccessFromFileURLs = false;
-    private boolean mAllowFileAccessFromFileURLs = false;
-    private boolean mJavaScriptCanOpenWindowsAutomatically = false;
-    private boolean mSupportMultipleWindows = false;
-    private PluginState mPluginState = PluginState.OFF;
-    private boolean mAppCacheEnabled = false;
-    private boolean mDomStorageEnabled = false;
-    private boolean mDatabaseEnabled = false;
-    private boolean mUseWideViewport = false;
-    private boolean mLoadWithOverviewMode = false;
-    private boolean mMediaPlaybackRequiresUserGesture = true;
-    private String mDefaultVideoPosterURL;
-
-    // Not accessed by the native side.
     private boolean mSupportZoom = true;
     private boolean mBuiltInZoomControls = false;
     private boolean mDisplayZoomControls = true;
-    static class LazyDefaultUserAgent {
-        // Lazy Holder pattern
-        private static final String sInstance = nativeGetDefaultUserAgent();
-    }
-
-    // Protects access to settings global fields.
-    private static final Object sGlobalContentSettingsLock = new Object();
-    // For compatibility with the legacy WebView, we can only enable AppCache when the path is
-    // provided. However, we don't use the path, so we just check if we have received it from the
-    // client.
-    private static boolean sAppCachePathIsSet = false;
 
     // Class to handle messages to be processed on the UI thread.
     private class EventHandler {
-        // Message id for syncing
-        private static final int SYNC = 0;
-        // Message id for updating user agent in the view
-        private static final int UPDATE_UA = 1;
         // Message id for updating multi-touch zoom state in the view
         private static final int UPDATE_MULTI_TOUCH = 2;
         // Actual UI thread handler
         private Handler mHandler;
 
         EventHandler() {
-            mHandler = mContentViewCore.isPersonalityView() ?
-                    new Handler(Looper.getMainLooper()) {
-                        @Override
-                        public void handleMessage(Message msg) {
-                            switch (msg.what) {
-                                case SYNC:
-                                    synchronized (mContentSettingsLock) {
-                                        syncToNativeOnUiThread();
-                                        mIsSyncMessagePending = false;
-                                        mContentSettingsLock.notifyAll();
-                                    }
-                                    break;
-                                case UPDATE_UA:
-                                    if (mContentViewCore.isAlive()) {
-                                        mContentViewCore.setAllUserAgentOverridesInHistory();
-                                    }
-                                    break;
-                                case UPDATE_MULTI_TOUCH:
-                                    if (mContentViewCore.isAlive()) {
-                                        mContentViewCore.updateMultiTouchZoomSupport();
-                                    }
-                                    break;
-                            }
-                        }
-                    } :
-                    new Handler(Looper.getMainLooper()) {
-                        @Override
-                        public void handleMessage(Message msg) {
-                            switch (msg.what) {
-                                case SYNC:
-                                    synchronized (mContentSettingsLock) {
-                                        syncFromNativeOnUiThread();
-                                        mIsSyncMessagePending = false;
-                                    }
-                                    break;
-                            }
-                        }
-                    };
-        }
-
-        private void syncSettingsLocked() {
-            assert Thread.holdsLock(mContentSettingsLock);
-            if (mNativeContentSettings == 0) return;
             if (mContentViewCore.isPersonalityView()) {
-                if (Looper.myLooper() == mHandler.getLooper()) {
-                    syncToNativeOnUiThread();
-                } else {
-                    // We're being called on a background thread, so post a message.
-                    if (mIsSyncMessagePending) {
-                        return;
-                    }
-                    mIsSyncMessagePending = true;
-                    mHandler.sendMessage(Message.obtain(null, SYNC));
-                    // When used in PERSONALITY_VIEW mode, we must block
-                    // until the settings have been sync'd to native to
-                    // ensure that they have taken effect.
-                    try {
-                        while (mIsSyncMessagePending) {
-                            mContentSettingsLock.wait();
+                mHandler = new Handler(Looper.getMainLooper()) {
+                    @Override
+                    public void handleMessage(Message msg) {
+                        switch (msg.what) {
+                            case UPDATE_MULTI_TOUCH:
+                                if (mContentViewCore.isAlive()) {
+                                    mContentViewCore.updateMultiTouchZoomSupport();
+                                }
+                                break;
                         }
-                    } catch (InterruptedException e) {}
-                }
-            } else {
-                if (mIsSyncMessagePending) {
-                    return;
-                }
-                mIsSyncMessagePending = true;
-                mHandler.sendMessage(Message.obtain(null, SYNC));
+                    }
+                };
             }
         }
 
-        private void sendUpdateUaMessageLocked() {
-            assert Thread.holdsLock(mContentSettingsLock);
-            if (mNativeContentSettings == 0) return;
-            mHandler.sendMessage(Message.obtain(null, UPDATE_UA));
-        }
-
         private void sendUpdateMultiTouchMessageLocked() {
             assert Thread.holdsLock(mContentSettingsLock);
             if (mNativeContentSettings == 0) return;
@@ -212,31 +80,16 @@
      * Package constructor to prevent clients from creating a new settings
      * instance. Must be called on the UI thread.
      */
-    ContentSettings(ContentViewCore contentViewCore, int nativeContentView,
-            boolean isAccessFromFileURLsGrantedByDefault) {
+    ContentSettings(ContentViewCore contentViewCore, int nativeContentView) {
         ThreadUtils.assertOnUiThread();
         mContentViewCore = contentViewCore;
-        mCanModifySettings = mContentViewCore.isPersonalityView();
-        mNativeContentSettings = nativeInit(nativeContentView, mCanModifySettings);
+        mNativeContentSettings = nativeInit(nativeContentView);
         assert mNativeContentSettings != 0;
 
-        if (isAccessFromFileURLsGrantedByDefault) {
-            mAllowUniversalAccessFromFileURLs = true;
-            mAllowFileAccessFromFileURLs = true;
-        }
-
         mEventHandler = new EventHandler();
-        if (mCanModifySettings) {
-            // PERSONALITY_VIEW
-            mUserAgent = LazyDefaultUserAgent.sInstance;
-            syncToNativeOnUiThread();
-        } else {
-            // PERSONALITY_CHROME
-            // Chrome has zooming enabled by default. These settings are not
-            // set by the native code.
+        if (!mContentViewCore.isPersonalityView()) {
             mBuiltInZoomControls = true;
             mDisplayZoomControls = false;
-            syncFromNativeOnUiThread();
         }
     }
 
@@ -251,43 +104,6 @@
     }
 
     /**
-     * @returns the default User-Agent used by each ContentViewCore instance, i.e. unless
-     * overridden by {@link #setUserAgentString()}
-     */
-    public static String getDefaultUserAgent() {
-        return LazyDefaultUserAgent.sInstance;
-    }
-
-    /**
-     * Set the WebView's user-agent string. If the string "ua" is null or empty,
-     * it will use the system default user-agent string.
-     */
-    public void setUserAgentString(String ua) {
-        assert mCanModifySettings;
-        synchronized (mContentSettingsLock) {
-            final String oldUserAgent = mUserAgent;
-            if (ua == null || ua.length() == 0) {
-                mUserAgent = LazyDefaultUserAgent.sInstance;
-            } else {
-                mUserAgent = ua;
-            }
-            if (!oldUserAgent.equals(mUserAgent)) {
-                mEventHandler.sendUpdateUaMessageLocked();
-            }
-        }
-    }
-
-    /**
-     * Gets the WebView's user-agent string.
-     */
-    public String getUserAgentString() {
-        // TODO(mnaganov): Doesn't reflect changes made by ChromeNativePreferences.
-        synchronized (mContentSettingsLock) {
-            return mUserAgent;
-        }
-    }
-
-    /**
      * Sets whether the WebView should support zooming using its on-screen zoom
      * controls and gestures. The particular zoom mechanisms that should be used
      * can be set with {@link #setBuiltInZoomControls}. This setting does not
@@ -379,874 +195,22 @@
         return supportsMultiTouchZoom() && mDisplayZoomControls;
     }
 
-    public void setLoadWithOverviewMode(boolean overview) {
-        assert mCanModifySettings;
-        synchronized (mContentSettingsLock) {
-            if (mLoadWithOverviewMode != overview) {
-                mLoadWithOverviewMode = overview;
-                mEventHandler.syncSettingsLocked();
-            }
-        }
-    }
-
-    public boolean getLoadWithOverviewMode() {
-        synchronized (mContentSettingsLock) {
-            return mLoadWithOverviewMode;
-        }
-    }
-
     /**
-     * Sets the text zoom of the page in percent. Default is 100.
-     *
-     * @param textZoom the percent value for increasing or decreasing the text
-     */
-    public void setTextZoom(int textZoom) {
-        assert mCanModifySettings;
-        synchronized (mContentSettingsLock) {
-            if (mTextSizePercent != textZoom) {
-                mTextSizePercent = textZoom;
-                mEventHandler.syncSettingsLocked();
-            }
-        }
-    }
-
-    /**
-     * Gets the text zoom of the page in percent.
-     *
-     * @return a percent value describing the text zoom
-     * @see #setTextSizeZoom
-     */
-    public int getTextZoom() {
-        synchronized (mContentSettingsLock) {
-            return mTextSizePercent;
-        }
-    }
-
-    /**
-     * Set the standard font family name.
-     * @param font A font family name.
-     */
-    public void setStandardFontFamily(String font) {
-        assert mCanModifySettings;
-        synchronized (mContentSettingsLock) {
-            if (font != null && !mStandardFontFamily.equals(font)) {
-                mStandardFontFamily = font;
-                mEventHandler.syncSettingsLocked();
-            }
-        }
-    }
-
-    /**
-     * Get the standard font family name. The default is "sans-serif".
-     * @return The standard font family name as a string.
-     */
-    public String getStandardFontFamily() {
-        synchronized (mContentSettingsLock) {
-            return mStandardFontFamily;
-        }
-    }
-
-    /**
-     * Set the fixed font family name.
-     * @param font A font family name.
-     */
-    public void setFixedFontFamily(String font) {
-        assert mCanModifySettings;
-        synchronized (mContentSettingsLock) {
-            if (font != null && !mFixedFontFamily.equals(font)) {
-                mFixedFontFamily = font;
-                mEventHandler.syncSettingsLocked();
-            }
-        }
-    }
-
-    /**
-     * Get the fixed font family name. The default is "monospace".
-     * @return The fixed font family name as a string.
-     */
-    public String getFixedFontFamily() {
-        synchronized (mContentSettingsLock) {
-            return mFixedFontFamily;
-        }
-    }
-
-    /**
-     * Set the sans-serif font family name.
-     * @param font A font family name.
-     */
-    public void setSansSerifFontFamily(String font) {
-        assert mCanModifySettings;
-        synchronized (mContentSettingsLock) {
-            if (font != null && !mSansSerifFontFamily.equals(font)) {
-                mSansSerifFontFamily = font;
-                mEventHandler.syncSettingsLocked();
-            }
-        }
-    }
-
-    /**
-     * Get the sans-serif font family name.
-     * @return The sans-serif font family name as a string.
-     */
-    public String getSansSerifFontFamily() {
-        synchronized (mContentSettingsLock) {
-            return mSansSerifFontFamily;
-        }
-    }
-
-    /**
-     * Set the serif font family name. The default is "sans-serif".
-     * @param font A font family name.
-     */
-    public void setSerifFontFamily(String font) {
-        assert mCanModifySettings;
-        synchronized (mContentSettingsLock) {
-            if (font != null && !mSerifFontFamily.equals(font)) {
-                mSerifFontFamily = font;
-                mEventHandler.syncSettingsLocked();
-            }
-        }
-    }
-
-    /**
-     * Get the serif font family name. The default is "serif".
-     * @return The serif font family name as a string.
-     */
-    public String getSerifFontFamily() {
-        synchronized (mContentSettingsLock) {
-            return mSerifFontFamily;
-        }
-    }
-
-    /**
-     * Set the cursive font family name.
-     * @param font A font family name.
-     */
-    public void setCursiveFontFamily(String font) {
-        assert mCanModifySettings;
-        synchronized (mContentSettingsLock) {
-            if (font != null && !mCursiveFontFamily.equals(font)) {
-                mCursiveFontFamily = font;
-                mEventHandler.syncSettingsLocked();
-            }
-        }
-    }
-
-    /**
-     * Get the cursive font family name. The default is "cursive".
-     * @return The cursive font family name as a string.
-     */
-    public String getCursiveFontFamily() {
-        synchronized (mContentSettingsLock) {
-            return mCursiveFontFamily;
-        }
-    }
-
-    /**
-     * Set the fantasy font family name.
-     * @param font A font family name.
-     */
-    public void setFantasyFontFamily(String font) {
-        assert mCanModifySettings;
-        synchronized (mContentSettingsLock) {
-            if (font != null && !mFantasyFontFamily.equals(font)) {
-                mFantasyFontFamily = font;
-                mEventHandler.syncSettingsLocked();
-            }
-        }
-    }
-
-    /**
-     * Get the fantasy font family name. The default is "fantasy".
-     * @return The fantasy font family name as a string.
-     */
-    public String getFantasyFontFamily() {
-        synchronized (mContentSettingsLock) {
-            return mFantasyFontFamily;
-        }
-    }
-
-    /**
-     * Set the minimum font size.
-     * @param size A non-negative integer between 1 and 72.
-     * Any number outside the specified range will be pinned.
-     */
-    public void setMinimumFontSize(int size) {
-        assert mCanModifySettings;
-        synchronized (mContentSettingsLock) {
-            size = clipFontSize(size);
-            if (mMinimumFontSize != size) {
-                mMinimumFontSize = size;
-                mEventHandler.syncSettingsLocked();
-            }
-        }
-    }
-
-    /**
-     * Get the minimum font size. The default is 8.
-     * @return A non-negative integer between 1 and 72.
-     */
-    public int getMinimumFontSize() {
-        synchronized (mContentSettingsLock) {
-            return mMinimumFontSize;
-        }
-    }
-
-    /**
-     * Set the minimum logical font size.
-     * @param size A non-negative integer between 1 and 72.
-     * Any number outside the specified range will be pinned.
-     */
-    public void setMinimumLogicalFontSize(int size) {
-        assert mCanModifySettings;
-        synchronized (mContentSettingsLock) {
-            size = clipFontSize(size);
-            if (mMinimumLogicalFontSize != size) {
-                mMinimumLogicalFontSize = size;
-                mEventHandler.syncSettingsLocked();
-            }
-        }
-    }
-
-    /**
-     * Get the minimum logical font size. The default is 8.
-     * @return A non-negative integer between 1 and 72.
-     */
-    public int getMinimumLogicalFontSize() {
-        synchronized (mContentSettingsLock) {
-            return mMinimumLogicalFontSize;
-        }
-    }
-
-    /**
-     * Set the default font size.
-     * @param size A non-negative integer between 1 and 72.
-     * Any number outside the specified range will be pinned.
-     */
-    public void setDefaultFontSize(int size) {
-        assert mCanModifySettings;
-        synchronized (mContentSettingsLock) {
-            size = clipFontSize(size);
-            if (mDefaultFontSize != size) {
-                mDefaultFontSize = size;
-                mEventHandler.syncSettingsLocked();
-            }
-        }
-    }
-
-    /**
-     * Get the default font size. The default is 16.
-     * @return A non-negative integer between 1 and 72.
-     */
-    public int getDefaultFontSize() {
-        synchronized (mContentSettingsLock) {
-            return mDefaultFontSize;
-        }
-    }
-
-    /**
-     * Set the default fixed font size.
-     * @param size A non-negative integer between 1 and 72.
-     * Any number outside the specified range will be pinned.
-     */
-    public void setDefaultFixedFontSize(int size) {
-        assert mCanModifySettings;
-        synchronized (mContentSettingsLock) {
-            size = clipFontSize(size);
-            if (mDefaultFixedFontSize != size) {
-                mDefaultFixedFontSize = size;
-                mEventHandler.syncSettingsLocked();
-            }
-        }
-    }
-
-    /**
-     * Get the default fixed font size. The default is 16.
-     * @return A non-negative integer between 1 and 72.
-     */
-    public int getDefaultFixedFontSize() {
-        synchronized (mContentSettingsLock) {
-            return mDefaultFixedFontSize;
-        }
-    }
-
-    /**
-     * Tell the WebView to enable JavaScript execution.
-     *
-     * @param flag True if the WebView should execute JavaScript.
-     */
-    public void setJavaScriptEnabled(boolean flag) {
-        assert mCanModifySettings;
-        synchronized (mContentSettingsLock) {
-            if (mJavaScriptEnabled != flag) {
-                mJavaScriptEnabled = flag;
-                mEventHandler.syncSettingsLocked();
-            }
-        }
-    }
-
-    /**
-     * Sets whether JavaScript running in the context of a file scheme URL
-     * should be allowed to access content from any origin. This includes
-     * access to content from other file scheme URLs. See
-     * {@link #setAllowFileAccessFromFileURLs}. To enable the most restrictive,
-     * and therefore secure policy, this setting should be disabled.
-     * <p>
-     * The default value is true for API level
-     * {@link android.os.Build.VERSION_CODES#ICE_CREAM_SANDWICH_MR1} and below,
-     * and false for API level {@link android.os.Build.VERSION_CODES#JELLY_BEAN}
-     * and above.
-     *
-     * @param flag whether JavaScript running in the context of a file scheme
-     *             URL should be allowed to access content from any origin
-     */
-    public void setAllowUniversalAccessFromFileURLs(boolean flag) {
-        assert mCanModifySettings;
-        synchronized (mContentSettingsLock) {
-            if (mAllowUniversalAccessFromFileURLs != flag) {
-                mAllowUniversalAccessFromFileURLs = flag;
-                mEventHandler.syncSettingsLocked();
-            }
-        }
-    }
-
-    /**
-     * Sets whether JavaScript running in the context of a file scheme URL
-     * should be allowed to access content from other file scheme URLs. To
-     * enable the most restrictive, and therefore secure policy, this setting
-     * should be disabled. Note that the value of this setting is ignored if
-     * the value of {@link #getAllowUniversalAccessFromFileURLs} is true.
-     * <p>
-     * The default value is true for API level
-     * {@link android.os.Build.VERSION_CODES#ICE_CREAM_SANDWICH_MR1} and below,
-     * and false for API level {@link android.os.Build.VERSION_CODES#JELLY_BEAN}
-     * and above.
-     *
-     * @param flag whether JavaScript running in the context of a file scheme
-     *             URL should be allowed to access content from other file
-     *             scheme URLs
-     */
-    public void setAllowFileAccessFromFileURLs(boolean flag) {
-        assert mCanModifySettings;
-        synchronized (mContentSettingsLock) {
-            if (mAllowFileAccessFromFileURLs != flag) {
-                mAllowFileAccessFromFileURLs = flag;
-                mEventHandler.syncSettingsLocked();
-            }
-        }
-    }
-
-    /**
-     * Tell the WebView to load image resources automatically.
-     * Note that setting this flag to false this does not block image loads
-     * from WebCore cache.
-     * @param flag True if the WebView should load images automatically.
-     */
-    public void setLoadsImagesAutomatically(boolean flag) {
-        assert mCanModifySettings;
-        synchronized (mContentSettingsLock) {
-            if (mLoadsImagesAutomatically != flag) {
-                mLoadsImagesAutomatically = flag;
-                mEventHandler.syncSettingsLocked();
-            }
-        }
-    }
-
-    /**
-     * Return true if the WebView will load image resources automatically.
-     * The default is true.
-     * @return True if the WebView loads images automatically.
-     */
-    public boolean getLoadsImagesAutomatically() {
-        synchronized (mContentSettingsLock) {
-            return mLoadsImagesAutomatically;
-        }
-    }
-
-    /**
-     * Sets whether images are enabled for this WebView. Setting this from
-     * false to true will reload the blocked images in place.
-     * Note that unlike {@link #setLoadsImagesAutomatically}, setting this
-     * flag to false this will block image loads from WebCore cache as well.
-     * The default is true.
-     * @param flag whether the WebView should enable images.
-     */
-    public void setImagesEnabled(boolean flag) {
-        assert mCanModifySettings;
-        synchronized (mContentSettingsLock) {
-            if (mImagesEnabled != flag) {
-                mImagesEnabled = flag;
-                mEventHandler.syncSettingsLocked();
-            }
-        }
-    }
-
-    /**
-     * Gets whether images are enabled for this WebView.
-     * @return true if the WebView has images eanbled
-     */
-    public boolean getImagesEnabled() {
-        synchronized (mContentSettingsLock) {
-            return mImagesEnabled;
-        }
-    }
-
-    /**
-     * Return true if JavaScript is enabled. <b>Note: The default is false.</b>
+     * Return true if JavaScript is enabled.
      *
      * @return True if JavaScript is enabled.
      */
     public boolean getJavaScriptEnabled() {
-        synchronized (mContentSettingsLock) {
-            return mJavaScriptEnabled;
-        }
-    }
-
-    /**
-     * Gets whether JavaScript running in the context of a file scheme URL can
-     * access content from any origin. This includes access to content from
-     * other file scheme URLs.
-     *
-     * @return whether JavaScript running in the context of a file scheme URL
-     *         can access content from any origin
-     * @see #setAllowUniversalAccessFromFileURLs
-     */
-    public boolean getAllowUniversalAccessFromFileURLs() {
-        synchronized (mContentSettingsLock) {
-            return mAllowUniversalAccessFromFileURLs;
-        }
-    }
-
-    /**
-     * Gets whether JavaScript running in the context of a file scheme URL can
-     * access content from other file scheme URLs.
-     *
-     * @return whether JavaScript running in the context of a file scheme URL
-     *         can access content from other file scheme URLs
-     * @see #setAllowFileAccessFromFileURLs
-     */
-    public boolean getAllowFileAccessFromFileURLs() {
-        synchronized (mContentSettingsLock) {
-            return mAllowFileAccessFromFileURLs;
-        }
-    }
-
-    /**
-     * Tell the WebView to enable plugins.
-     * @param flag True if the WebView should load plugins.
-     * @deprecated This method has been deprecated in favor of
-     *             {@link #setPluginState}
-     */
-    @Deprecated
-    public void setPluginsEnabled(boolean flag) {
-        assert mCanModifySettings;
-        setPluginState(flag ? PluginState.ON : PluginState.OFF);
-    }
-
-    /**
-     * Tell the WebView to enable, disable, or have plugins on demand. On
-     * demand mode means that if a plugin exists that can handle the embedded
-     * content, a placeholder icon will be shown instead of the plugin. When
-     * the placeholder is clicked, the plugin will be enabled.
-     * @param state One of the PluginState values.
-     */
-    public void setPluginState(PluginState state) {
-        assert mCanModifySettings;
-        synchronized (mContentSettingsLock) {
-            if (mPluginState != state) {
-                mPluginState = state;
-                mEventHandler.syncSettingsLocked();
-            }
-        }
-    }
-
-    /**
-     * Return true if plugins are enabled.
-     * @return True if plugins are enabled.
-     * @deprecated This method has been replaced by {@link #getPluginState}
-     */
-    @Deprecated
-    public boolean getPluginsEnabled() {
-        synchronized (mContentSettingsLock) {
-            return mPluginState == PluginState.ON;
-        }
-    }
-
-    /**
-     * Return true if plugins are disabled.
-     * @return True if plugins are disabled.
-     * @hide
-     */
-    @CalledByNative
-    private boolean getPluginsDisabled() {
-        // This should only be called from SyncToNative, which is called
-        // either from the constructor, or with mContentSettingsLock being held.
-        return mPluginState == PluginState.OFF;
-    }
-
-    /**
-     * Sets if plugins are disabled.
-     * @return True if plugins are disabled.
-     * @hide
-     */
-    @CalledByNative
-    private void setPluginsDisabled(boolean disabled) {
-        // This should only be called from SyncFromToNative, which is called
-        // either from the constructor, or with mContentSettingsLock being held.
-        mPluginState = disabled ? PluginState.OFF : PluginState.ON;
-    }
-
-    /**
-     * Return the current plugin state.
-     * @return A value corresponding to the enum PluginState.
-     */
-    public PluginState getPluginState() {
-        synchronized (mContentSettingsLock) {
-            return mPluginState;
-        }
-    }
-
-
-    /**
-     * Tell javascript to open windows automatically. This applies to the
-     * javascript function window.open().
-     * @param flag True if javascript can open windows automatically.
-     */
-    public void setJavaScriptCanOpenWindowsAutomatically(boolean flag) {
-        assert mCanModifySettings;
-        synchronized (mContentSettingsLock) {
-            if (mJavaScriptCanOpenWindowsAutomatically != flag) {
-                mJavaScriptCanOpenWindowsAutomatically = flag;
-                mEventHandler.syncSettingsLocked();
-            }
-        }
-    }
-
-    /**
-     * Return true if javascript can open windows automatically. The default
-     * is false.
-     * @return True if javascript can open windows automatically during
-     *         window.open().
-     */
-    public boolean getJavaScriptCanOpenWindowsAutomatically() {
-        synchronized (mContentSettingsLock) {
-            return mJavaScriptCanOpenWindowsAutomatically;
-        }
-    }
-
-    /**
-     * Sets the underlying layout algorithm. The default is
-     * {@link LayoutAlgorithm#NARROW_COLUMNS}.
-     *
-     * @param l the layout algorithm to use, as a {@link LayoutAlgorithm} value
-     */
-    public void setLayoutAlgorithm(LayoutAlgorithm l) {
-        assert mCanModifySettings;
-        synchronized (mContentSettingsLock) {
-            if (mLayoutAlgorithm != l) {
-                mLayoutAlgorithm = l;
-                mEventHandler.syncSettingsLocked();
-            }
-        }
-    }
-
-    /**
-     * Gets the current layout algorithm.
-     *
-     * @return the layout algorithm in use, as a {@link LayoutAlgorithm} value
-     * @see #setLayoutAlgorithm
-     */
-    public LayoutAlgorithm getLayoutAlgorithm() {
-        synchronized (mContentSettingsLock) {
-            return mLayoutAlgorithm;
-        }
-    }
-
-    /**
-     * Sets whether Text Auto-sizing layout algorithm is enabled.
-     *
-     * @param enabled whether Text Auto-sizing layout algorithm is enabled
-     * @hide
-     */
-    @CalledByNative
-    private void setTextAutosizingEnabled(boolean enabled) {
-        // This should only be called from SyncFromNative, which is called
-        // either from the constructor, or with mContentSettingsLock being held.
-        mLayoutAlgorithm = enabled ?
-                LayoutAlgorithm.TEXT_AUTOSIZING : LayoutAlgorithm.NARROW_COLUMNS;
-    }
-
-    /**
-     * Gets whether Text Auto-sizing layout algorithm is enabled.
-     *
-     * @return true if Text Auto-sizing layout algorithm is enabled
-     * @hide
-     */
-    @CalledByNative
-    private boolean getTextAutosizingEnabled() {
-        return mLayoutAlgorithm == LayoutAlgorithm.TEXT_AUTOSIZING;
-    }
-
-    /**
-     * Tells the WebView whether it supports multiple windows. True means
-     * that {@link WebChromeClient#onCreateWindow(WebView, boolean,
-     * boolean, Message)} is implemented by the host application.
-     */
-    public void setSupportMultipleWindows(boolean support) {
-        assert mCanModifySettings;
-        synchronized (mContentSettingsLock) {
-            if (mSupportMultipleWindows != support) {
-                mSupportMultipleWindows = support;
-                mEventHandler.syncSettingsLocked();
-            }
-        }
-    }
-
-    /**
-     * Gets whether the WebView is supporting multiple windows.
-     *
-     * @return true if the WebView is supporting multiple windows. This means
-     *         that {@link WebChromeClient#onCreateWindow(WebView, boolean,
-     *         boolean, Message)} is implemented by the host application.
-     */
-    public boolean supportMultipleWindows() {
-        synchronized (mContentSettingsLock) {
-            return mSupportMultipleWindows;
-        }
-    }
-
-    /**
-     * Sets whether the WebView should enable support for the &quot;viewport&quot;
-     * HTML meta tag or should use a wide viewport.
-     * When the value of the setting is false, the layout width is always set to the
-     * width of the WebView control in device-independent (CSS) pixels.
-     * When the value is true and the page contains the viewport meta tag, the value
-     * of the width specified in the tag is used. If the page does not contain the tag or
-     * does not provide a width, then a wide viewport will be used.
-     *
-     * @param use whether to enable support for the viewport meta tag
-     */
-    public void setUseWideViewPort(boolean use) {
-        assert mCanModifySettings;
-        synchronized (mContentSettingsLock) {
-            if (mUseWideViewport != use) {
-                mUseWideViewport = use;
-                mEventHandler.syncSettingsLocked();
-            }
-        }
-    }
-
-    /**
-     * Gets whether the WebView supports the &quot;viewport&quot;
-     * HTML meta tag or will use a wide viewport.
-     *
-     * @return true if the WebView supports the viewport meta tag
-     * @see #setUseWideViewPort
-     */
-    public boolean getUseWideViewPort() {
-        synchronized (mContentSettingsLock) {
-            return mUseWideViewport;
-        }
-    }
-
-    /**
-     * Sets whether the Application Caches API should be enabled. The default
-     * is false. Note that in order for the Application Caches API to be
-     * enabled, a non-empty database path must also be supplied to
-     * {@link #setAppCachePath} (this is done for compatibility with the
-     * legacy implementation).
-     *
-     * @param flag true if the WebView should enable Application Caches
-     */
-    public void setAppCacheEnabled(boolean flag) {
-        assert mCanModifySettings;
-        synchronized (mContentSettingsLock) {
-            if (mAppCacheEnabled != flag) {
-                mAppCacheEnabled = flag;
-                mEventHandler.syncSettingsLocked();
-            }
-        }
-    }
-
-    /**
-     * Sets the path to the Application Caches files. In order for the
-     * Application Caches API to be enabled, this method must be called with a
-     * non-empty path. This method should only be called once: repeated calls
-     * are ignored.
-     *
-     * @param path a non empty-string
-     */
-    public void setAppCachePath(String path) {
-        assert mCanModifySettings;
-        boolean needToSync = false;
-        synchronized (sGlobalContentSettingsLock) {
-            // AppCachePath can only be set once.
-            if (!sAppCachePathIsSet && path != null && !path.isEmpty()) {
-                sAppCachePathIsSet = true;
-                needToSync = true;
-            }
-        }
-        // The obvious problem here is that other WebViews will not be updated,
-        // until they execute synchronization from Java to the native side.
-        // But this is the same behaviour as it was in the legacy WebView.
-        if (needToSync) {
-            synchronized (mContentSettingsLock) {
-                mEventHandler.syncSettingsLocked();
-            }
-        }
-    }
-
-    /**
-     * Gets whether Application Cache is enabled.
-     *
-     * @return true if Application Cache is enabled
-     * @hide
-     */
-    @CalledByNative
-    private boolean getAppCacheEnabled() {
-        // This should only be called from SyncToNative, which is called
-        // either from the constructor, or with mContentSettingsLock being held.
-        if (!mAppCacheEnabled) {
-            return false;
-        }
-        synchronized (sGlobalContentSettingsLock) {
-            return sAppCachePathIsSet;
-        }
-    }
-
-    /**
-     * Sets whether the DOM storage API is enabled. The default value is false.
-     *
-     * @param flag true if the ContentView should use the DOM storage API
-     */
-    public void setDomStorageEnabled(boolean flag) {
-        assert mCanModifySettings;
-        synchronized (mContentSettingsLock) {
-            if (mDomStorageEnabled != flag) {
-                mDomStorageEnabled = flag;
-                mEventHandler.syncSettingsLocked();
-            }
-        }
-    }
-
-    /**
-     * Gets whether the DOM Storage APIs are enabled.
-     *
-     * @return true if the DOM Storage APIs are enabled
-     * @see #setDomStorageEnabled
-     */
-    public boolean getDomStorageEnabled() {
-       synchronized (mContentSettingsLock) {
-           return mDomStorageEnabled;
-       }
-    }
-
-    /**
-     * Sets whether the WebSQL storage API is enabled. The default value is false.
-     *
-     * @param flag true if the ContentView should use the WebSQL storage API
-     */
-    public void setDatabaseEnabled(boolean flag) {
-        assert mCanModifySettings;
-        synchronized (mContentSettingsLock) {
-            if (mDatabaseEnabled != flag) {
-                mDatabaseEnabled = flag;
-                mEventHandler.syncSettingsLocked();
-            }
-        }
-    }
-
-    /**
-     * Gets whether the WebSQL Storage APIs are enabled.
-     *
-     * @return true if the WebSQL Storage APIs are enabled
-     * @see #setDatabaseEnabled
-     */
-    public boolean getDatabaseEnabled() {
-       synchronized (mContentSettingsLock) {
-           return mDatabaseEnabled;
-       }
-    }
-
-    /**
-     * Set the default text encoding name to use when decoding html pages.
-     * @param encoding The text encoding name.
-     */
-    public void setDefaultTextEncodingName(String encoding) {
-        assert mCanModifySettings;
-        synchronized (mContentSettingsLock) {
-            if (encoding != null && !mDefaultTextEncoding.equals(encoding)) {
-                mDefaultTextEncoding = encoding;
-                mEventHandler.syncSettingsLocked();
-            }
-        }
-    }
-
-    /**
-     * Get the default text encoding name. The default is "Latin-1".
-     * @return The default text encoding name as a string.
-     */
-    public String getDefaultTextEncodingName() {
-        synchronized (mContentSettingsLock) {
-            return mDefaultTextEncoding;
-        }
-    }
-
-    /**
-     * Set whether the user gesture is required for media playback.
-     * @param require true if the user gesture is required.
-     */
-    public void setMediaPlaybackRequiresUserGesture(boolean require) {
-        assert mCanModifySettings;
-        synchronized (mContentSettingsLock) {
-            if (mMediaPlaybackRequiresUserGesture != require) {
-                mMediaPlaybackRequiresUserGesture = require;
-                mEventHandler.syncSettingsLocked();
-            }
-        }
-    }
-
-    /**
-     * Get whether the user gesture is required for Media Playback.
-     * @return true if the user gesture is required.
-     */
-    public boolean getMediaPlaybackRequiresUserGesture() {
-        synchronized (mContentSettingsLock) {
-            return mMediaPlaybackRequiresUserGesture;
-        }
-    }
-
-    /**
-     * Set the default video poster URL.
-     * @param url The url of default video poster.
-     */
-    public void setDefaultVideoPosterURL(String url) {
-        assert mCanModifySettings;
-        synchronized (mContentSettingsLock) {
-            if (mDefaultVideoPosterURL != null && !mDefaultVideoPosterURL.equals(url) ||
-                    mDefaultVideoPosterURL == null && url != null) {
-                mDefaultVideoPosterURL = url;
-                mEventHandler.syncSettingsLocked();
-            }
-        }
-    }
-
-    /**
-     * Get the default video poster URL.
-     */
-    public String getDefaultVideoPosterURL() {
-        synchronized (mContentSettingsLock) {
-            return mDefaultVideoPosterURL;
-        }
-    }
-
-    private int clipFontSize(int size) {
-        if (size < MINIMUM_FONT_SIZE) {
-            return MINIMUM_FONT_SIZE;
-        } else if (size > MAXIMUM_FONT_SIZE) {
-            return MAXIMUM_FONT_SIZE;
-        }
-        return size;
+        return ThreadUtils.runOnUiThreadBlockingNoException(new Callable<Boolean>() {
+                @Override
+                public Boolean call() {
+                    if (mNativeContentSettings != 0) {
+                        return nativeGetJavaScriptEnabled(mNativeContentSettings);
+                    } else {
+                        return false;
+                    }
+                }
+            });
     }
 
     /**
@@ -1257,69 +221,13 @@
      * windows in an already created WebView)
      */
     public void initFrom(ContentSettings settings) {
-        setLayoutAlgorithm(settings.getLayoutAlgorithm());
-        setLoadWithOverviewMode(settings.getLoadWithOverviewMode());
-        setTextZoom(settings.getTextZoom());
-        setStandardFontFamily(settings.getStandardFontFamily());
-        setFixedFontFamily(settings.getFixedFontFamily());
-        setSansSerifFontFamily(settings.getSansSerifFontFamily());
-        setSerifFontFamily(settings.getSerifFontFamily());
-        setCursiveFontFamily(settings.getCursiveFontFamily());
-        setFantasyFontFamily(settings.getFantasyFontFamily());
-        setDefaultTextEncodingName(settings.getDefaultTextEncodingName());
-        setUserAgentString(settings.getUserAgentString());
-        setMinimumFontSize(settings.getMinimumFontSize());
-        setMinimumLogicalFontSize(settings.getMinimumLogicalFontSize());
-        setDefaultFontSize(settings.getDefaultFontSize());
-        setDefaultFixedFontSize(settings.getDefaultFixedFontSize());
-        setLoadsImagesAutomatically(settings.getLoadsImagesAutomatically());
-        setImagesEnabled(settings.getImagesEnabled());
-        setJavaScriptEnabled(settings.getJavaScriptEnabled());
-        setAllowUniversalAccessFromFileURLs(settings.getAllowUniversalAccessFromFileURLs());
-        setAllowFileAccessFromFileURLs(settings.getAllowFileAccessFromFileURLs());
-        setJavaScriptCanOpenWindowsAutomatically(
-                settings.getJavaScriptCanOpenWindowsAutomatically());
-        setSupportMultipleWindows(settings.supportMultipleWindows());
-        setPluginState(settings.getPluginState());
-        setAppCacheEnabled(settings.mAppCacheEnabled);
-        setDomStorageEnabled(settings.getDomStorageEnabled());
-        setDatabaseEnabled(settings.getDatabaseEnabled());
         setSupportZoom(settings.supportZoom());
         setBuiltInZoomControls(settings.getBuiltInZoomControls());
         setDisplayZoomControls(settings.getDisplayZoomControls());
-        setMediaPlaybackRequiresUserGesture(settings.getMediaPlaybackRequiresUserGesture());
-        setDefaultVideoPosterURL(settings.getDefaultVideoPosterURL());
-    }
-
-    /**
-     * Synchronize java side and native side settings. When ContentView
-     * is running in PERSONALITY_VIEW mode, this needs to be done after
-     * any java side setting is changed to sync them to native. In
-     * PERSONALITY_CHROME mode, this needs to be called whenever native
-     * settings are changed to sync them to java.
-     */
-    void syncSettings() {
-        synchronized (mContentSettingsLock) {
-            mEventHandler.syncSettingsLocked();
-        }
-    }
-
-    void syncToNativeOnUiThread() {
-        if (mNativeContentSettings != 0) nativeSyncToNative(mNativeContentSettings);
-    }
-
-    void syncFromNativeOnUiThread() {
-        if (mNativeContentSettings != 0) nativeSyncFromNative(mNativeContentSettings);
     }
 
     // Initialize the ContentSettings native side.
-    private native int nativeInit(int contentViewPtr, boolean isMasterMode);
+    private native int nativeInit(int contentViewPtr);
 
-    private static native String nativeGetDefaultUserAgent();
-
-    // Synchronize Java settings from native settings.
-    private native void nativeSyncFromNative(int nativeContentSettings);
-
-    // Synchronize native settings from Java settings.
-    private native void nativeSyncToNative(int nativeContentSettings);
+    private native boolean nativeGetJavaScriptEnabled(int nativeContentSettings);
 }
diff --git a/content/public/android/java/src/org/chromium/content/browser/ContentView.java b/content/public/android/java/src/org/chromium/content/browser/ContentView.java
index fa5cea7..9ea4fb4 100644
--- a/content/public/android/java/src/org/chromium/content/browser/ContentView.java
+++ b/content/public/android/java/src/org/chromium/content/browser/ContentView.java
@@ -23,11 +23,8 @@
 
 import com.google.common.annotations.VisibleForTesting;
 
-import org.chromium.content.common.ProcessInitException;
 import org.chromium.content.common.TraceEvent;
-import org.chromium.ui.gfx.NativeWindow;
-
-import java.util.ArrayList;
+import org.chromium.ui.WindowAndroid;
 
 /**
  * The containing view for {@link ContentViewCore} that exists in the Android UI hierarchy and
@@ -36,26 +33,30 @@
  * TODO(joth): Remove any methods overrides from this class that were added for WebView
  *             compatibility.
  */
-public class ContentView extends FrameLayout implements ContentViewCore.InternalAccessDelegate {
+public class ContentView extends FrameLayout
+        implements ContentViewCore.InternalAccessDelegate, PageInfo {
     // Used when ContentView implements a standalone View.
     public static final int PERSONALITY_VIEW = ContentViewCore.PERSONALITY_VIEW;
     // Used for Chrome.
     public static final int PERSONALITY_CHROME = ContentViewCore.PERSONALITY_CHROME;
 
-    private ContentViewCore mContentViewCore;
+    private final ContentViewCore mContentViewCore;
+
+    private float mCurrentTouchOffsetX;
+    private float mCurrentTouchOffsetY;
 
     /**
      * Creates an instance of a ContentView.
      * @param context The Context the view is running in, through which it can
      *                access the current theme, resources, etc.
      * @param nativeWebContents A pointer to the native web contents.
-     * @param nativeWindow An instance of the NativeWindow.
+     * @param windowAndroid An instance of the WindowAndroid.
      * @param personality One of {@link #PERSONALITY_CHROME} or {@link #PERSONALITY_VIEW}.
      * @return A ContentView instance.
      */
     public static ContentView newInstance(Context context, int nativeWebContents,
-            NativeWindow nativeWindow, int personality) {
-        return newInstance(context, nativeWebContents, nativeWindow, null,
+            WindowAndroid windowAndroid, int personality) {
+        return newInstance(context, nativeWebContents, windowAndroid, null,
                 android.R.attr.webViewStyle, personality);
     }
 
@@ -64,15 +65,15 @@
      * @param context The Context the view is running in, through which it can
      *                access the current theme, resources, etc.
      * @param nativeWebContents A pointer to the native web contents.
-     * @param nativeWindow An instance of the NativeWindow.
+     * @param windowAndroid An instance of the WindowAndroid.
      * @param attrs The attributes of the XML tag that is inflating the view.
      * @return A ContentView instance.
      */
     public static ContentView newInstance(Context context, int nativeWebContents,
-            NativeWindow nativeWindow, AttributeSet attrs) {
+            WindowAndroid windowAndroid, AttributeSet attrs) {
         // TODO(klobag): use the WebViewStyle as the default style for now. It enables scrollbar.
         // When ContentView is moved to framework, we can define its own style in the res.
-        return newInstance(context, nativeWebContents, nativeWindow, attrs,
+        return newInstance(context, nativeWebContents, windowAndroid, attrs,
                 android.R.attr.webViewStyle);
     }
 
@@ -81,34 +82,71 @@
      * @param context The Context the view is running in, through which it can
      *                access the current theme, resources, etc.
      * @param nativeWebContents A pointer to the native web contents.
-     * @param nativeWindow An instance of the NativeWindow.
+     * @param windowAndroid An instance of the WindowAndroid.
      * @param attrs The attributes of the XML tag that is inflating the view.
      * @param defStyle The default style to apply to this view.
      * @return A ContentView instance.
      */
     public static ContentView newInstance(Context context, int nativeWebContents,
-            NativeWindow nativeWindow, AttributeSet attrs, int defStyle) {
-        return newInstance(context, nativeWebContents, nativeWindow, attrs, defStyle,
+            WindowAndroid windowAndroid, AttributeSet attrs, int defStyle) {
+        return newInstance(context, nativeWebContents, windowAndroid, attrs, defStyle,
                 PERSONALITY_VIEW);
     }
 
     private static ContentView newInstance(Context context, int nativeWebContents,
-            NativeWindow nativeWindow, AttributeSet attrs, int defStyle, int personality) {
+            WindowAndroid windowAndroid, AttributeSet attrs, int defStyle, int personality) {
         if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
-            return new ContentView(context, nativeWebContents, nativeWindow, attrs, defStyle,
+            return new ContentView(context, nativeWebContents, windowAndroid, attrs, defStyle,
                     personality);
         } else {
-            return new JellyBeanContentView(context, nativeWebContents, nativeWindow, attrs,
+            return new JellyBeanContentView(context, nativeWebContents, windowAndroid, attrs,
                     defStyle, personality);
         }
     }
 
-    protected ContentView(Context context, int nativeWebContents, NativeWindow nativeWindow,
+    protected ContentView(Context context, int nativeWebContents, WindowAndroid windowAndroid,
             AttributeSet attrs, int defStyle, int personality) {
         super(context, attrs, defStyle);
 
         mContentViewCore = new ContentViewCore(context, personality);
-        mContentViewCore.initialize(this, this, nativeWebContents, nativeWindow, false);
+        mContentViewCore.initialize(this, this, nativeWebContents, windowAndroid);
+    }
+
+    // PageInfo implementation.
+
+    @Override
+    public String getUrl() {
+        return mContentViewCore.getUrl();
+    }
+
+    @Override
+    public String getTitle() {
+        return mContentViewCore.getTitle();
+    }
+
+    @Override
+    public boolean isReadyForSnapshot() {
+        return !isCrashed() && isReady();
+    }
+
+    @Override
+    public Bitmap getBitmap() {
+        return getBitmap(getWidth(), getHeight());
+    }
+
+    @Override
+    public Bitmap getBitmap(int width, int height) {
+        return mContentViewCore.getBitmap(width, height);
+    }
+
+    @Override
+    public int getBackgroundColor() {
+        return mContentViewCore.getBackgroundColor();
+    }
+
+    @Override
+    public View getView() {
+        return this;
     }
 
     /**
@@ -180,25 +218,17 @@
         return mContentViewCore.getContentViewClient();
     }
 
-    public int getBackgroundColor() {
-        return mContentViewCore.getBackgroundColor();
-    }
-
     /**
      * Load url without fixing up the url string. Consumers of ContentView are responsible for
      * ensuring the URL passed in is properly formatted (i.e. the scheme has been added if left
      * off during user input).
      *
-     * @param pararms Parameters for this load.
+     * @param params Parameters for this load.
      */
     public void loadUrl(LoadUrlParams params) {
         mContentViewCore.loadUrl(params);
     }
 
-    void setAllUserAgentOverridesInHistory() {
-        mContentViewCore.setAllUserAgentOverridesInHistory();
-    }
-
     /**
      * Stops loading the current web contents.
      */
@@ -207,41 +237,6 @@
     }
 
     /**
-     * Get the URL of the current page.
-     *
-     * @return The URL of the current page.
-     */
-    public String getUrl() {
-        return mContentViewCore.getUrl();
-    }
-
-    /**
-     * Get the title of the current page.
-     *
-     * @return The title of the current page.
-     */
-    public String getTitle() {
-        return mContentViewCore.getTitle();
-    }
-
-    public Bitmap getBitmap() {
-        return getBitmap(getWidth(), getHeight());
-    }
-
-    public Bitmap getBitmap(int width, int height) {
-        return mContentViewCore.getBitmap(width, height);
-    }
-
-    /**
-     * @return Whether the ContentView is covered by an overlay that is more than half
-     *         of it's surface. This is used to determine if we need to do a slow bitmap capture or
-     *         to show the ContentView without them.
-     */
-    public boolean hasLargeOverlay() {
-        return mContentViewCore.hasLargeOverlay();
-    }
-
-    /**
      * @return Whether the current WebContents has a previous navigation entry.
      */
     public boolean canGoBack() {
@@ -486,12 +481,19 @@
 
     @Override
     public boolean dispatchKeyEvent(KeyEvent event) {
-        return mContentViewCore.dispatchKeyEvent(event);
+        if (isFocused()) {
+            return mContentViewCore.dispatchKeyEvent(event);
+        } else {
+            return super.dispatchKeyEvent(event);
+        }
     }
 
     @Override
     public boolean onTouchEvent(MotionEvent event) {
-        return mContentViewCore.onTouchEvent(event);
+        MotionEvent offset = createOffsetMotionEvent(event);
+        boolean consumed = mContentViewCore.onTouchEvent(offset);
+        offset.recycle();
+        return consumed;
     }
 
     /**
@@ -509,6 +511,23 @@
         return mContentViewCore.onGenericMotionEvent(event);
     }
 
+    /**
+     * Sets the current amount to offset incoming touch events by.  This is used to handle content
+     * moving and not lining up properly with the android input system.
+     * @param dx The X offset in pixels to shift touch events.
+     * @param dy The Y offset in pixels to shift touch events.
+     */
+    public void setCurrentMotionEventOffsets(float dx, float dy) {
+        mCurrentTouchOffsetX = dx;
+        mCurrentTouchOffsetY = dy;
+    }
+
+    private MotionEvent createOffsetMotionEvent(MotionEvent src) {
+        MotionEvent dst = MotionEvent.obtain(src);
+        dst.offsetLocation(mCurrentTouchOffsetX, mCurrentTouchOffsetY);
+        return dst;
+    }
+
     @Override
     protected void onConfigurationChanged(Configuration newConfig) {
         mContentViewCore.onConfigurationChanged(newConfig);
@@ -753,13 +772,6 @@
     }
 
     /**
-     * @return Whether or not the texture view is available or not.
-     */
-    public boolean isAvailable() {
-        return mContentViewCore.isAvailable();
-    }
-
-    /**
      * Returns whether or not accessibility injection is being used.
      */
     public boolean isInjectingAccessibilityScript() {
@@ -787,6 +799,24 @@
         mContentViewCore.exitFullscreen();
     }
 
+    /**
+     * Return content scroll y.
+     *
+     * @return The vertical scroll position in pixels.
+     */
+    public int getContentScrollY() {
+        return mContentViewCore.computeVerticalScrollOffset();
+    }
+
+    /**
+     * Return content height.
+     *
+     * @return The height of the content in pixels.
+     */
+    public int getContentHeight() {
+        return mContentViewCore.computeVerticalScrollRange();
+    }
+
     ///////////////////////////////////////////////////////////////////////////////////////////////
     //              Start Implementation of ContentViewCore.InternalAccessDelegate               //
     ///////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/content/public/android/java/src/org/chromium/content/browser/ContentViewClient.java b/content/public/android/java/src/org/chromium/content/browser/ContentViewClient.java
index 9d765a3..3176ecc 100644
--- a/content/public/android/java/src/org/chromium/content/browser/ContentViewClient.java
+++ b/content/public/android/java/src/org/chromium/content/browser/ContentViewClient.java
@@ -42,14 +42,6 @@
     }
 
     /**
-     * Notifies that the content size has changed.
-     * @param widthCss The width of the content in CSS pixels.
-     * @param heightCss The height of the content in CSS pixels.
-     */
-    public void onContentSizeChanged(float widthCss, float heightCss) {
-    }
-
-    /**
       * Lets client listen on the scaling changes on delayed, throttled
       * and best-effort basis. Used for WebView.onScaleChanged.
       */
@@ -60,9 +52,10 @@
      * Notifies the client that the position of the top controls has changed.
      * @param topControlsOffsetYPix The Y offset of the top controls in physical pixels.
      * @param contentOffsetYPix The Y offset of the content in physical pixels.
+     * @param overdrawBottomHeightPix The overdraw height.
      */
     public void onOffsetsForFullscreenChanged(
-            float topControlsOffsetYPix, float contentOffsetYPix) {
+            float topControlsOffsetYPix, float contentOffsetYPix, float overdrawBottomHeightPix) {
     }
 
     public void onTabCrash() {
@@ -173,4 +166,7 @@
 
     public void onExternalVideoSurfaceRequested(int playerId) {
     }
+
+    public void onGeometryChanged(int playerId, float x, float y, float height, float width) {
+    }
 }
diff --git a/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java b/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java
index 731166d..20b30d8 100644
--- a/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java
+++ b/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java
@@ -34,6 +34,7 @@
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputConnection;
 import android.view.inputmethod.InputMethodManager;
+import android.widget.FrameLayout;
 
 import com.google.common.annotations.VisibleForTesting;
 
@@ -42,10 +43,19 @@
 import org.chromium.base.WeakContext;
 import org.chromium.content.R;
 import org.chromium.content.browser.ContentViewGestureHandler.MotionEventDelegate;
-import org.chromium.content.browser.ImeAdapter.AdapterInputConnectionFactory;
 import org.chromium.content.browser.accessibility.AccessibilityInjector;
+import org.chromium.content.browser.input.AdapterInputConnection;
+import org.chromium.content.browser.input.HandleView;
+import org.chromium.content.browser.input.ImeAdapter;
+import org.chromium.content.browser.input.ImeAdapter.AdapterInputConnectionFactory;
+import org.chromium.content.browser.input.InsertionHandleController;
+import org.chromium.content.browser.input.SelectPopupDialog;
+import org.chromium.content.browser.input.SelectionHandleController;
 import org.chromium.content.common.TraceEvent;
-import org.chromium.ui.gfx.NativeWindow;
+import org.chromium.ui.ViewAndroid;
+import org.chromium.ui.ViewAndroidDelegate;
+import org.chromium.ui.WindowAndroid;
+import org.chromium.ui.gfx.DeviceDisplayInfo;
 
 import java.lang.annotation.Annotation;
 import java.util.HashMap;
@@ -157,21 +167,102 @@
     }
 
     /**
-     * Interface for subscribing to content size changes.
+     * An interface that allows the embedder to be notified when the pinch gesture starts and
+     * stops.
      */
-    public static interface ContentSizeChangeListener {
+    public static interface PinchGestureStateListener {
         /**
-         * Called when the content size changes.
-         * The containing view may want to adjust its size to match the content.
+         * Called when the pinch gesture starts.
          */
-        void onContentSizeChanged(int contentWidthPix, int contentHeightPix);
+        void onPinchGestureStart();
+        /**
+         * Called when the pinch gesture ends.
+         */
+        void onPinchGestureEnd();
+    }
+
+    private VSyncManager.Provider mVSyncProvider;
+    private VSyncManager.Listener mVSyncListener;
+    private int mVSyncSubscriberCount;
+    private boolean mVSyncListenerRegistered;
+
+    // To avoid IPC delay we use input events to directly trigger a vsync signal in the renderer.
+    // When we do this, we also need to avoid sending the real vsync signal for the current
+    // frame to avoid double-ticking. This flag is used to inhibit the next vsync notification.
+    private boolean mDidSignalVSyncUsingInputEvent;
+
+    public VSyncManager.Listener getVSyncListener(VSyncManager.Provider vsyncProvider) {
+        if (mVSyncProvider != null && mVSyncListenerRegistered) {
+            mVSyncProvider.unregisterVSyncListener(mVSyncListener);
+            mVSyncListenerRegistered = false;
+        }
+
+        mVSyncProvider = vsyncProvider;
+        mVSyncListener = new VSyncManager.Listener() {
+            @Override
+            public void updateVSync(long tickTimeMicros, long intervalMicros) {
+                if (mNativeContentViewCore != 0) {
+                    nativeUpdateVSyncParameters(mNativeContentViewCore, tickTimeMicros,
+                            intervalMicros);
+                }
+            }
+
+            @Override
+            public void onVSync(long frameTimeMicros) {
+                if (mDidSignalVSyncUsingInputEvent) {
+                    TraceEvent.instant("ContentViewCore::onVSync ignored");
+                    mDidSignalVSyncUsingInputEvent = false;
+                    return;
+                }
+                if (mNativeContentViewCore != 0) {
+                    nativeOnVSync(mNativeContentViewCore, frameTimeMicros);
+                }
+            }
+        };
+
+        if (mVSyncSubscriberCount > 0) {
+            // setVSyncNotificationEnabled(true) is called before getVSyncListener.
+            vsyncProvider.registerVSyncListener(mVSyncListener);
+            mVSyncListenerRegistered = true;
+        }
+
+        return mVSyncListener;
+    }
+
+    @CalledByNative
+    void setVSyncNotificationEnabled(boolean enabled) {
+        if (!isVSyncNotificationEnabled() && enabled) {
+            mDidSignalVSyncUsingInputEvent = false;
+        }
+        if (mVSyncProvider != null) {
+            if (!mVSyncListenerRegistered && enabled) {
+                mVSyncProvider.registerVSyncListener(mVSyncListener);
+                mVSyncListenerRegistered = true;
+            } else if (mVSyncSubscriberCount == 1 && !enabled) {
+                assert mVSyncListenerRegistered;
+                mVSyncProvider.unregisterVSyncListener(mVSyncListener);
+                mVSyncListenerRegistered = false;
+            }
+        }
+        mVSyncSubscriberCount += enabled ? 1 : -1;
+        assert mVSyncSubscriberCount >= 0;
+    }
+
+    @CalledByNative
+    private void resetVSyncNotification() {
+        while (isVSyncNotificationEnabled()) setVSyncNotificationEnabled(false);
+        mVSyncSubscriberCount = 0;
+        mVSyncListenerRegistered = false;
+    }
+
+    private boolean isVSyncNotificationEnabled() {
+        return mVSyncProvider != null && mVSyncListenerRegistered;
     }
 
     private final Context mContext;
     private ViewGroup mContainerView;
     private InternalAccessDelegate mContainerViewInternals;
     private WebContentsObserverAndroid mWebContentsObserver;
-    private ContentSizeChangeListener mContentSizeChangeListener;
 
     private ContentViewClient mContentViewClient;
 
@@ -183,6 +274,7 @@
     private boolean mAttachedToWindow = false;
 
     private ContentViewGestureHandler mContentViewGestureHandler;
+    private PinchGestureStateListener mPinchGestureStateListener;
     private ZoomManager mZoomManager;
 
     private PopupZoomer mPopupZoomer;
@@ -192,7 +284,7 @@
     // Only valid when focused on a text / password field.
     private ImeAdapter mImeAdapter;
     private ImeAdapter.AdapterInputConnectionFactory mAdapterInputConnectionFactory;
-    private ImeAdapter.AdapterInputConnection mInputConnection;
+    private AdapterInputConnection mInputConnection;
 
     private SelectionHandleController mSelectionHandleController;
     private InsertionHandleController mInsertionHandleController;
@@ -205,6 +297,8 @@
     private int mPhysicalBackingWidthPix;
     private int mPhysicalBackingHeightPix;
     private int mOverdrawBottomHeightPix;
+    private int mViewportSizeOffsetWidthPix;
+    private int mViewportSizeOffsetHeightPix;
 
     // Cached copy of all positions and scales as reported by the renderer.
     private final RenderCoordinates mRenderCoordinates;
@@ -240,6 +334,11 @@
     // Whether we use hardware-accelerated drawing.
     private boolean mHardwareAccelerated = false;
 
+    // Whether we received a new frame since consumePendingRendererFrame() was last called.
+    private boolean mPendingRendererFrame = false;
+
+    private ViewAndroid mViewAndroid;
+
     /**
      * Constructs a new ContentViewCore. Embedders must call initialize() after constructing
      * a ContentViewCore and before using it.
@@ -278,6 +377,21 @@
     }
 
     /**
+     * Specifies how much smaller the WebKit layout size should be relative to the size of this
+     * view.
+     * @param offsetXPix The X amount in pixels to shrink the viewport by.
+     * @param offsetYPix The Y amount in pixels to shrink the viewport by.
+     */
+    public void setViewportSizeOffset(int offsetXPix, int offsetYPix) {
+        if (offsetXPix != mViewportSizeOffsetWidthPix ||
+                offsetYPix != mViewportSizeOffsetHeightPix) {
+            mViewportSizeOffsetWidthPix = offsetXPix;
+            mViewportSizeOffsetHeightPix = offsetYPix;
+            if (mNativeContentViewCore != 0) nativeWasResized(mNativeContentViewCore);
+        }
+    }
+
+    /**
      * Returns a delegate that can be used to add and remove views from the ContainerView.
      *
      * NOTE: Use with care, as not all ContentViewCore users setup their ContainerView in the same
@@ -286,35 +400,58 @@
      * compatibility breaks with existing applications. If in doubt, contact the
      * android_webview/OWNERS
      *
-     * @return A ContainerViewDelegate that can be used to add and remove views.
+     * @return A ViewAndroidDelegate that can be used to add and remove views.
      */
-    @CalledByNative
-    public ContainerViewDelegate getContainerViewDelegate() {
-        return new ContainerViewDelegate() {
+    @VisibleForTesting
+    public ViewAndroidDelegate getViewAndroidDelegate() {
+        return new ViewAndroidDelegate() {
             @Override
-            public void addViewToContainerView(View view) {
-                mContainerView.addView(view);
+            public View acquireAnchorView() {
+                View anchorView = new View(getContext());
+                mContainerView.addView(anchorView);
+                return anchorView;
             }
 
             @Override
-            public void removeViewFromContainerView(View view) {
-                mContainerView.removeView(view);
+            public void setAnchorViewPosition(
+                    View view, float x, float y, float width, float height) {
+                assert(view.getParent() == mContainerView);
+                float scale = (float) DeviceDisplayInfo.create(getContext()).getDIPScale();
+
+                // The anchor view should not go outside the bounds of the ContainerView.
+                int scaledX = Math.round(x * scale);
+                int scaledWidth = Math.round(width * scale);
+                if (scaledWidth + scaledX > mContainerView.getWidth()) {
+                    scaledWidth = mContainerView.getWidth() - scaledX;
+                }
+
+                FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(
+                        scaledWidth, Math.round(height * scale));
+                lp.leftMargin = scaledX;
+                lp.topMargin = (int) mRenderCoordinates.getContentOffsetYPix() +
+                        Math.round(y * scale);
+                view.setLayoutParams(lp);
+            }
+
+            @Override
+            public void releaseAnchorView(View anchorView) {
+                mContainerView.removeView(anchorView);
             }
         };
     }
 
     @VisibleForTesting
-    protected ImeAdapter getImeAdapterForTest() {
+    public ImeAdapter getImeAdapterForTest() {
         return mImeAdapter;
     }
 
     @VisibleForTesting
-    protected void setAdapterInputConnectionFactory(AdapterInputConnectionFactory factory) {
+    public void setAdapterInputConnectionFactory(AdapterInputConnectionFactory factory) {
         mAdapterInputConnectionFactory = factory;
     }
 
     @VisibleForTesting
-    protected ImeAdapter.AdapterInputConnection getInputConnectionForTest() {
+    public AdapterInputConnection getInputConnectionForTest() {
         return mInputConnection;
     }
 
@@ -423,8 +560,7 @@
      * @param internalDispatcher Handles dispatching all hidden or super methods to the
      *                           containerView.
      * @param nativeWebContents A pointer to the native web contents.
-     * @param nativeWindow An instance of the NativeWindow.
-     * @param isAccessFromFileURLsGrantedByDefault Default WebSettings configuration.
+     * @param windowAndroid An instance of the WindowAndroid.
      */
     // Perform important post-construction set up of the ContentViewCore.
     // We do not require the containing view in the constructor to allow embedders to create a
@@ -436,8 +572,7 @@
     // Note that the caller remains the owner of the nativeWebContents and is responsible for
     // deleting it after destroying the ContentViewCore.
     public void initialize(ViewGroup containerView, InternalAccessDelegate internalDispatcher,
-            int nativeWebContents, NativeWindow nativeWindow,
-            boolean isAccessFromFileURLsGrantedByDefault) {
+            int nativeWebContents, WindowAndroid windowAndroid) {
         // Check whether to use hardware acceleration. This is a bit hacky, and
         // only works if the Context is actually an Activity (as it is in the
         // Chrome application).
@@ -453,20 +588,21 @@
         // HW support directly.
         mHardwareAccelerated = hasHardwareAcceleration(mContext);
 
-        // Input events are delivered at vsync time on JB+.
-        boolean inputEventsDeliveredAtVSync =
-                (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN);
-
         mContainerView = containerView;
-        mNativeContentViewCore = nativeInit(mHardwareAccelerated, inputEventsDeliveredAtVSync,
-                nativeWebContents, nativeWindow.getNativePointer());
-        mContentSettings = new ContentSettings(
-                this, mNativeContentViewCore, isAccessFromFileURLsGrantedByDefault);
-        initializeContainerView(internalDispatcher);
-        if (mPersonality == PERSONALITY_VIEW) {
-            setAllUserAgentOverridesInHistory();
+
+        int windowNativePointer = windowAndroid != null ? windowAndroid.getNativePointer() : 0;
+
+        int viewAndroidNativePointer = 0;
+        if (windowNativePointer != 0) {
+            mViewAndroid = new ViewAndroid(windowAndroid, getViewAndroidDelegate());
+            viewAndroidNativePointer = mViewAndroid.getNativePointer();
         }
 
+        mNativeContentViewCore = nativeInit(mHardwareAccelerated,
+                nativeWebContents, viewAndroidNativePointer, windowNativePointer);
+        mContentSettings = new ContentSettings(this, mNativeContentViewCore);
+        initializeContainerView(internalDispatcher);
+
         mAccessibilityInjector = AccessibilityInjector.newInstance(this);
         mAccessibilityInjector.addOrRemoveAccessibilityApisIfNecessary();
 
@@ -611,6 +747,9 @@
         if (mNativeContentViewCore != 0) {
             nativeOnJavaContentViewCoreDestroyed(mNativeContentViewCore);
         }
+        resetVSyncNotification();
+        mVSyncProvider = null;
+        if (mViewAndroid != null) mViewAndroid.destroy();
         mNativeContentViewCore = 0;
         mContentSettings = null;
         mJavaScriptInterfaces.clear();
@@ -665,10 +804,6 @@
         return mContentViewClient;
     }
 
-    public void setContentSizeChangeListener(ContentSizeChangeListener listener) {
-        mContentSizeChangeListener = listener;
-    }
-
     public int getBackgroundColor() {
         if (mNativeContentViewCore != 0) {
             return nativeGetBackgroundColor(mNativeContentViewCore);
@@ -692,7 +827,7 @@
      * ensuring the URL passed in is properly formatted (i.e. the scheme has been added if left
      * off during user input).
      *
-     * @param pararms Parameters for this load.
+     * @param params Parameters for this load.
      */
     public void loadUrl(LoadUrlParams params) {
         if (mNativeContentViewCore == 0) return;
@@ -714,11 +849,6 @@
                 params.mCanLoadLocalResources);
     }
 
-    void setAllUserAgentOverridesInHistory() {
-        nativeSetAllUserAgentOverridesInHistory(mNativeContentViewCore,
-                mContentSettings.getUserAgentString());
-    }
-
     /**
      * Stops loading the current web contents.
      */
@@ -768,13 +898,14 @@
     }
 
     /**
-     * Indicate that the browser compositor has consumed a pending renderer frame.
+     * Mark any new frames that have arrived since this function was last called as non-pending.
      *
-     * @return Whether there was a pending renderer frame.
+     * @return Whether there was a pending frame from the renderer.
      */
     public boolean consumePendingRendererFrame() {
-        return mNativeContentViewCore == 0 ?
-                false : nativeConsumePendingRendererFrame(mNativeContentViewCore);
+        boolean hadPendingFrame = mPendingRendererFrame;
+        mPendingRendererFrame = false;
+        return hadPendingFrame;
     }
 
     /**
@@ -808,6 +939,18 @@
     public int getOverdrawBottomHeightPix() { return mOverdrawBottomHeightPix; }
 
     /**
+     * @return The amount to shrink the viewport relative to {@link #getViewportWidthPix()}.
+     */
+    @CalledByNative
+    public int getViewportSizeOffsetWidthPix() { return mViewportSizeOffsetWidthPix; }
+
+    /**
+     * @return The amount to shrink the viewport relative to {@link #getViewportHeightPix()}.
+     */
+    @CalledByNative
+    public int getViewportSizeOffsetHeightPix() { return mViewportSizeOffsetHeightPix; }
+
+    /**
      * @see android.webkit.WebView#getContentHeight()
      */
     public float getContentHeightCss() {
@@ -874,16 +1017,6 @@
     }
 
     /**
-     * @return Whether the ContentView is covered by an overlay that is more than half
-     *         of it's surface. This is used to determine if we need to do a slow bitmap capture or
-     *         to show the ContentView without them.
-     */
-    public boolean hasLargeOverlay() {
-        // TODO(nileshagrawal): Implement this.
-        return false;
-    }
-
-    /**
      * @return Whether the current WebContents has a previous navigation entry.
      */
     public boolean canGoBack() {
@@ -1017,9 +1150,16 @@
     }
 
     @Override
-    public boolean sendGesture(int type, long timeMs, int x, int y, Bundle b) {
+    public boolean sendGesture(int type, long timeMs, int x, int y, boolean lastInputEventForVSync,
+                               Bundle b) {
         if (mNativeContentViewCore == 0) return false;
         updateTextHandlesForGesture(type);
+        updatePinchGestureStateListener(type);
+        if (lastInputEventForVSync && isVSyncNotificationEnabled()) {
+            assert type == ContentViewGestureHandler.GESTURE_SCROLL_BY ||
+                    type == ContentViewGestureHandler.GESTURE_PINCH_BY;
+            mDidSignalVSyncUsingInputEvent = true;
+        }
         switch (type) {
             case ContentViewGestureHandler.GESTURE_SHOW_PRESSED_STATE:
                 nativeShowPressState(mNativeContentViewCore, timeMs, x, y);
@@ -1049,7 +1189,8 @@
             case ContentViewGestureHandler.GESTURE_SCROLL_BY: {
                 int dx = b.getInt(ContentViewGestureHandler.DISTANCE_X);
                 int dy = b.getInt(ContentViewGestureHandler.DISTANCE_Y);
-                nativeScrollBy(mNativeContentViewCore, timeMs, x, y, dx, dy);
+                nativeScrollBy(mNativeContentViewCore, timeMs, x, y, dx, dy,
+                        lastInputEventForVSync);
                 return true;
             }
             case ContentViewGestureHandler.GESTURE_SCROLL_END:
@@ -1068,7 +1209,8 @@
                 return true;
             case ContentViewGestureHandler.GESTURE_PINCH_BY:
                 nativePinchBy(mNativeContentViewCore, timeMs, x, y,
-                        b.getFloat(ContentViewGestureHandler.DELTA, 0));
+                        b.getFloat(ContentViewGestureHandler.DELTA, 0),
+                        lastInputEventForVSync);
                 return true;
             case ContentViewGestureHandler.GESTURE_PINCH_END:
                 nativePinchEnd(mNativeContentViewCore, timeMs);
@@ -1078,6 +1220,25 @@
         }
     }
 
+    public void setPinchGestureStateListener(PinchGestureStateListener pinchGestureStateListener) {
+        mPinchGestureStateListener = pinchGestureStateListener;
+    }
+
+    void updatePinchGestureStateListener(int gestureType) {
+        if (mPinchGestureStateListener == null) return;
+
+        switch (gestureType) {
+            case ContentViewGestureHandler.GESTURE_PINCH_BEGIN:
+                mPinchGestureStateListener.onPinchGestureStart();
+                break;
+            case ContentViewGestureHandler.GESTURE_PINCH_END:
+                mPinchGestureStateListener.onPinchGestureEnd();
+                break;
+            default:
+                break;
+        }
+    }
+
     public interface JavaScriptCallback {
         void handleJavaScriptResult(String jsonResult);
     }
@@ -1088,10 +1249,10 @@
      * Used in automation tests.
      *
      * @param script The Javascript to execute.
-     * @param message The callback to be fired off when a result is ready. The script's
-     *                result will be json encoded and passed as the parameter, and the call
-     *                will be made on the main thread.
-     *                If no result is required, pass null.
+     * @param callback The callback to be fired off when a result is ready. The script's
+     *                 result will be json encoded and passed as the parameter, and the call
+     *                 will be made on the main thread.
+     *                 If no result is required, pass null.
      * @throws IllegalStateException If the ContentView has been destroyed.
      */
     public void evaluateJavaScript(
@@ -1206,6 +1367,9 @@
         }
         setAccessibilityState(false);
         hidePopupDialog();
+        if (mContentSettings != null && mContentSettings.supportZoom()) {
+            mZoomManager.dismissZoomPicker();
+        }
     }
 
     /**
@@ -1219,11 +1383,6 @@
       }
     }
 
-    @CalledByNative
-    private void onWebPreferencesUpdated() {
-        mContentSettings.syncSettings();
-    }
-
     /**
      * @see View#onCreateInputConnection(EditorInfo)
      */
@@ -1259,7 +1418,9 @@
 
         if (newConfig.keyboard != Configuration.KEYBOARD_NOKEYS) {
             mImeAdapter.attach(nativeGetNativeImeAdapter(mNativeContentViewCore),
-                    ImeAdapter.sTextInputTypeNone);
+                    ImeAdapter.getTextInputTypeNone(),
+                    AdapterInputConnection.INVALID_SELECTION,
+                    AdapterInputConnection.INVALID_SELECTION);
             InputMethodManager manager = (InputMethodManager)
                     getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
             manager.restartInput(mContainerView);
@@ -1486,7 +1647,7 @@
     public void scrollBy(int xPix, int yPix) {
         if (mNativeContentViewCore != 0) {
             nativeScrollBy(mNativeContentViewCore,
-                    System.currentTimeMillis(), 0, 0, xPix, yPix);
+                    System.currentTimeMillis(), 0, 0, xPix, yPix, false);
         }
     }
 
@@ -1502,7 +1663,8 @@
         if (dxPix != 0 || dyPix != 0) {
             long time = System.currentTimeMillis();
             nativeScrollBegin(mNativeContentViewCore, time, xCurrentPix, yCurrentPix);
-            nativeScrollBy(mNativeContentViewCore, time, xCurrentPix, yCurrentPix, dxPix, dyPix);
+            nativeScrollBy(mNativeContentViewCore,
+                    time, xCurrentPix, yCurrentPix, dxPix, dyPix, false);
             nativeScrollEnd(mNativeContentViewCore, time);
         }
     }
@@ -1627,7 +1789,7 @@
         return mZoomManager.isMultiTouchZoomSupported();
     }
 
-    void selectPopupMenuItems(int[] indices) {
+    public void selectPopupMenuItems(int[] indices) {
         if (mNativeContentViewCore != 0) {
             nativeSelectPopupMenuItems(mNativeContentViewCore, indices);
         }
@@ -1689,7 +1851,9 @@
                 @Override
                 public void selectBetweenCoordinates(int x1, int y1, int x2, int y2) {
                     if (mNativeContentViewCore != 0 && !(x1 == x2 && y1 == y2)) {
-                        nativeSelectBetweenCoordinates(mNativeContentViewCore, x1, y1, x2, y2);
+                        nativeSelectBetweenCoordinates(mNativeContentViewCore,
+                                x1, y1 - mRenderCoordinates.getContentOffsetYPix(),
+                                x2, y2 - mRenderCoordinates.getContentOffsetYPix());
                     }
                 }
 
@@ -1715,7 +1879,8 @@
                 @Override
                 public void setCursorPosition(int x, int y) {
                     if (mNativeContentViewCore != 0) {
-                        nativeMoveCaret(mNativeContentViewCore, x, y);
+                        nativeMoveCaret(mNativeContentViewCore,
+                                x, y - mRenderCoordinates.getContentOffsetYPix());
                     }
                 }
 
@@ -1816,9 +1981,13 @@
                 getContentViewClient().onContextualActionBarHidden();
             }
         };
-        mActionMode = mContainerView.startActionMode(
-                getContentViewClient().getSelectActionModeCallback(getContext(), actionHandler,
-                        nativeIsIncognito(mNativeContentViewCore)));
+        mActionMode = null;
+        // On ICS, startActionMode throws an NPE when getParent() is null.
+        if (mContainerView.getParent() != null) {
+            mActionMode = mContainerView.startActionMode(
+                    getContentViewClient().getSelectActionModeCallback(getContext(), actionHandler,
+                            nativeIsIncognito(mNativeContentViewCore)));
+        }
         mUnselectAllOnActionModeDismiss = true;
         if (mActionMode == null) {
             // There is no ActionMode, so remove the selection.
@@ -1934,8 +2103,9 @@
             float pageScaleFactor, float minPageScaleFactor, float maxPageScaleFactor,
             float contentWidth, float contentHeight,
             float viewportWidth, float viewportHeight,
-            float controlsOffsetYCss, float contentOffsetYCss) {
-
+            float controlsOffsetYCss, float contentOffsetYCss,
+            float overdrawBottomHeightCss) {
+        TraceEvent.instant("ContentViewCore:updateFrameInfo");
         // Adjust contentWidth/Height to be always at least as big as
         // the actual viewport (as set by onSizeChanged).
         contentWidth = Math.max(contentWidth,
@@ -1943,6 +2113,8 @@
         contentHeight = Math.max(contentHeight,
                 mRenderCoordinates.fromPixToLocalCss(mViewportHeightPix));
 
+        final float contentOffsetYPix = mRenderCoordinates.fromDipToPix(contentOffsetYCss);
+
         final boolean contentSizeChanged =
                 contentWidth != mRenderCoordinates.getContentWidthCss()
                 || contentHeight != mRenderCoordinates.getContentHeightCss();
@@ -1955,6 +2127,9 @@
                 pageScaleChanged
                 || scrollOffsetX != mRenderCoordinates.getScrollX()
                 || scrollOffsetY != mRenderCoordinates.getScrollY();
+        final boolean contentOffsetChanged =
+                contentOffsetYPix != mRenderCoordinates.getContentOffsetYPix();
+
         final boolean needHidePopupZoomer = contentSizeChanged || scrollChanged;
         final boolean needUpdateZoomControls = scaleLimitsChanged || scrollChanged;
         final boolean needTemporarilyHideHandles = scrollChanged;
@@ -1981,27 +2156,21 @@
                 scrollOffsetX, scrollOffsetY,
                 contentWidth, contentHeight,
                 viewportWidth, viewportHeight,
-                pageScaleFactor, minPageScaleFactor, maxPageScaleFactor);
-
-        if (contentSizeChanged) {
-            getContentViewClient().onContentSizeChanged(
-                    mRenderCoordinates.getContentWidthCss(),
-                    mRenderCoordinates.getContentHeightCss());
-            if (mContentSizeChangeListener != null) {
-                mContentSizeChangeListener.onContentSizeChanged(
-                        mRenderCoordinates.getContentWidthPixInt(),
-                        mRenderCoordinates.getContentHeightPixInt());
-            }
-        }
+                pageScaleFactor, minPageScaleFactor, maxPageScaleFactor,
+                contentOffsetYPix);
 
         if (needTemporarilyHideHandles) temporarilyHideTextHandles();
         if (needUpdateZoomControls) mZoomManager.updateZoomControls();
+        if (contentOffsetChanged) updateHandleScreenPositions();
 
         // Update offsets for fullscreen.
         final float deviceScale = mRenderCoordinates.getDeviceScaleFactor();
         final float controlsOffsetPix = controlsOffsetYCss * deviceScale;
-        final float contentOffsetYPix = contentOffsetYCss * deviceScale;
-        getContentViewClient().onOffsetsForFullscreenChanged(controlsOffsetPix, contentOffsetYPix);
+        final float overdrawBottomHeightPix = overdrawBottomHeightCss * deviceScale;
+        getContentViewClient().onOffsetsForFullscreenChanged(
+                controlsOffsetPix, contentOffsetYPix, overdrawBottomHeightPix);
+
+        mPendingRendererFrame = true;
     }
 
     @SuppressWarnings("unused")
@@ -2010,24 +2179,14 @@
             String text, int selectionStart, int selectionEnd,
             int compositionStart, int compositionEnd, boolean showImeIfNeeded) {
         TraceEvent.begin();
-
-        // Non-breaking spaces can cause the IME to get confused. Replace with normal spaces.
-        text = text.replace('\u00A0', ' ');
-
-        mSelectionEditable = (textInputType != ImeAdapter.sTextInputTypeNone);
+        mSelectionEditable = (textInputType != ImeAdapter.getTextInputTypeNone());
 
         if (mActionMode != null) mActionMode.invalidate();
 
         mImeAdapter.attachAndShowIfNeeded(nativeImeAdapterAndroid, textInputType,
-                text, showImeIfNeeded);
+                selectionStart, selectionEnd, showImeIfNeeded);
 
         if (mInputConnection != null) {
-            // In WebKit if there's a composition then the selection will usually be the
-            // same as the composition, whereas Android IMEs expect the selection to be
-            // just a caret at the end of the composition.
-            if (selectionStart == compositionStart && selectionEnd == compositionEnd) {
-                selectionStart = selectionEnd;
-            }
             mInputConnection.setEditableText(text, selectionStart, selectionEnd,
                     compositionStart, compositionEnd);
         }
@@ -2170,6 +2329,14 @@
         }
     }
 
+    @SuppressWarnings("unused")
+    @CalledByNative
+    private void onWebContentsSwapped() {
+        if (mImeAdapter != null && mNativeContentViewCore != 0) {
+            mImeAdapter.attach(nativeGetNativeImeAdapter(mNativeContentViewCore));
+        }
+    }
+
     /**
      * @return Whether a reload happens when this ContentView is activated.
      */
@@ -2382,14 +2549,6 @@
         return nativeIsRenderWidgetHostViewReady(mNativeContentViewCore);
     }
 
-    /**
-     * @return Whether or not the texture view is available or not.
-     */
-    public boolean isAvailable() {
-        // TODO(nileshagrawal): Implement this.
-        return false;
-    }
-
     @CalledByNative
     private void startContentIntent(String contentUrl) {
         getContentViewClient().onStartContentIntent(getContext(), contentUrl);
@@ -2484,10 +2643,13 @@
     /**
      * Changes whether hiding the top controls is enabled.
      *
-     * @param enable Whether hiding the top controls should be enabled.
+     * @param enableHiding Whether hiding the top controls should be enabled or not.
+     * @param enableShowing Whether showing the top controls should be enabled or not.
+     * @param animate Whether the transition should be animated or not.
      */
-    public void enableHidingTopControls(boolean enable) {
-        nativeEnableHidingTopControls(mNativeContentViewCore, enable);
+    public void updateTopControlsState(boolean enableHiding, boolean enableShowing,
+            boolean animate) {
+        nativeUpdateTopControlsState(mNativeContentViewCore, enableHiding, enableShowing, animate);
     }
 
     /**
@@ -2556,14 +2718,11 @@
     }
 
     /**
-     * Update of the latest vsync parameters.
-     * @param tickTimeMicros The latest vsync tick time in microseconds.
-     * @param intervalMicros The vsync interval in microseconds.
+     * @return The original request URL for the current navigation entry, or null if there is no
+     *         current entry.
      */
-    public void updateVSync(long tickTimeMicros, long intervalMicros) {
-        if (mNativeContentViewCore != 0) {
-            nativeUpdateVSyncParameters(mNativeContentViewCore, tickTimeMicros, intervalMicros);
-        }
+    public String getOriginalUrlForActiveNavigationEntry() {
+        return nativeGetOriginalUrlForActiveNavigationEntry(mNativeContentViewCore);
     }
 
     /**
@@ -2595,8 +2754,23 @@
         getContentViewClient().onExternalVideoSurfaceRequested(playerId);
     }
 
-    private native int nativeInit(boolean hardwareAccelerated, boolean inputEventsDeliveredAtVSync,
-            int webContentsPtr, int windowAndroidPtr);
+    @CalledByNative
+    private void notifyGeometryChange(int playerId, float x, float y, float width, float height) {
+        RenderCoordinates.NormalizedPoint topLeft = mRenderCoordinates.createNormalizedPoint();
+        RenderCoordinates.NormalizedPoint bottomRight = mRenderCoordinates.createNormalizedPoint();
+        topLeft.setLocalDip(x * getScale(), y * getScale());
+        bottomRight.setLocalDip((x + width) * getScale(), (y + height) * getScale());
+
+        getContentViewClient().onGeometryChanged(
+                playerId,
+                topLeft.getXPix(),
+                topLeft.getYPix(),
+                bottomRight.getXPix() - topLeft.getXPix(),
+                bottomRight.getYPix() - topLeft.getYPix());
+    }
+
+    private native int nativeInit(boolean hardwareAccelerated, int webContentsPtr,
+            int viewAndroidPtr, int windowAndroidPtr);
 
     private native void nativeOnJavaContentViewCoreDestroyed(int nativeContentViewCoreImpl);
 
@@ -2612,9 +2786,6 @@
             String virtualUrlForDataUrl,
             boolean canLoadLocalResources);
 
-    private native void nativeSetAllUserAgentOverridesInHistory(int nativeContentViewCoreImpl,
-            String userAgentOverride);
-
     private native String nativeGetURL(int nativeContentViewCoreImpl);
 
     private native String nativeGetTitle(int nativeContentViewCoreImpl);
@@ -2623,8 +2794,6 @@
             int nativeContentViewCoreImpl, String url, int nativeInterstitialPageDelegateAndroid);
     private native boolean nativeIsShowingInterstitialPage(int nativeContentViewCoreImpl);
 
-    private native boolean nativeConsumePendingRendererFrame(int nativeContentViewCoreImpl);
-
     private native boolean nativeIsIncognito(int nativeContentViewCoreImpl);
 
     // Returns true if the native side crashed so that java side can draw a sad tab.
@@ -2651,8 +2820,8 @@
     private native void nativeScrollEnd(int nativeContentViewCoreImpl, long timeMs);
 
     private native void nativeScrollBy(
-            int nativeContentViewCoreImpl, long timeMs,
-            float x, float y, float deltaX, float deltaY);
+            int nativeContentViewCoreImpl, long timeMs, float x, float y,
+            float deltaX, float deltaY, boolean lastInputEventForVSync);
 
     private native void nativeFlingStart(
             int nativeContentViewCoreImpl, long timeMs, float x, float y, float vx, float vy);
@@ -2683,7 +2852,7 @@
     private native void nativePinchEnd(int nativeContentViewCoreImpl, long timeMs);
 
     private native void nativePinchBy(int nativeContentViewCoreImpl, long timeMs,
-            float anchorX, float anchorY, float deltaScale);
+            float anchorX, float anchorY, float deltaScale, boolean lastInputEventForVSync);
 
     private native void nativeSelectBetweenCoordinates(
             int nativeContentViewCoreImpl, float x1, float y1, float x2, float y2);
@@ -2742,10 +2911,14 @@
     private native int nativeGetNavigationHistory(int nativeContentViewCoreImpl, Object context);
     private native void nativeGetDirectedNavigationHistory(int nativeContentViewCoreImpl,
             Object context, boolean isForward, int maxEntries);
+    private native String nativeGetOriginalUrlForActiveNavigationEntry(
+            int nativeContentViewCoreImpl);
 
     private native void nativeUpdateVSyncParameters(int nativeContentViewCoreImpl,
             long timebaseMicros, long intervalMicros);
 
+    private native void nativeOnVSync(int nativeContentViewCoreImpl, long frameTimeMicros);
+
     private native boolean nativePopulateBitmapFromCompositor(int nativeContentViewCoreImpl,
             Bitmap bitmap);
 
@@ -2754,8 +2927,8 @@
     private native boolean nativeIsRenderWidgetHostViewReady(int nativeContentViewCoreImpl);
 
     private native void nativeExitFullscreen(int nativeContentViewCoreImpl);
-    private native void nativeEnableHidingTopControls(
-            int nativeContentViewCoreImpl, boolean enable);
+    private native void nativeUpdateTopControlsState(int nativeContentViewCoreImpl,
+            boolean enableHiding, boolean enableShowing, boolean animate);
 
     private native void nativeShowImeIfNeeded(int nativeContentViewCoreImpl);
 
diff --git a/content/public/android/java/src/org/chromium/content/browser/ContentViewDownloadDelegate.java b/content/public/android/java/src/org/chromium/content/browser/ContentViewDownloadDelegate.java
index 9c056dd..46c3e97 100644
--- a/content/public/android/java/src/org/chromium/content/browser/ContentViewDownloadDelegate.java
+++ b/content/public/android/java/src/org/chromium/content/browser/ContentViewDownloadDelegate.java
@@ -24,18 +24,26 @@
             String mimetype, String cookie, String referer, long contentLength);
 
     /**
-     * Notify the host application that a POST download is started.
+     * Notify the host application that a download is started.
      */
-    void onHttpPostDownloadStarted();
+    void onDownloadStarted();
 
     /**
-     * Notify the host application that a POST download is finished.
+     * Notify the host application that a download is finished.
      * @param url The full url to the content that was downloaded.
      * @param mimetype The mimetype of downloaded file.
      * @param path Path of the downloaded file.
      * @param contentLength The file size of the downloaded file (in bytes).
      * @param successful Whether the download succeeded
      */
-    void onHttpPostDownloadCompleted(String url, String mimetype, String path,
+    void onDownloadCompleted(String url, String mimetype, String path,
             long contentLength, boolean successful);
+
+    /**
+     * Notify the host application that a download has an extension indicating
+     * a dangerous file type.
+     * @param filename File name of the downloaded file.
+     * @param downloadId The download id.
+     */
+    void onDangerousDownload(String filename, int downloadId);
 }
diff --git a/content/public/android/java/src/org/chromium/content/browser/ContentViewGestureHandler.java b/content/public/android/java/src/org/chromium/content/browser/ContentViewGestureHandler.java
index 2a73c01..7ce32da 100644
--- a/content/public/android/java/src/org/chromium/content/browser/ContentViewGestureHandler.java
+++ b/content/public/android/java/src/org/chromium/content/browser/ContentViewGestureHandler.java
@@ -5,6 +5,7 @@
 package org.chromium.content.browser;
 
 import android.content.Context;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.SystemClock;
 import android.util.Log;
@@ -60,12 +61,8 @@
     private MotionEvent mCurrentDownEvent;
     private final MotionEventDelegate mMotionEventDelegate;
 
-    // Queue of motion events. If the boolean value is true, it means
-    // that the event has been offered to the native side but not yet acknowledged. If the
-    // value is false, it means the touch event has not been offered
-    // to the native side and can be immediately processed.
-    private final Deque<MotionEvent> mPendingMotionEvents =
-            new ArrayDeque<MotionEvent>();
+    // Queue of motion events.
+    private final Deque<MotionEvent> mPendingMotionEvents = new ArrayDeque<MotionEvent>();
 
     // Has WebKit told us the current page requires touch events.
     private boolean mHasTouchHandlers = false;
@@ -90,9 +87,8 @@
     private boolean mIgnoreSingleTap;
 
     // Does native think we are scrolling?  True from right before we
-    // send the first scroll event until the last finger is raised, or
-    // until after the follow-up fling has finished.  Call
-    // nativeScrollBegin() when setting this to true, and use
+    // send the first scroll event until the last finger is raised.
+    // Call nativeScrollBegin() when setting this to true, and use
     // tellNativeScrollingHasEnded() to set it to false.
     private boolean mNativeScrolling;
 
@@ -104,6 +100,9 @@
     // into scrolling or pinching mode.
     private boolean mTouchCancelEventSent = false;
 
+    // Last cancelled touch event as a result of scrolling or pinching.
+    private MotionEvent mLastCancelledEvent = null;
+
     private static final int DOUBLE_TAP_TIMEOUT = ViewConfiguration.getDoubleTapTimeout();
 
     //On single tap this will store the x, y coordinates of the touch.
@@ -118,7 +117,7 @@
     // Cache of square of the scaled touch slop so we don't have to calculate it on every touch.
     private int mScaledTouchSlopSquare;
 
-    // Object that keeps trqack of and updates scroll snapping behavior.
+    // Object that keeps track of and updates scroll snapping behavior.
     private SnapScrollController mSnapScrollController;
 
     // Used to track the accumulated scroll error over time. This is used to remove the
@@ -126,6 +125,9 @@
     private float mAccumulatedScrollErrorX = 0;
     private float mAccumulatedScrollErrorY = 0;
 
+    // Whether input events are delivered right before vsync.
+    private boolean mInputEventsDeliveredAtVSync = false;
+
     static final int GESTURE_SHOW_PRESSED_STATE = 0;
     static final int GESTURE_DOUBLE_TAP = 1;
     static final int GESTURE_SINGLE_TAP_UP = 2;
@@ -148,6 +150,11 @@
     static final int INPUT_EVENT_ACK_STATE_NOT_CONSUMED = 2;
     static final int INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS = 3;
 
+    // Return values of sendTouchEventToNative();
+    static final int EVENT_FORWARDED_TO_NATIVE = 0;
+    static final int EVENT_CONVERTED_TO_CANCEL = 1;
+    static final int EVENT_NOT_FORWARDED = 2;
+
     /**
      * This is an interface to handle MotionEvent related communication with the native side also
      * access some ContentView specific parameters.
@@ -168,12 +175,15 @@
          * @param timeMs The time the gesture event occurred at.
          * @param x The x location for the gesture event.
          * @param y The y location for the gesture event.
+         * @param lastInputEventForVSync Indicates that this gesture event is the last input
+         * to be event sent during the current vsync interval.
          * @param extraParams A bundle that holds specific extra parameters for certain gestures.
          * Refer to gesture type definition for more information.
          * @return Whether the gesture was sent successfully.
          */
         boolean sendGesture(
-                int type, long timeMs, int x, int y, Bundle extraParams);
+                int type, long timeMs, int x, int y, boolean lastInputEventForVSync,
+                Bundle extraParams);
 
         /**
          * Gives the UI the chance to override each scroll event.
@@ -200,7 +210,11 @@
         mLongPressDetector = new LongPressDetector(context, this);
         mMotionEventDelegate = delegate;
         mZoomManager = zoomManager;
-        mSnapScrollController = new SnapScrollController(mZoomManager);
+        mSnapScrollController = new SnapScrollController(context, mZoomManager);
+
+        // Input events are delivered at vsync time on JB+.
+        mInputEventsDeliveredAtVSync = (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN);
+
         initGestureDetectors(context);
     }
 
@@ -220,7 +234,7 @@
     }
 
     private void initGestureDetectors(final Context context) {
-        int scaledTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
+        final int scaledTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
         mScaledTouchSlopSquare = scaledTouchSlop * scaledTouchSlop;
         try {
             TraceEvent.begin();
@@ -244,6 +258,19 @@
                     @Override
                     public boolean onScroll(MotionEvent e1, MotionEvent e2,
                             float distanceX, float distanceY) {
+                        if (!mSeenFirstScrollEvent) {
+                            // Remove the touch slop region from the first scroll event to avoid a
+                            // jump.
+                            mSeenFirstScrollEvent = true;
+                            double distance = Math.sqrt(
+                                    distanceX * distanceX + distanceY * distanceY);
+                            double epsilon = 1e-3;
+                            if (distance > epsilon) {
+                                double ratio = Math.max(0, distance - scaledTouchSlop) / distance;
+                                distanceX *= ratio;
+                                distanceY *= ratio;
+                            }
+                        }
                         mSnapScrollController.updateSnapScrollMode(distanceX, distanceY);
                         if (mSnapScrollController.isSnappingScrolls()) {
                             if (mSnapScrollController.isSnapHorizontal()) {
@@ -253,12 +280,6 @@
                             }
                         }
 
-                        if (!mSeenFirstScrollEvent) {
-                            // Ignore the first scroll delta to avoid a visible jump.
-                            mSeenFirstScrollEvent = true;
-                            return true;
-                        }
-
                         boolean didUIStealScroll = mMotionEventDelegate.didUIStealScroll(
                                 e2.getRawX() - mLastRawX, e2.getRawY() - mLastRawY);
 
@@ -267,9 +288,7 @@
                         if (didUIStealScroll) return true;
                         if (!mNativeScrolling) {
                             sendShowPressCancelIfNecessary(e1);
-                            if (mMotionEventDelegate.sendGesture(
-                                    GESTURE_SCROLL_START, e1.getEventTime(),
-                                            (int) e1.getX(), (int) e1.getY(), null)) {
+                            if (sendMotionEventAsGesture(GESTURE_SCROLL_START, e1, null)) {
                                 mNativeScrolling = true;
                             }
                         }
@@ -288,7 +307,7 @@
                         mExtraParamBundle.putInt(DISTANCE_X, dx);
                         mExtraParamBundle.putInt(DISTANCE_Y, dy);
                         if ((dx | dy) != 0) {
-                            mMotionEventDelegate.sendGesture(GESTURE_SCROLL_BY,
+                            sendLastGestureForVSync(GESTURE_SCROLL_BY,
                                     e2.getEventTime(), x, y, mExtraParamBundle);
                         }
 
@@ -316,8 +335,7 @@
                     @Override
                     public void onShowPress(MotionEvent e) {
                         mShowPressIsCalled = true;
-                        mMotionEventDelegate.sendGesture(GESTURE_SHOW_PRESSED_STATE,
-                                e.getEventTime(), (int) e.getX(), (int) e.getY(), null);
+                        sendMotionEventAsGesture(GESTURE_SHOW_PRESSED_STATE, e, null);
                     }
 
                     @Override
@@ -336,8 +354,7 @@
                             if (e.getEventTime() - e.getDownTime() > DOUBLE_TAP_TIMEOUT) {
                                 float x = e.getX();
                                 float y = e.getY();
-                                if (mMotionEventDelegate.sendGesture(GESTURE_SINGLE_TAP_UP,
-                                        e.getEventTime(), (int) x, (int) y, null)) {
+                                if (sendMotionEventAsGesture(GESTURE_SINGLE_TAP_UP, e, null)) {
                                     mIgnoreSingleTap = true;
                                 }
                                 setClickXAndY((int) x, (int) y);
@@ -349,8 +366,8 @@
                                 float y = e.getY();
                                 mExtraParamBundle.clear();
                                 mExtraParamBundle.putBoolean(SHOW_PRESS, mShowPressIsCalled);
-                                if (mMotionEventDelegate.sendGesture(GESTURE_SINGLE_TAP_CONFIRMED,
-                                        e.getEventTime(), (int) x, (int) y, mExtraParamBundle)) {
+                                if (sendMotionEventAsGesture(GESTURE_SINGLE_TAP_CONFIRMED, e,
+                                        mExtraParamBundle)) {
                                     mIgnoreSingleTap = true;
                                 }
                                 setClickXAndY((int) x, (int) y);
@@ -372,8 +389,8 @@
                         int y = (int) e.getY();
                         mExtraParamBundle.clear();
                         mExtraParamBundle.putBoolean(SHOW_PRESS, mShowPressIsCalled);
-                        mMotionEventDelegate.sendGesture(GESTURE_SINGLE_TAP_CONFIRMED,
-                                e.getEventTime(), x, y, mExtraParamBundle);
+                        sendMotionEventAsGesture(GESTURE_SINGLE_TAP_CONFIRMED, e,
+                            mExtraParamBundle);
                         setClickXAndY(x, y);
                         return true;
                     }
@@ -381,8 +398,7 @@
                     @Override
                     public boolean onDoubleTap(MotionEvent e) {
                         sendShowPressCancelIfNecessary(e);
-                        mMotionEventDelegate.sendGesture(GESTURE_DOUBLE_TAP,
-                                e.getEventTime(), (int) e.getX(), (int) e.getY(), null);
+                        sendMotionEventAsGesture(GESTURE_DOUBLE_TAP, e, null);
                         return true;
                     }
 
@@ -390,8 +406,7 @@
                     public void onLongPress(MotionEvent e) {
                         if (!mZoomManager.isScaleGestureDetectionInProgress()) {
                             sendShowPressCancelIfNecessary(e);
-                            mMotionEventDelegate.sendGesture(GESTURE_LONG_PRESS,
-                                    e.getEventTime(), (int) e.getX(), (int) e.getY(), null);
+                            sendMotionEventAsGesture(GESTURE_LONG_PRESS, e, null);
                         }
                     }
 
@@ -452,12 +467,17 @@
      * @param velocityY Initial velocity of the fling (Y) measured in pixels per second.
      */
     void fling(long timeMs, int x, int y, int velocityX, int velocityY) {
+        if (!mNativeScrolling) {
+            // The native side needs a GESTURE_SCROLL_BEGIN before GESTURE_FLING_START
+            // to send the fling to the correct target. Send if it has not sent.
+            sendGesture(GESTURE_SCROLL_START, timeMs, x, y, null);
+        }
+
         endFling(timeMs);
         mExtraParamBundle.clear();
         mExtraParamBundle.putInt(VELOCITY_X, velocityX);
         mExtraParamBundle.putInt(VELOCITY_Y, velocityY);
-        mMotionEventDelegate.sendGesture(GESTURE_FLING_START,
-                timeMs, x, y, mExtraParamBundle);
+        sendGesture(GESTURE_FLING_START, timeMs, x, y, mExtraParamBundle);
     }
 
     /**
@@ -465,16 +485,18 @@
      * @param timeMs The time in ms for the event initiating this gesture.
      */
     void endFling(long timeMs) {
-        mMotionEventDelegate.sendGesture(GESTURE_FLING_CANCEL, timeMs, 0, 0, null);
-        tellNativeScrollingHasEnded(timeMs);
+        sendGesture(GESTURE_FLING_CANCEL, timeMs, 0, 0, null);
+        tellNativeScrollingHasEnded(timeMs, false);
     }
 
     // If native thinks scrolling (or fling-scrolling) is going on, tell native
     // it has ended.
-    private void tellNativeScrollingHasEnded(long timeMs) {
+    private void tellNativeScrollingHasEnded(long timeMs, boolean sendScrollEndEvent) {
         if (mNativeScrolling) {
             mNativeScrolling = false;
-            mMotionEventDelegate.sendGesture(GESTURE_SCROLL_END, timeMs, 0, 0, null);
+            if (sendScrollEndEvent) {
+                sendGesture(GESTURE_SCROLL_END, timeMs, 0, 0, null);
+            }
         }
     }
 
@@ -501,7 +523,7 @@
      * @param y The x coordinate for the event initiating this gesture.
      */
     void pinchBegin(long timeMs, int x, int y) {
-        mMotionEventDelegate.sendGesture(GESTURE_PINCH_BEGIN, timeMs, x, y, null);
+        sendGesture(GESTURE_PINCH_BEGIN, timeMs, x, y, null);
     }
 
     /**
@@ -514,8 +536,7 @@
     void pinchBy(long timeMs, int anchorX, int anchorY, float delta) {
         mExtraParamBundle.clear();
         mExtraParamBundle.putFloat(DELTA, delta);
-        mMotionEventDelegate.sendGesture(GESTURE_PINCH_BY,
-                timeMs, anchorX, anchorY, mExtraParamBundle);
+        sendLastGestureForVSync(GESTURE_PINCH_BY, timeMs, anchorX, anchorY, mExtraParamBundle);
         mPinchInProgress = true;
     }
 
@@ -524,7 +545,7 @@
      * @param timeMs The time in ms for the event initiating this gesture.
      */
     void pinchEnd(long timeMs) {
-        mMotionEventDelegate.sendGesture(GESTURE_PINCH_END, timeMs, 0, 0, null);
+        sendGesture(GESTURE_PINCH_END, timeMs, 0, 0, null);
         mPinchInProgress = false;
     }
 
@@ -649,7 +670,7 @@
                     && previousEvent.getActionMasked() == MotionEvent.ACTION_MOVE
                     && previousEvent.getPointerCount() == event.getPointerCount()) {
                 MotionEvent.PointerCoords[] coords =
-                    new MotionEvent.PointerCoords[event.getPointerCount()];
+                        new MotionEvent.PointerCoords[event.getPointerCount()];
                 for (int i = 0; i < coords.length; ++i) {
                     coords[i] = new MotionEvent.PointerCoords();
                     event.getPointerCoords(i, coords[i]);
@@ -658,27 +679,42 @@
                 return true;
             }
         }
-        if (!mPendingMotionEvents.isEmpty() || sendTouchEventToNative(event)) {
+        int forward = EVENT_NOT_FORWARDED;
+        if (mPendingMotionEvents.isEmpty()) {
+            forward = sendTouchEventToNative(event);
+        }
+        if (!mPendingMotionEvents.isEmpty() || forward != EVENT_NOT_FORWARDED) {
             // Copy the event, as the original may get mutated after this method returns.
-            mPendingMotionEvents.add(MotionEvent.obtain(event));
+            MotionEvent clone = MotionEvent.obtain(event);
+            mPendingMotionEvents.add(clone);
+            // If touch cancel was sent, remember the event.
+            if (forward == EVENT_CONVERTED_TO_CANCEL) {
+                mLastCancelledEvent = clone;
+            }
             return true;
         }
         return false;
     }
 
-    private boolean sendTouchEventToNative(MotionEvent event) {
+    private int sendTouchEventToNative(MotionEvent event) {
         TouchPoint[] pts = new TouchPoint[event.getPointerCount()];
         int type = TouchPoint.createTouchPoints(event, pts);
-        boolean forwarded = false;
-        if (type != TouchPoint.CONVERSION_ERROR && !mNativeScrolling && !mPinchInProgress) {
-            forwarded = mMotionEventDelegate.sendTouchEvent(event.getEventTime(), type, pts);
-            mTouchCancelEventSent = false;
-        } else if (!mTouchCancelEventSent) {
-            mMotionEventDelegate.sendTouchEvent(event.getEventTime(),
-                    TouchPoint.TOUCH_EVENT_TYPE_CANCEL, pts);
-            mTouchCancelEventSent = true;
+
+        if (type != TouchPoint.CONVERSION_ERROR) {
+            if (!mNativeScrolling && !mPinchInProgress) {
+                mTouchCancelEventSent = false;
+                if (mMotionEventDelegate.sendTouchEvent(event.getEventTime(), type, pts)) {
+                    return EVENT_FORWARDED_TO_NATIVE;
+                }
+            } else if (!mTouchCancelEventSent) {
+                mTouchCancelEventSent = true;
+                if (mMotionEventDelegate.sendTouchEvent(event.getEventTime(),
+                        TouchPoint.TOUCH_EVENT_TYPE_CANCEL, pts)) {
+                    return EVENT_CONVERTED_TO_CANCEL;
+                }
+            }
         }
-        return forwarded;
+        return EVENT_NOT_FORWARDED;
     }
 
     private boolean processTouchEvent(MotionEvent event) {
@@ -712,7 +748,7 @@
         handled |= mZoomManager.processTouchEvent(event);
 
         if (possiblyEndMovement && !handled) {
-            tellNativeScrollingHasEnded(event.getEventTime());
+            tellNativeScrollingHasEnded(event.getEventTime(), true);
         }
 
         return handled;
@@ -729,7 +765,11 @@
         }
         TraceEvent.begin();
         MotionEvent ackedEvent = mPendingMotionEvents.removeFirst();
-        MotionEvent nextEvent = mPendingMotionEvents.peekFirst();
+        if (ackedEvent.equals(mLastCancelledEvent)) {
+            // The event is canceled, just drain all the pending events until next
+            // touch down.
+            ackResult = INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS;
+        }
         switch (ackResult) {
             case INPUT_EVENT_ACK_STATE_UNKNOWN:
                 // This should never get sent.
@@ -738,11 +778,15 @@
             case INPUT_EVENT_ACK_STATE_CONSUMED:
                 mJavaScriptIsConsumingGesture = true;
                 mZoomManager.passTouchEventThrough(ackedEvent);
-                trySendNextEventToNative(nextEvent);
+                if (!mPendingMotionEvents.isEmpty()) {
+                    trySendNextEventToNative(mPendingMotionEvents.peekFirst());
+                }
                 break;
             case INPUT_EVENT_ACK_STATE_NOT_CONSUMED:
                 if (!mJavaScriptIsConsumingGesture) processTouchEvent(ackedEvent);
-                trySendNextEventToNative(nextEvent);
+                if (!mPendingMotionEvents.isEmpty()) {
+                    trySendNextEventToNative(mPendingMotionEvents.peekFirst());
+                }
                 break;
             case INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS:
                 mNoTouchHandlerForGesture = true;
@@ -760,16 +804,20 @@
     }
 
     private void trySendNextEventToNative(MotionEvent nextEvent) {
-        if (nextEvent == null) return;
+        assert(nextEvent != null);
 
-        if (!sendTouchEventToNative(nextEvent)) {
+        int forward = sendTouchEventToNative(nextEvent);
+        if (forward == EVENT_NOT_FORWARDED) {
             if (!mJavaScriptIsConsumingGesture) processTouchEvent(nextEvent);
             mPendingMotionEvents.removeFirst();
-            nextEvent = mPendingMotionEvents.peekFirst();
-            // Event though we missed sending one event to native, as long as we haven't
+            // Even though we missed sending one event to native, as long as we haven't
             // received INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS, we should keep sending
             // events on the queue to native.
-            trySendNextEventToNative(nextEvent);
+            if (!mPendingMotionEvents.isEmpty()) {
+                trySendNextEventToNative(mPendingMotionEvents.peekFirst());
+            }
+        } else if (forward == EVENT_CONVERTED_TO_CANCEL) {
+            mLastCancelledEvent = mPendingMotionEvents.peekFirst();
         }
     }
 
@@ -786,15 +834,30 @@
         if (nextEvent == null) return;
 
         mNoTouchHandlerForGesture = false;
-        MotionEvent newDownEvent = mPendingMotionEvents.peekFirst();
-        trySendNextEventToNative(newDownEvent);
+        trySendNextEventToNative(nextEvent);
+    }
+
+    private boolean sendMotionEventAsGesture(
+            int type, MotionEvent event, Bundle extraParams) {
+        return mMotionEventDelegate.sendGesture(type, event.getEventTime(),
+            (int) event.getX(), (int) event.getY(), false, extraParams);
+    }
+
+    private boolean sendGesture(
+            int type, long timeMs, int x, int y, Bundle extraParams) {
+        return mMotionEventDelegate.sendGesture(type, timeMs, x, y, false, extraParams);
+    }
+
+    private boolean sendLastGestureForVSync(
+            int type, long timeMs, int x, int y, Bundle extraParams) {
+        return mMotionEventDelegate.sendGesture(
+            type, timeMs, x, y, mInputEventsDeliveredAtVSync, extraParams);
     }
 
     void sendShowPressCancelIfNecessary(MotionEvent e) {
         if (!mShowPressIsCalled) return;
 
-        if (mMotionEventDelegate.sendGesture(GESTURE_SHOW_PRESS_CANCEL,
-                e.getEventTime(), (int) e.getX(), (int) e.getY(), null)) {
+        if (sendMotionEventAsGesture(GESTURE_SHOW_PRESS_CANCEL, e, null)) {
             mShowPressIsCalled = false;
         }
     }
@@ -816,8 +879,7 @@
         if (mLongPressDetector.isInLongPress() && ev.getAction() == MotionEvent.ACTION_UP &&
                 !mZoomManager.isScaleGestureDetectionInProgress()) {
             sendShowPressCancelIfNecessary(ev);
-            mMotionEventDelegate.sendGesture(GESTURE_LONG_TAP,
-                ev.getEventTime(), (int) ev.getX(), (int) ev.getY(), null);
+            sendMotionEventAsGesture(GESTURE_LONG_TAP, ev, null);
             return true;
         }
         return false;
@@ -827,15 +889,23 @@
      * This is for testing only.
      * @return The first motion event on the pending motion events queue.
      */
-    MotionEvent peekFirstInPendingMotionEvents() {
+    MotionEvent peekFirstInPendingMotionEventsForTesting() {
         return mPendingMotionEvents.peekFirst();
     }
 
     /**
      * This is for testing only.
+     * @return Whether the motion event is cancelled.
+     */
+    boolean isEventCancelledForTesting(MotionEvent event) {
+        return event != null && event.equals(mLastCancelledEvent);
+    }
+
+    /**
+     * This is for testing only.
      * @return The number of motion events on the pending motion events queue.
      */
-    int getNumberOfPendingMotionEvents() {
+    int getNumberOfPendingMotionEventsForTesting() {
         return mPendingMotionEvents.size();
     }
 
@@ -844,7 +914,7 @@
      * Sends a show pressed state gesture through mListener. This should always be called after
      * a down event;
      */
-    void sendShowPressedStateGestureForTest() {
+    void sendShowPressedStateGestureForTesting() {
         if (mCurrentDownEvent == null) return;
         mListener.onShowPress(mCurrentDownEvent);
     }
diff --git a/content/public/android/java/src/org/chromium/content/browser/ContentViewRenderView.java b/content/public/android/java/src/org/chromium/content/browser/ContentViewRenderView.java
index 781899d..ddd6b28 100644
--- a/content/public/android/java/src/org/chromium/content/browser/ContentViewRenderView.java
+++ b/content/public/android/java/src/org/chromium/content/browser/ContentViewRenderView.java
@@ -25,17 +25,10 @@
     private int mNativeContentViewRenderView = 0;
 
     private SurfaceView mSurfaceView;
+    private VSyncAdapter mVSyncAdapter;
 
     private ContentView mCurrentContentView;
 
-    private final VSyncMonitor mVSyncMonitor;
-
-    // The VSyncMonitor gives the timebase for the actual vsync, but we don't want render until
-    // we have had a chance for input events to propagate to the compositor thread. This takes
-    // 3 ms typically, so we adjust the vsync timestamps forward by a bit to give input events a
-    // chance to arrive.
-    private static final long INPUT_EVENT_LAG_FROM_VSYNC_MICROSECONDS = 3200;
-
     /**
      * Constructs a new ContentViewRenderView that should be can to a view hierarchy.
      * Native code should add/remove the layers to be rendered through the ContentViewLayerRenderer.
@@ -47,7 +40,7 @@
         mNativeContentViewRenderView = nativeInit();
         assert mNativeContentViewRenderView != 0;
 
-        mSurfaceView = new SurfaceView(getContext());
+        mSurfaceView = createSurfaceView(getContext());
         mSurfaceView.getHolder().addCallback(new SurfaceHolder.Callback() {
             @Override
             public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
@@ -70,24 +63,60 @@
             }
         });
 
-        mVSyncMonitor = new VSyncMonitor(getContext(), new VSyncMonitor.Listener() {
-            @Override
-            public void onVSync(VSyncMonitor monitor, long vsyncTimeMicros) {
-                if (mCurrentContentView == null) return;
+        mVSyncAdapter = new VSyncAdapter(getContext());
+        addView(mSurfaceView,
+                new FrameLayout.LayoutParams(
+                        FrameLayout.LayoutParams.MATCH_PARENT,
+                        FrameLayout.LayoutParams.MATCH_PARENT));
+    }
+
+    private static class VSyncAdapter implements VSyncManager.Provider, VSyncMonitor.Listener {
+        private final VSyncMonitor mVSyncMonitor;
+        private boolean mVSyncNotificationEnabled;
+        private VSyncManager.Listener mVSyncListener;
+
+        // The VSyncMonitor gives the timebase for the actual vsync, but we don't want render until
+        // we have had a chance for input events to propagate to the compositor thread. This takes
+        // 3 ms typically, so we adjust the vsync timestamps forward by a bit to give input events a
+        // chance to arrive.
+        private static final long INPUT_EVENT_LAG_FROM_VSYNC_MICROSECONDS = 3200;
+
+        VSyncAdapter(Context context) {
+            mVSyncMonitor = new VSyncMonitor(context, this);
+        }
+
+        @Override
+        public void onVSync(VSyncMonitor monitor, long vsyncTimeMicros) {
+            if (mVSyncListener == null) return;
+            if (mVSyncNotificationEnabled) {
+                mVSyncListener.onVSync(vsyncTimeMicros);
+                mVSyncMonitor.requestUpdate();
+            } else {
                 // Compensate for input event lag. Input events are delivered immediately on
                 // pre-JB releases, so this adjustment is only done for later versions.
                 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
                     vsyncTimeMicros += INPUT_EVENT_LAG_FROM_VSYNC_MICROSECONDS;
                 }
-                mCurrentContentView.getContentViewCore().updateVSync(vsyncTimeMicros,
+                mVSyncListener.updateVSync(vsyncTimeMicros,
                         mVSyncMonitor.getVSyncPeriodInMicroseconds());
             }
-        });
+        }
 
-        addView(mSurfaceView,
-                new FrameLayout.LayoutParams(
-                        FrameLayout.LayoutParams.MATCH_PARENT,
-                        FrameLayout.LayoutParams.MATCH_PARENT));
+        @Override
+        public void registerVSyncListener(VSyncManager.Listener listener) {
+            if (!mVSyncNotificationEnabled) mVSyncMonitor.requestUpdate();
+            mVSyncNotificationEnabled = true;
+        }
+
+        @Override
+        public void unregisterVSyncListener(VSyncManager.Listener listener) {
+            mVSyncNotificationEnabled = false;
+        }
+
+        void setVSyncListener(VSyncManager.Listener listener) {
+            mVSyncListener = listener;
+            if (mVSyncListener != null) mVSyncMonitor.requestUpdate();
+        }
     }
 
     /**
@@ -102,13 +131,13 @@
      * Makes the passed ContentView the one displayed by this ContentViewRenderView.
      */
     public void setCurrentContentView(ContentView contentView) {
+        ContentViewCore contentViewCore = contentView.getContentViewCore();
         nativeSetCurrentContentView(mNativeContentViewRenderView,
-                contentView.getContentViewCore().getNativeContentViewCore());
+                contentViewCore.getNativeContentViewCore());
 
         mCurrentContentView = contentView;
-        mCurrentContentView.getContentViewCore().onPhysicalBackingSizeChanged(
-                getWidth(), getHeight());
-        mVSyncMonitor.requestUpdate();
+        contentViewCore.onPhysicalBackingSizeChanged(getWidth(), getHeight());
+        mVSyncAdapter.setVSyncListener(contentViewCore.getVSyncListener(mVSyncAdapter));
     }
 
     /**
@@ -119,6 +148,16 @@
     }
 
     /**
+     * This method could be subclassed optionally to provide a custom SurfaceView object to
+     * this ContentViewRenderView.
+     * @param context The context used to create the SurfaceView object.
+     * @return The created SurfaceView object.
+     */
+    protected SurfaceView createSurfaceView(Context context) {
+        return new SurfaceView(context);
+    }
+
+    /**
      * @return whether the surface view is initialized and ready to render.
      */
     public boolean isInitialized() {
diff --git a/content/public/android/java/src/org/chromium/content/browser/DeviceMotionAndOrientation.java b/content/public/android/java/src/org/chromium/content/browser/DeviceMotionAndOrientation.java
new file mode 100644
index 0000000..ecb9d62
--- /dev/null
+++ b/content/public/android/java/src/org/chromium/content/browser/DeviceMotionAndOrientation.java
@@ -0,0 +1,451 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.content.browser;
+
+import android.content.Context;
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
+import android.hardware.SensorManager;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Looper;
+import android.util.Log;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Sets;
+
+import org.chromium.base.CalledByNative;
+import org.chromium.base.JNINamespace;
+import org.chromium.base.WeakContext;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Android implementation of the device motion and orientation APIs.
+ */
+@JNINamespace("content")
+class DeviceMotionAndOrientation implements SensorEventListener {
+
+    private static final String TAG = "DeviceMotionAndOrientation";
+
+    // These fields are lazily initialized by getHandler().
+    private Thread mThread;
+    private Handler mHandler;
+
+    // The lock to access the mHandler.
+    private Object mHandlerLock = new Object();
+
+    // Non-zero if and only if we're listening for events.
+    // To avoid race conditions on the C++ side, access must be synchronized.
+    private int mNativePtr;
+
+    // The lock to access the mNativePtr.
+    private Object mNativePtrLock = new Object();
+
+    // The acceleration vector including gravity expressed in the body frame.
+    private float[] mAccelerationVector;
+
+    // The geomagnetic vector expressed in the body frame.
+    private float[] mMagneticFieldVector;
+
+    // Lazily initialized when registering for notifications.
+    private SensorManagerProxy mSensorManagerProxy;
+
+    // The only instance of that class and its associated lock.
+    private static DeviceMotionAndOrientation sSingleton;
+    private static Object sSingletonLock = new Object();
+
+    /**
+     * constants for using in JNI calls, also see
+     * content/browser/device_orientation/data_fetcher_impl_android.cc
+     */
+    static final int DEVICE_ORIENTATION = 0;
+    static final int DEVICE_MOTION = 1;
+
+    static final ImmutableSet<Integer> DEVICE_ORIENTATION_SENSORS = ImmutableSet.of(
+            Sensor.TYPE_ACCELEROMETER,
+            Sensor.TYPE_MAGNETIC_FIELD);
+
+    static final ImmutableSet<Integer> DEVICE_MOTION_SENSORS = ImmutableSet.of(
+            Sensor.TYPE_ACCELEROMETER,
+            Sensor.TYPE_LINEAR_ACCELERATION,
+            Sensor.TYPE_GYROSCOPE);
+
+    @VisibleForTesting
+    final Set<Integer> mActiveSensors = Sets.newHashSet();
+    boolean mDeviceMotionIsActive = false;
+    boolean mDeviceOrientationIsActive = false;
+
+    protected DeviceMotionAndOrientation() {
+    }
+
+    /**
+     * Start listening for sensor events. If this object is already listening
+     * for events, the old callback is unregistered first.
+     *
+     * @param nativePtr Value to pass to nativeGotOrientation() for each event.
+     * @param rateInMilliseconds Requested callback rate in milliseconds. The
+     *            actual rate may be higher. Unwanted events should be ignored.
+     * @param eventType Type of event to listen to, can be either DEVICE_ORIENTATION or
+     *                  DEVICE_MOTION.
+     * @return True on success.
+     */
+    @CalledByNative
+    public boolean start(int nativePtr, int eventType, int rateInMilliseconds) {
+        boolean success = false;
+        synchronized (mNativePtrLock) {
+            switch (eventType) {
+                case DEVICE_ORIENTATION:
+                    success = registerSensors(DEVICE_ORIENTATION_SENSORS, rateInMilliseconds,
+                            true);
+                    break;
+                case DEVICE_MOTION:
+                    // note: device motion spec does not require all sensors to be available
+                    success = registerSensors(DEVICE_MOTION_SENSORS, rateInMilliseconds, false);
+                    break;
+                default:
+                    Log.e(TAG, "Unknown event type: " + eventType);
+                    return false;
+            }
+            if (success) {
+                mNativePtr = nativePtr;
+                setEventTypeActive(eventType, true);
+            }
+            return success;
+        }
+    }
+
+    /**
+     * Stop listening to sensors for a given event type. Ensures that sensors are not disabled
+     * if they are still in use by a different event type.
+     *
+     * @param eventType Type of event to listen to, can be either DEVICE_ORIENTATION or
+     *                  DEVICE_MOTION.
+     * We strictly guarantee that the corresponding native*() methods will not be called
+     * after this method returns.
+     */
+    @CalledByNative
+    public void stop(int eventType) {
+        Set<Integer> sensorsToRemainActive = Sets.newHashSet();
+        synchronized (mNativePtrLock) {
+            switch (eventType) {
+                case DEVICE_ORIENTATION:
+                    if (mDeviceMotionIsActive) {
+                        sensorsToRemainActive.addAll(DEVICE_MOTION_SENSORS);
+                    }
+                    break;
+                case DEVICE_MOTION:
+                    if (mDeviceOrientationIsActive) {
+                        sensorsToRemainActive.addAll(DEVICE_ORIENTATION_SENSORS);
+                    }
+                    break;
+                default:
+                    Log.e(TAG, "Unknown event type: " + eventType);
+                    return;
+            }
+
+            Set<Integer> sensorsToDeactivate = Sets.newHashSet(mActiveSensors);
+            sensorsToDeactivate.removeAll(sensorsToRemainActive);
+            unregisterSensors(sensorsToDeactivate);
+            setEventTypeActive(eventType, false);
+            if (mActiveSensors.isEmpty()) {
+                mNativePtr = 0;
+            }
+        }
+    }
+
+    @Override
+    public void onAccuracyChanged(Sensor sensor, int accuracy) {
+        // Nothing
+    }
+
+    @Override
+    public void onSensorChanged(SensorEvent event) {
+        sensorChanged(event.sensor.getType(), event.values);
+    }
+
+    @VisibleForTesting
+    void sensorChanged(int type, float[] values) {
+
+        switch (type) {
+            case Sensor.TYPE_ACCELEROMETER:
+                if (mAccelerationVector == null) {
+                    mAccelerationVector = new float[3];
+                }
+                System.arraycopy(values, 0, mAccelerationVector, 0,
+                        mAccelerationVector.length);
+                if (mDeviceMotionIsActive) {
+                    gotAccelerationIncludingGravity(mAccelerationVector[0], mAccelerationVector[1],
+                        mAccelerationVector[2]);
+                }
+                break;
+            case Sensor.TYPE_LINEAR_ACCELERATION:
+                if (mDeviceMotionIsActive) {
+                    gotAcceleration(values[0], values[1], values[2]);
+                }
+                break;
+            case Sensor.TYPE_GYROSCOPE:
+                if (mDeviceMotionIsActive) {
+                    gotRotationRate(values[0], values[1], values[2]);
+                }
+                break;
+            case Sensor.TYPE_MAGNETIC_FIELD:
+                if (mMagneticFieldVector == null) {
+                    mMagneticFieldVector = new float[3];
+                }
+                System.arraycopy(values, 0, mMagneticFieldVector, 0,
+                        mMagneticFieldVector.length);
+                break;
+            default:
+                // Unexpected
+                return;
+        }
+
+        if (mDeviceOrientationIsActive) {
+            getOrientationUsingGetRotationMatrix();
+        }
+    }
+
+    private void getOrientationUsingGetRotationMatrix() {
+        if (mAccelerationVector == null || mMagneticFieldVector == null) {
+            return;
+        }
+
+        // Get the rotation matrix.
+        // The rotation matrix that transforms from the body frame to the earth
+        // frame.
+        float[] deviceRotationMatrix = new float[9];
+        if (!SensorManager.getRotationMatrix(deviceRotationMatrix, null, mAccelerationVector,
+                mMagneticFieldVector)) {
+            return;
+        }
+
+        // Convert rotation matrix to rotation angles.
+        // Assuming that the rotations are appied in the order listed at
+        // http://developer.android.com/reference/android/hardware/SensorEvent.html#values
+        // the rotations are applied about the same axes and in the same order as required by the
+        // API. The only conversions are sign changes as follows.  The angles are in radians
+
+        float[] rotationAngles = new float[3];
+        SensorManager.getOrientation(deviceRotationMatrix, rotationAngles);
+
+        double alpha = Math.toDegrees(-rotationAngles[0]);
+        while (alpha < 0.0) {
+            alpha += 360.0; // [0, 360)
+        }
+
+        double beta = Math.toDegrees(-rotationAngles[1]);
+        while (beta < -180.0) {
+            beta += 360.0; // [-180, 180)
+        }
+
+        double gamma = Math.toDegrees(rotationAngles[2]);
+        while (gamma < -90.0) {
+            gamma += 360.0; // [-90, 90)
+        }
+
+        gotOrientation(alpha, beta, gamma);
+    }
+
+    private SensorManagerProxy getSensorManagerProxy() {
+        if (mSensorManagerProxy != null) {
+            return mSensorManagerProxy;
+        }
+        SensorManager sensorManager = (SensorManager)WeakContext.getSystemService(
+                Context.SENSOR_SERVICE);
+        if (sensorManager != null) {
+            mSensorManagerProxy = new SensorManagerProxyImpl(sensorManager);
+        }
+        return mSensorManagerProxy;
+    }
+
+    @VisibleForTesting
+    void setSensorManagerProxy(SensorManagerProxy sensorManagerProxy) {
+        mSensorManagerProxy = sensorManagerProxy;
+    }
+
+    private void setEventTypeActive(int eventType, boolean value) {
+        switch (eventType) {
+            case DEVICE_ORIENTATION:
+                mDeviceOrientationIsActive = value;
+                return;
+            case DEVICE_MOTION:
+                mDeviceMotionIsActive = value;
+                return;
+        }
+    }
+
+    /**
+     * @param sensorTypes List of sensors to activate.
+     * @param rateInMilliseconds Intended delay (in milliseconds) between sensor readings.
+     * @param failOnMissingSensor If true the method returns true only if all sensors could be
+     *                            activated. When false the method return true if at least one
+     *                            sensor in sensorTypes could be activated.
+     */
+    private boolean registerSensors(Iterable<Integer> sensorTypes, int rateInMilliseconds,
+            boolean failOnMissingSensor) {
+        Set<Integer> sensorsToActivate = Sets.newHashSet(sensorTypes);
+        sensorsToActivate.removeAll(mActiveSensors);
+        boolean success = false;
+
+        for (Integer sensorType : sensorsToActivate) {
+            boolean result = registerForSensorType(sensorType, rateInMilliseconds);
+            if (!result && failOnMissingSensor) {
+                // restore the previous state upon failure
+                unregisterSensors(sensorsToActivate);
+                return false;
+            }
+            if (result) {
+                mActiveSensors.add(sensorType);
+                success = true;
+            }
+        }
+        return success;
+    }
+
+    private void unregisterSensors(Iterable<Integer> sensorTypes) {
+        for (Integer sensorType : sensorTypes) {
+            if (mActiveSensors.contains(sensorType)) {
+                getSensorManagerProxy().unregisterListener(this, sensorType);
+                mActiveSensors.remove(sensorType);
+            }
+        }
+    }
+
+    private boolean registerForSensorType(int type, int rateInMilliseconds) {
+        SensorManagerProxy sensorManager = getSensorManagerProxy();
+        if (sensorManager == null) {
+            return false;
+        }
+        final int rateInMicroseconds = 1000 * rateInMilliseconds;
+        return sensorManager.registerListener(this, type, rateInMicroseconds, getHandler());
+    }
+
+    protected void gotOrientation(double alpha, double beta, double gamma) {
+        synchronized (mNativePtrLock) {
+            if (mNativePtr != 0) {
+              nativeGotOrientation(mNativePtr, alpha, beta, gamma);
+            }
+        }
+    }
+
+    protected void gotAcceleration(double x, double y, double z) {
+        synchronized (mNativePtrLock) {
+            if (mNativePtr != 0) {
+              nativeGotAcceleration(mNativePtr, x, y, z);
+            }
+        }
+    }
+
+    protected void gotAccelerationIncludingGravity(double x, double y, double z) {
+        synchronized (mNativePtrLock) {
+            if (mNativePtr != 0) {
+              nativeGotAccelerationIncludingGravity(mNativePtr, x, y, z);
+            }
+        }
+    }
+
+    protected void gotRotationRate(double alpha, double beta, double gamma) {
+        synchronized (mNativePtrLock) {
+            if (mNativePtr != 0) {
+              nativeGotRotationRate(mNativePtr, alpha, beta, gamma);
+            }
+        }
+    }
+
+    private Handler getHandler() {
+        // TODO(timvolodine): Remove the mHandlerLock when sure that getHandler is not called
+        // from multiple threads. This will be the case when device motion and device orientation
+        // use the same polling thread (also see crbug/234282).
+        synchronized (mHandlerLock) {
+            if (mHandler == null) {
+                HandlerThread thread = new HandlerThread("DeviceMotionAndOrientation");
+                thread.start();
+                mHandler = new Handler(thread.getLooper());  // blocks on thread start
+            }
+            return mHandler;
+        }
+    }
+
+    @CalledByNative
+    static DeviceMotionAndOrientation getInstance() {
+        synchronized (sSingletonLock) {
+            if (sSingleton == null) {
+                sSingleton = new DeviceMotionAndOrientation();
+            }
+            return sSingleton;
+        }
+    }
+
+    /**
+     * Native JNI calls,
+     * see content/browser/device_orientation/data_fetcher_impl_android.cc
+     */
+
+    /**
+     * Orientation of the device with respect to its reference frame.
+     */
+    private native void nativeGotOrientation(
+            int nativeDataFetcherImplAndroid,
+            double alpha, double beta, double gamma);
+
+    /**
+     * Linear acceleration without gravity of the device with respect to its body frame.
+     */
+    private native void nativeGotAcceleration(
+            int nativeDataFetcherImplAndroid,
+            double x, double y, double z);
+
+    /**
+     * Acceleration including gravity of the device with respect to its body frame.
+     */
+    private native void nativeGotAccelerationIncludingGravity(
+            int nativeDataFetcherImplAndroid,
+            double x, double y, double z);
+
+    /**
+     * Rotation rate of the device with respect to its body frame.
+     */
+    private native void nativeGotRotationRate(
+            int nativeDataFetcherImplAndroid,
+            double alpha, double beta, double gamma);
+
+    /**
+     * Need the an interface for SensorManager for testing.
+     */
+    interface SensorManagerProxy {
+        public boolean registerListener(SensorEventListener listener, int sensorType, int rate,
+                Handler handler);
+        public void unregisterListener(SensorEventListener listener, int sensorType);
+    }
+
+    static class SensorManagerProxyImpl implements SensorManagerProxy {
+        private final SensorManager mSensorManager;
+
+        SensorManagerProxyImpl(SensorManager sensorManager) {
+            mSensorManager = sensorManager;
+        }
+
+        public boolean registerListener(SensorEventListener listener, int sensorType, int rate,
+                Handler handler) {
+            List<Sensor> sensors = mSensorManager.getSensorList(sensorType);
+            if (sensors.isEmpty()) {
+                return false;
+            }
+            return mSensorManager.registerListener(listener, sensors.get(0), rate, handler);
+        }
+
+        public void unregisterListener(SensorEventListener listener, int sensorType) {
+            List<Sensor> sensors = mSensorManager.getSensorList(sensorType);
+            if (!sensors.isEmpty()) {
+                mSensorManager.unregisterListener(listener, sensors.get(0));
+            }
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/content/public/android/java/src/org/chromium/content/browser/DeviceOrientation.java b/content/public/android/java/src/org/chromium/content/browser/DeviceOrientation.java
deleted file mode 100644
index a77cd28..0000000
--- a/content/public/android/java/src/org/chromium/content/browser/DeviceOrientation.java
+++ /dev/null
@@ -1,269 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.content.browser;
-
-import android.content.Context;
-import android.hardware.Sensor;
-import android.hardware.SensorEvent;
-import android.hardware.SensorEventListener;
-import android.hardware.SensorManager;
-import android.os.Handler;
-import android.os.Looper;
-
-import org.chromium.base.CalledByNative;
-import org.chromium.base.JNINamespace;
-import org.chromium.base.WeakContext;
-
-import java.util.List;
-
-/**
- * Android implementation of the DeviceOrientation API.
- */
-@JNINamespace("content")
-class DeviceOrientation implements SensorEventListener {
-
-    // These fields are lazily initialized by getHandler().
-    private Thread mThread;
-    private Handler mHandler;
-
-    // The lock to access the mHandler.
-    private Object mHandlerLock = new Object();
-
-    // Non-zero if and only if we're listening for events.
-    // To avoid race conditions on the C++ side, access must be synchronized.
-    private int mNativePtr;
-
-    // The lock to access the mNativePtr.
-    private Object mNativePtrLock = new Object();
-
-    // The gravity vector expressed in the body frame.
-    private float[] mGravityVector;
-
-    // The geomagnetic vector expressed in the body frame.
-    private float[] mMagneticFieldVector;
-
-    // Lazily initialized when registering for notifications.
-    private SensorManager mSensorManager;
-
-    // The only instance of that class and its associated lock.
-    private static DeviceOrientation sSingleton;
-    private static Object sSingletonLock = new Object();
-
-    private DeviceOrientation() {
-    }
-
-    /**
-     * Start listening for sensor events. If this object is already listening
-     * for events, the old callback is unregistered first.
-     *
-     * @param nativePtr Value to pass to nativeGotOrientation() for each event.
-     * @param rateInMilliseconds Requested callback rate in milliseconds. The
-     *            actual rate may be higher. Unwanted events should be ignored.
-     * @return True on success.
-     */
-    @CalledByNative
-    public boolean start(int nativePtr, int rateInMilliseconds) {
-        synchronized (mNativePtrLock) {
-            stop();
-            if (registerForSensors(rateInMilliseconds)) {
-                mNativePtr = nativePtr;
-                return true;
-            }
-            return false;
-        }
-    }
-
-    /**
-     * Stop listening for sensor events. Always succeeds.
-     *
-     * We strictly guarantee that nativeGotOrientation() will not be called
-     * after this method returns.
-     */
-    @CalledByNative
-    public void stop() {
-        synchronized (mNativePtrLock) {
-            if (mNativePtr != 0) {
-                mNativePtr = 0;
-                unregisterForSensors();
-            }
-        }
-    }
-
-    @Override
-    public void onAccuracyChanged(Sensor sensor, int accuracy) {
-        // Nothing
-    }
-
-    @Override
-    public void onSensorChanged(SensorEvent event) {
-        switch (event.sensor.getType()) {
-            case Sensor.TYPE_ACCELEROMETER:
-                if (mGravityVector == null) {
-                    mGravityVector = new float[3];
-                }
-                System.arraycopy(event.values, 0, mGravityVector, 0, mGravityVector.length);
-                break;
-
-            case Sensor.TYPE_MAGNETIC_FIELD:
-                if (mMagneticFieldVector == null) {
-                    mMagneticFieldVector = new float[3];
-                }
-                System.arraycopy(event.values, 0, mMagneticFieldVector, 0,
-                                 mMagneticFieldVector.length);
-                break;
-
-            default:
-                // Unexpected
-                return;
-        }
-
-        getOrientationUsingGetRotationMatrix();
-    }
-
-    void getOrientationUsingGetRotationMatrix() {
-        if (mGravityVector == null || mMagneticFieldVector == null) {
-            return;
-        }
-
-        // Get the rotation matrix.
-        // The rotation matrix that transforms from the body frame to the earth
-        // frame.
-        float[] deviceRotationMatrix = new float[9];
-        if (!SensorManager.getRotationMatrix(deviceRotationMatrix, null, mGravityVector,
-                mMagneticFieldVector)) {
-            return;
-        }
-
-        // Convert rotation matrix to rotation angles.
-        // Assuming that the rotations are appied in the order listed at
-        // http://developer.android.com/reference/android/hardware/SensorEvent.html#values
-        // the rotations are applied about the same axes and in the same order as required by the
-        // API. The only conversions are sign changes as follows.  The angles are in radians
-
-        float[] rotationAngles = new float[3];
-        SensorManager.getOrientation(deviceRotationMatrix, rotationAngles);
-
-        double alpha = Math.toDegrees(-rotationAngles[0]);
-        while (alpha < 0.0) {
-            alpha += 360.0; // [0, 360)
-        }
-
-        double beta = Math.toDegrees(-rotationAngles[1]);
-        while (beta < -180.0) {
-            beta += 360.0; // [-180, 180)
-        }
-
-        double gamma = Math.toDegrees(rotationAngles[2]);
-        while (gamma < -90.0) {
-            gamma += 360.0; // [-90, 90)
-        }
-
-        gotOrientation(alpha, beta, gamma);
-    }
-
-    boolean registerForSensors(int rateInMilliseconds) {
-        if (registerForSensorType(Sensor.TYPE_ACCELEROMETER, rateInMilliseconds)
-                && registerForSensorType(Sensor.TYPE_MAGNETIC_FIELD, rateInMilliseconds)) {
-            return true;
-        }
-        unregisterForSensors();
-        return false;
-    }
-
-    private SensorManager getSensorManager() {
-        if (mSensorManager != null) {
-            return mSensorManager;
-        }
-        mSensorManager = (SensorManager)WeakContext.getSystemService(Context.SENSOR_SERVICE);
-        return mSensorManager;
-    }
-
-    void unregisterForSensors() {
-        SensorManager sensorManager = getSensorManager();
-        if (sensorManager == null) {
-            return;
-        }
-        sensorManager.unregisterListener(this);
-    }
-
-    boolean registerForSensorType(int type, int rateInMilliseconds) {
-        SensorManager sensorManager = getSensorManager();
-        if (sensorManager == null) {
-            return false;
-        }
-        List<Sensor> sensors = sensorManager.getSensorList(type);
-        if (sensors.isEmpty()) {
-            return false;
-        }
-
-        final int rateInMicroseconds = 1000 * rateInMilliseconds;
-        // We want to err on the side of getting more events than we need.
-        final int requestedRate = rateInMicroseconds / 2;
-
-        // TODO(steveblock): Consider handling multiple sensors.
-        return sensorManager.registerListener(this, sensors.get(0), requestedRate, getHandler());
-    }
-
-    void gotOrientation(double alpha, double beta, double gamma) {
-        synchronized (mNativePtrLock) {
-            if (mNativePtr != 0) {
-              nativeGotOrientation(mNativePtr, alpha, beta, gamma);
-            }
-        }
-    }
-
-    private Handler getHandler() {
-        synchronized (mHandlerLock) {
-            // If we don't have a background thread, start it now.
-            if (mThread == null) {
-                mThread = new Thread(new Runnable() {
-                    @Override
-                    public void run() {
-                        Looper.prepare();
-                        // Our Handler doesn't actually have to do anything, because
-                        // SensorManager posts directly to the underlying Looper.
-                        setHandler(new Handler());
-                        Looper.loop();
-                    }
-                });
-                mThread.start();
-            }
-            // Wait for the background thread to spin up.
-            while (mHandler == null) {
-                try {
-                    mHandlerLock.wait();
-                } catch (InterruptedException e) {
-                    // Somebody doesn't want us to wait! That's okay, SensorManager accepts null.
-                    return null;
-                }
-            }
-            return mHandler;
-        }
-    }
-
-    private void setHandler(Handler handler) {
-        synchronized (mHandlerLock) {
-            mHandler = handler;
-            mHandlerLock.notify();
-        }
-    }
-
-    @CalledByNative
-    private static DeviceOrientation getInstance() {
-        synchronized (sSingletonLock) {
-            if (sSingleton == null) {
-                sSingleton = new DeviceOrientation();
-            }
-            return sSingleton;
-        }
-    }
-
-    /**
-     * See chrome/browser/device_orientation/data_fetcher_impl_android.cc
-     */
-    private native void nativeGotOrientation(
-            int nativeDataFetcherImplAndroid,
-            double alpha, double beta, double gamma);
-}
diff --git a/content/public/android/java/src/org/chromium/content/browser/DeviceUtils.java b/content/public/android/java/src/org/chromium/content/browser/DeviceUtils.java
index 04ebb45..30bb418 100644
--- a/content/public/android/java/src/org/chromium/content/browser/DeviceUtils.java
+++ b/content/public/android/java/src/org/chromium/content/browser/DeviceUtils.java
@@ -24,6 +24,9 @@
      * @return        Whether the app is should treat the device as a tablet for layout.
      */
     public static boolean isTablet(Context context) {
+        if (isTv(context)) {
+            return true;
+        }
         int minimumScreenWidthDp = context.getResources().getConfiguration().smallestScreenWidthDp;
         return minimumScreenWidthDp >= MINIMUM_TABLET_WIDTH_DP;
     }
@@ -49,7 +52,7 @@
      * @param context The context for the caller activity.
      */
     public static void addDeviceSpecificUserAgentSwitch(Context context) {
-        if (isTv(context) || isTablet(context)) {
+        if (isTablet(context)) {
             CommandLine.getInstance().appendSwitch(CommandLine.TABLET_UI);
         } else {
             CommandLine.getInstance().appendSwitch(CommandLine.USE_MOBILE_UA);
diff --git a/content/public/android/java/src/org/chromium/content/browser/DownloadController.java b/content/public/android/java/src/org/chromium/content/browser/DownloadController.java
index 77936fc..9577ba1 100644
--- a/content/public/android/java/src/org/chromium/content/browser/DownloadController.java
+++ b/content/public/android/java/src/org/chromium/content/browser/DownloadController.java
@@ -52,33 +52,46 @@
     }
 
     /**
-     * Notifies the download delegate that a new POST download has started.
+     * Notifies the download delegate that a new download has started. This can
+     * be either a POST download or a GET download with authentication.
      */
     @CalledByNative
-    public void onHttpPostDownloadStarted(ContentViewCore view) {
+    public void onDownloadStarted(ContentViewCore view) {
         ContentViewDownloadDelegate downloadDelagate = downloadDelegateFromView(view);
 
         if (downloadDelagate != null) {
-            downloadDelagate.onHttpPostDownloadStarted();
+            downloadDelagate.onDownloadStarted();
         }
     }
 
     /**
-     * Notifies the download delegate that a POST download completed and passes along info about the
-     * download.
+     * Notifies the download delegate that a download completed and passes along info about the
+     * download. This can be either a POST download or a GET download with authentication.
      */
     @CalledByNative
-    public void onHttpPostDownloadCompleted(ContentViewCore view, String url,
+    public void onDownloadCompleted(ContentViewCore view, String url,
             String contentDisposition, String mimetype, String path,
             long contentLength, boolean successful) {
         ContentViewDownloadDelegate downloadDelagate = downloadDelegateFromView(view);
 
         if (downloadDelagate != null) {
-            downloadDelagate.onHttpPostDownloadCompleted(
+            downloadDelagate.onDownloadCompleted(
                     url, mimetype, path, contentLength, successful);
         }
     }
 
+    /**
+     * Notifies the download delegate that a dangerous download started.
+     */
+    @CalledByNative
+    public void onDangerousDownload(ContentViewCore view, String filename,
+            int downloadId) {
+        ContentViewDownloadDelegate downloadDelagate = downloadDelegateFromView(view);
+        if (downloadDelagate != null) {
+            downloadDelagate.onDangerousDownload(filename, downloadId);
+        }
+    }
+
     // native methods
     private native void nativeInit();
 }
diff --git a/content/public/android/java/src/org/chromium/content/browser/ImeAdapter.java b/content/public/android/java/src/org/chromium/content/browser/ImeAdapter.java
deleted file mode 100644
index 4b312fd..0000000
--- a/content/public/android/java/src/org/chromium/content/browser/ImeAdapter.java
+++ /dev/null
@@ -1,842 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.content.browser;
-
-import android.content.Context;
-import android.os.Handler;
-import android.os.ResultReceiver;
-import android.text.Editable;
-import android.text.InputType;
-import android.text.Selection;
-import android.util.Log;
-import android.view.KeyCharacterMap;
-import android.view.KeyEvent;
-import android.view.View;
-import android.view.inputmethod.BaseInputConnection;
-import android.view.inputmethod.EditorInfo;
-import android.view.inputmethod.ExtractedText;
-import android.view.inputmethod.ExtractedTextRequest;
-
-import com.google.common.annotations.VisibleForTesting;
-
-import org.chromium.base.CalledByNative;
-import org.chromium.base.JNINamespace;
-
-/**
- * Adapts and plumbs android IME service onto the chrome text input API.
- * ImeAdapter provides an interface in both ways native <-> java:
- * 1. InputConnectionAdapter notifies native code of text composition state and
- *    dispatch key events from java -> WebKit.
- * 2. Native ImeAdapter notifies java side to clear composition text.
- *
- * The basic flow is:
- * 1. When InputConnectionAdapter gets called with composition or result text:
- *    If we receive a composition text or a result text, then we just need to
- *    dispatch a synthetic key event with special keycode 229, and then dispatch
- *    the composition or result text.
- * 2. Intercept dispatchKeyEvent() method for key events not handled by IME, we
- *   need to dispatch them to webkit and check webkit's reply. Then inject a
- *   new key event for further processing if webkit didn't handle it.
- *
- * Note that the native peer object does not take any strong reference onto the
- * instance of this java object, hence it is up to the client of this class (e.g.
- * the ViewEmbedder implementor) to hold a strong reference to it for the required
- * lifetime of the object.
- */
-@JNINamespace("content")
-class ImeAdapter {
-    interface ViewEmbedder {
-        /**
-         * @param isFinish whether the event is occurring because input is finished.
-         */
-        public void onImeEvent(boolean isFinish);
-        public void onSetFieldValue();
-        public void onDismissInput();
-        public View getAttachedView();
-        public ResultReceiver getNewShowKeyboardReceiver();
-    }
-
-    static final int COMPOSITION_KEY_CODE = 229;
-
-    static int sEventTypeRawKeyDown;
-    static int sEventTypeKeyUp;
-    static int sEventTypeChar;
-    static int sTextInputTypeNone;
-    static int sTextInputTypeText;
-    static int sTextInputTypeTextArea;
-    static int sTextInputTypePassword;
-    static int sTextInputTypeSearch;
-    static int sTextInputTypeUrl;
-    static int sTextInputTypeEmail;
-    static int sTextInputTypeTel;
-    static int sTextInputTypeNumber;
-    static int sTextInputTypeWeek;
-    static int sTextInputTypeContentEditable;
-    static int sModifierShift;
-    static int sModifierAlt;
-    static int sModifierCtrl;
-    static int sModifierCapsLockOn;
-    static int sModifierNumLockOn;
-
-    @CalledByNative
-    static void initializeWebInputEvents(int eventTypeRawKeyDown, int eventTypeKeyUp,
-            int eventTypeChar, int modifierShift, int modifierAlt, int modifierCtrl,
-            int modifierCapsLockOn, int modifierNumLockOn) {
-        sEventTypeRawKeyDown = eventTypeRawKeyDown;
-        sEventTypeKeyUp = eventTypeKeyUp;
-        sEventTypeChar = eventTypeChar;
-        sModifierShift = modifierShift;
-        sModifierAlt = modifierAlt;
-        sModifierCtrl = modifierCtrl;
-        sModifierCapsLockOn = modifierCapsLockOn;
-        sModifierNumLockOn = modifierNumLockOn;
-    }
-
-    @CalledByNative
-    static void initializeTextInputTypes(int textInputTypeNone, int textInputTypeText,
-            int textInputTypeTextArea, int textInputTypePassword, int textInputTypeSearch,
-            int textInputTypeUrl, int textInputTypeEmail, int textInputTypeTel,
-            int textInputTypeNumber, int textInputTypeDate, int textInputTypeDateTime,
-            int textInputTypeDateTimeLocal, int textInputTypeMonth, int textInputTypeTime,
-            int textInputTypeWeek, int textInputTypeContentEditable) {
-        sTextInputTypeNone = textInputTypeNone;
-        sTextInputTypeText = textInputTypeText;
-        sTextInputTypeTextArea = textInputTypeTextArea;
-        sTextInputTypePassword = textInputTypePassword;
-        sTextInputTypeSearch = textInputTypeSearch;
-        sTextInputTypeUrl = textInputTypeUrl;
-        sTextInputTypeEmail = textInputTypeEmail;
-        sTextInputTypeTel = textInputTypeTel;
-        sTextInputTypeNumber = textInputTypeNumber;
-        sTextInputTypeWeek = textInputTypeWeek;
-        sTextInputTypeContentEditable = textInputTypeContentEditable;
-    }
-
-    private int mNativeImeAdapterAndroid;
-    private int mTextInputType;
-
-    private final Context mContext;
-    private InputMethodManagerWrapper mInputMethodManagerWrapper;
-    private final SelectionHandleController mSelectionHandleController;
-    private final InsertionHandleController mInsertionHandleController;
-    private AdapterInputConnection mInputConnection;
-    private final ViewEmbedder mViewEmbedder;
-    private final Handler mHandler;
-
-    private class DelayedDismissInput implements Runnable {
-        private final int mNativeImeAdapter;
-
-        DelayedDismissInput(int nativeImeAdapter) {
-            mNativeImeAdapter = nativeImeAdapter;
-        }
-
-        @Override
-        public void run() {
-            attach(mNativeImeAdapter, sTextInputTypeNone);
-            dismissInput(true);
-        }
-    }
-
-    private DelayedDismissInput mDismissInput = null;
-
-    @VisibleForTesting
-    protected boolean mIsShowWithoutHideOutstanding = false;
-
-    // Delay introduced to avoid hiding the keyboard if new show requests are received.
-    // The time required by the unfocus-focus events triggered by tab has been measured in soju:
-    // Mean: 18.633 ms, Standard deviation: 7.9837 ms.
-    // The value here should be higher enough to cover these cases, but not too high to avoid
-    // letting the user perceiving important delays.
-    private static final int INPUT_DISMISS_DELAY = 150;
-
-    ImeAdapter(Context context, SelectionHandleController selectionHandleController,
-            InsertionHandleController insertionHandleController, ViewEmbedder embedder) {
-        mContext = context;
-        mInputMethodManagerWrapper = new InputMethodManagerWrapper(context);
-        mSelectionHandleController = selectionHandleController;
-        mInsertionHandleController = insertionHandleController;
-        mViewEmbedder = embedder;
-        mHandler = new Handler();
-    }
-
-    boolean isFor(int nativeImeAdapter, int textInputType) {
-        return mNativeImeAdapterAndroid == nativeImeAdapter &&
-               mTextInputType == textInputType;
-    }
-
-    @VisibleForTesting
-    protected void setInputMethodManagerWrapper(InputMethodManagerWrapper immw) {
-        mInputMethodManagerWrapper = immw;
-    }
-
-    private InputMethodManagerWrapper getInputMethodManagerWrapper() {
-        return mInputMethodManagerWrapper;
-    }
-
-    void attachAndShowIfNeeded(int nativeImeAdapter, int textInputType,
-            String text, boolean showIfNeeded) {
-        mHandler.removeCallbacks(mDismissInput);
-
-        // If current input type is none and showIfNeeded is false, IME should not be shown
-        // and input type should remain as none.
-        if (mTextInputType == sTextInputTypeNone && !showIfNeeded) {
-            return;
-        }
-
-        if (!isFor(nativeImeAdapter, textInputType)) {
-            // Set a delayed task to perform unfocus. This avoids hiding the keyboard when tabbing
-            // through text inputs or when JS rapidly changes focus to another text element.
-            if (textInputType == sTextInputTypeNone) {
-                mDismissInput = new DelayedDismissInput(nativeImeAdapter);
-                mHandler.postDelayed(mDismissInput, INPUT_DISMISS_DELAY);
-                return;
-            }
-
-            int previousType = mTextInputType;
-            attach(nativeImeAdapter, textInputType);
-
-            mInputMethodManagerWrapper.restartInput(mViewEmbedder.getAttachedView());
-            if (showIfNeeded) {
-                showKeyboard();
-            }
-        } else if (hasInputType() && showIfNeeded) {
-            showKeyboard();
-        }
-    }
-
-    void attach(int nativeImeAdapter, int textInputType) {
-        mNativeImeAdapterAndroid = nativeImeAdapter;
-        mTextInputType = textInputType;
-        nativeAttachImeAdapter(mNativeImeAdapterAndroid);
-    }
-
-    /**
-     * Attaches the imeAdapter to its native counterpart. This is needed to start forwarding
-     * keyboard events to WebKit.
-     * @param nativeImeAdapter The pointer to the native ImeAdapter object.
-     */
-    void attach(int nativeImeAdapter) {
-        mNativeImeAdapterAndroid = nativeImeAdapter;
-        if (nativeImeAdapter != 0) {
-            nativeAttachImeAdapter(mNativeImeAdapterAndroid);
-        }
-    }
-
-    /**
-     * Used to check whether the native counterpart of the ImeAdapter has been attached yet.
-     * @return Whether native ImeAdapter has been attached and its pointer is currently nonzero.
-     */
-    boolean isNativeImeAdapterAttached() {
-        return mNativeImeAdapterAndroid != 0;
-    }
-
-    private void showKeyboard() {
-        mIsShowWithoutHideOutstanding = true;
-        mInputMethodManagerWrapper.showSoftInput(mViewEmbedder.getAttachedView(), 0,
-                mViewEmbedder.getNewShowKeyboardReceiver());
-    }
-
-    private void dismissInput(boolean unzoomIfNeeded) {
-        hideKeyboard(unzoomIfNeeded);
-        mViewEmbedder.onDismissInput();
-    }
-
-    private void hideKeyboard(boolean unzoomIfNeeded) {
-        mIsShowWithoutHideOutstanding  = false;
-        View view = mViewEmbedder.getAttachedView();
-        if (mInputMethodManagerWrapper.isActive(view)) {
-            mInputMethodManagerWrapper.hideSoftInputFromWindow(view.getWindowToken(), 0,
-                    unzoomIfNeeded ? mViewEmbedder.getNewShowKeyboardReceiver() : null);
-        }
-    }
-
-    @CalledByNative
-    void detach() {
-        mNativeImeAdapterAndroid = 0;
-        mTextInputType = 0;
-    }
-
-    boolean hasInputType() {
-        return mTextInputType != sTextInputTypeNone;
-    }
-
-    static boolean isTextInputType(int type) {
-        return type != sTextInputTypeNone && !InputDialogContainer.isDialogInputType(type);
-    }
-
-    boolean hasTextInputType() {
-        return isTextInputType(mTextInputType);
-    }
-
-    boolean dispatchKeyEvent(KeyEvent event) {
-        return translateAndSendNativeEvents(event);
-    }
-
-    void commitText() {
-        cancelComposition();
-        if (mNativeImeAdapterAndroid != 0) {
-            nativeCommitText(mNativeImeAdapterAndroid, "");
-        }
-    }
-
-    @SuppressWarnings("unused")
-    @CalledByNative
-    private void cancelComposition() {
-        if (mInputConnection != null) {
-            mInputConnection.restartInput();
-        }
-    }
-
-    @VisibleForTesting
-    boolean checkCompositionQueueAndCallNative(String text, int newCursorPosition,
-            boolean isCommit) {
-        if (mNativeImeAdapterAndroid == 0) return false;
-
-
-        // Committing an empty string finishes the current composition.
-        boolean isFinish = text.isEmpty();
-        if (!isFinish) {
-            mSelectionHandleController.hideAndDisallowAutomaticShowing();
-            mInsertionHandleController.hideAndDisallowAutomaticShowing();
-        }
-        mViewEmbedder.onImeEvent(isFinish);
-        int keyCode = shouldSendKeyEventWithKeyCode(text);
-        long timeStampMs = System.currentTimeMillis();
-
-        if (keyCode != COMPOSITION_KEY_CODE) {
-            sendKeyEventWithKeyCode(keyCode,
-                    KeyEvent.FLAG_SOFT_KEYBOARD | KeyEvent.FLAG_KEEP_TOUCH_MODE);
-        } else {
-            nativeSendSyntheticKeyEvent(mNativeImeAdapterAndroid, sEventTypeRawKeyDown,
-                    timeStampMs, keyCode, 0);
-            if (isCommit) {
-                nativeCommitText(mNativeImeAdapterAndroid, text);
-            } else {
-                nativeSetComposingText(mNativeImeAdapterAndroid, text, newCursorPosition);
-            }
-            nativeSendSyntheticKeyEvent(mNativeImeAdapterAndroid, sEventTypeKeyUp,
-                    timeStampMs, keyCode, 0);
-        }
-
-        return true;
-    }
-
-    private int shouldSendKeyEventWithKeyCode(String text) {
-        if (text.length() != 1) return COMPOSITION_KEY_CODE;
-
-        if (text.equals("\n")) return KeyEvent.KEYCODE_ENTER;
-        else if (text.equals("\t")) return KeyEvent.KEYCODE_TAB;
-        else return COMPOSITION_KEY_CODE;
-    }
-
-    private void sendKeyEventWithKeyCode(int keyCode, int flags) {
-        long eventTime = System.currentTimeMillis();
-        translateAndSendNativeEvents(new KeyEvent(eventTime, eventTime,
-                KeyEvent.ACTION_DOWN, keyCode, 0, 0,
-                KeyCharacterMap.VIRTUAL_KEYBOARD, 0,
-                flags));
-        translateAndSendNativeEvents(new KeyEvent(System.currentTimeMillis(), eventTime,
-                KeyEvent.ACTION_UP, keyCode, 0, 0,
-                KeyCharacterMap.VIRTUAL_KEYBOARD, 0,
-                flags));
-    }
-
-    private boolean translateAndSendNativeEvents(KeyEvent event) {
-        if (mNativeImeAdapterAndroid == 0) return false;
-
-        int action = event.getAction();
-        if (action != KeyEvent.ACTION_DOWN &&
-            action != KeyEvent.ACTION_UP) {
-            // action == KeyEvent.ACTION_MULTIPLE
-            // TODO(bulach): confirm the actual behavior. Apparently:
-            // If event.getKeyCode() == KEYCODE_UNKNOWN, we can send a
-            // composition key down (229) followed by a commit text with the
-            // string from event.getUnicodeChars().
-            // Otherwise, we'd need to send an event with a
-            // WebInputEvent::IsAutoRepeat modifier. We also need to verify when
-            // we receive ACTION_MULTIPLE: we may receive it after an ACTION_DOWN,
-            // and if that's the case, we'll need to review when to send the Char
-            // event.
-            return false;
-        }
-        mViewEmbedder.onImeEvent(false);
-        return nativeSendKeyEvent(mNativeImeAdapterAndroid, event, event.getAction(),
-                getModifiers(event.getMetaState()), event.getEventTime(), event.getKeyCode(),
-                                event.isSystem(), event.getUnicodeChar());
-    }
-
-    private void setInputConnection(AdapterInputConnection inputConnection) {
-        mInputConnection = inputConnection;
-    }
-
-    private static int getModifiers(int metaState) {
-        int modifiers = 0;
-        if ((metaState & KeyEvent.META_SHIFT_ON) != 0) {
-          modifiers |= sModifierShift;
-        }
-        if ((metaState & KeyEvent.META_ALT_ON) != 0) {
-          modifiers |= sModifierAlt;
-        }
-        if ((metaState & KeyEvent.META_CTRL_ON) != 0) {
-          modifiers |= sModifierCtrl;
-        }
-        if ((metaState & KeyEvent.META_CAPS_LOCK_ON) != 0) {
-          modifiers |= sModifierCapsLockOn;
-        }
-        if ((metaState & KeyEvent.META_NUM_LOCK_ON) != 0) {
-          modifiers |= sModifierNumLockOn;
-        }
-        return modifiers;
-    }
-
-    boolean isActive() {
-        return mInputConnection != null && mInputConnection.isActive();
-    }
-
-    private boolean sendSyntheticKeyEvent(
-            int eventType, long timestampMs, int keyCode, int unicodeChar) {
-        if (mNativeImeAdapterAndroid == 0) return false;
-
-        nativeSendSyntheticKeyEvent(
-                mNativeImeAdapterAndroid, eventType, timestampMs, keyCode, unicodeChar);
-        return true;
-    }
-
-    private boolean deleteSurroundingText(int leftLength, int rightLength) {
-        if (mNativeImeAdapterAndroid == 0) return false;
-
-        nativeDeleteSurroundingText(mNativeImeAdapterAndroid, leftLength, rightLength);
-        return true;
-    }
-
-    @VisibleForTesting
-    protected boolean setEditableSelectionOffsets(int start, int end) {
-        if (mNativeImeAdapterAndroid == 0) return false;
-
-        nativeSetEditableSelectionOffsets(mNativeImeAdapterAndroid, start, end);
-        return true;
-    }
-
-    private void batchStateChanged(boolean isBegin) {
-        if (mNativeImeAdapterAndroid == 0) return;
-        nativeImeBatchStateChanged(mNativeImeAdapterAndroid, isBegin);
-    }
-
-    private boolean setComposingRegion(int start, int end) {
-        if (mNativeImeAdapterAndroid == 0) return false;
-
-        nativeSetComposingRegion(mNativeImeAdapterAndroid, start, end);
-        return true;
-    }
-
-    boolean unselect() {
-        if (mNativeImeAdapterAndroid == 0) return false;
-
-        nativeUnselect(mNativeImeAdapterAndroid);
-        return true;
-    }
-
-    boolean selectAll() {
-        if (mNativeImeAdapterAndroid == 0) return false;
-
-        nativeSelectAll(mNativeImeAdapterAndroid);
-        return true;
-    }
-
-    boolean cut() {
-        if (mNativeImeAdapterAndroid == 0) return false;
-
-        nativeCut(mNativeImeAdapterAndroid);
-        return true;
-    }
-
-    boolean copy() {
-        if (mNativeImeAdapterAndroid == 0) return false;
-
-        nativeCopy(mNativeImeAdapterAndroid);
-        return true;
-    }
-
-    boolean paste() {
-        if (mNativeImeAdapterAndroid == 0) return false;
-
-        nativePaste(mNativeImeAdapterAndroid);
-        return true;
-    }
-
-    public static class AdapterInputConnectionFactory {
-        public AdapterInputConnection get(View view, ImeAdapter imeAdapter,
-                EditorInfo outAttrs) {
-            return new AdapterInputConnection(view, imeAdapter, outAttrs);
-        }
-    }
-
-    // This InputConnection is created by ContentView.onCreateInputConnection.
-    // It then adapts android's IME to chrome's RenderWidgetHostView using the
-    // native ImeAdapterAndroid via the outer class ImeAdapter.
-    public static class AdapterInputConnection extends BaseInputConnection {
-        private static final String TAG =
-                "org.chromium.content.browser.ImeAdapter$AdapterInputConnection";
-        private static final boolean DEBUG = false;
-        private final View mInternalView;
-        private final ImeAdapter mImeAdapter;
-
-        private boolean mSingleLine;
-        private int mNumNestedBatchEdits = 0;
-        private boolean mIgnoreTextInputStateUpdates = false;
-
-        /**
-         * Updates the AdapterInputConnection's internal representation of the text
-         * being edited and its selection and composition properties. The resulting
-         * Editable is accessible through the getEditable() method.
-         * If the text has not changed, this also calls updateSelection on the InputMethodManager.
-         * @param text The String contents of the field being edited
-         * @param selectionStart The character offset of the selection start, or the caret
-         * position if there is no selection
-         * @param selectionEnd The character offset of the selection end, or the caret
-         * position if there is no selection
-         * @param compositionStart The character offset of the composition start, or -1
-         * if there is no composition
-         * @param compositionEnd The character offset of the composition end, or -1
-         * if there is no selection
-         */
-        public void setEditableText(String text, int selectionStart, int selectionEnd,
-                int compositionStart, int compositionEnd) {
-            if (DEBUG) {
-                Log.w(TAG, "setEditableText [" + text + "] [" + selectionStart + " " + selectionEnd
-                        + "] [" + compositionStart + " " + compositionEnd + "]");
-            }
-            Editable editable = getEditable();
-
-            int prevSelectionStart = Selection.getSelectionStart(editable);
-            int prevSelectionEnd = Selection.getSelectionEnd(editable);
-            int prevCompositionStart = getComposingSpanStart(editable);
-            int prevCompositionEnd = getComposingSpanEnd(editable);
-            String prevText = editable.toString();
-
-            selectionStart = Math.min(selectionStart, text.length());
-            selectionEnd = Math.min(selectionEnd, text.length());
-            compositionStart = Math.min(compositionStart, text.length());
-            compositionEnd = Math.min(compositionEnd, text.length());
-
-            boolean textUnchanged = prevText.equals(text);
-
-            if (!textUnchanged) {
-                editable.replace(0, editable.length(), text);
-            }
-
-            if (prevSelectionStart == selectionStart && prevSelectionEnd == selectionEnd
-                    && prevCompositionStart == compositionStart
-                    && prevCompositionEnd == compositionEnd) {
-                // Nothing has changed; don't need to do anything
-                return;
-            }
-
-            Selection.setSelection(editable, selectionStart, selectionEnd);
-            super.setComposingRegion(compositionStart, compositionEnd);
-
-            if (mIgnoreTextInputStateUpdates) return;
-            updateSelection(selectionStart, selectionEnd, compositionStart, compositionEnd);
-        }
-
-        @VisibleForTesting
-        protected void updateSelection(
-                int selectionStart, int selectionEnd,
-                int compositionStart, int compositionEnd) {
-            if (DEBUG) {
-                Log.w(TAG, "updateSelection [" + selectionStart + " " + selectionEnd + "] ["
-                        + compositionStart + " " + compositionEnd + "]");
-            }
-            // updateSelection should
-            // be called every time the selection or composition changes if it happens not
-            // within a batch edit, or at the end of each top level batch edit.
-            getInputMethodManagerWrapper().updateSelection(mInternalView,
-                    selectionStart, selectionEnd, compositionStart, compositionEnd);
-        }
-
-        @Override
-        public boolean setComposingText(CharSequence text, int newCursorPosition) {
-            if (DEBUG) Log.w(TAG, "setComposingText [" + text + "] [" + newCursorPosition + "]");
-            super.setComposingText(text, newCursorPosition);
-            return mImeAdapter.checkCompositionQueueAndCallNative(text.toString(),
-                    newCursorPosition, false);
-        }
-
-        @Override
-        public boolean commitText(CharSequence text, int newCursorPosition) {
-            if (DEBUG) Log.w(TAG, "commitText [" + text + "] [" + newCursorPosition + "]");
-            super.commitText(text, newCursorPosition);
-            return mImeAdapter.checkCompositionQueueAndCallNative(text.toString(),
-                    newCursorPosition, text.length() > 0);
-        }
-
-        @Override
-        public boolean performEditorAction(int actionCode) {
-            if (DEBUG) Log.w(TAG, "performEditorAction [" + actionCode + "]");
-            if (actionCode == EditorInfo.IME_ACTION_NEXT) {
-                restartInput();
-                // Send TAB key event
-                long timeStampMs = System.currentTimeMillis();
-                mImeAdapter.sendSyntheticKeyEvent(
-                        sEventTypeRawKeyDown, timeStampMs, KeyEvent.KEYCODE_TAB, 0);
-            } else {
-                mImeAdapter.sendKeyEventWithKeyCode(KeyEvent.KEYCODE_ENTER,
-                        KeyEvent.FLAG_SOFT_KEYBOARD | KeyEvent.FLAG_KEEP_TOUCH_MODE
-                        | KeyEvent.FLAG_EDITOR_ACTION);
-            }
-            return true;
-        }
-
-        @Override
-        public boolean performContextMenuAction(int id) {
-            if (DEBUG) Log.w(TAG, "performContextMenuAction [" + id + "]");
-            switch (id) {
-                case android.R.id.selectAll:
-                    return mImeAdapter.selectAll();
-                case android.R.id.cut:
-                    return mImeAdapter.cut();
-                case android.R.id.copy:
-                    return mImeAdapter.copy();
-                case android.R.id.paste:
-                    return mImeAdapter.paste();
-                default:
-                    return false;
-            }
-        }
-
-        @Override
-        public ExtractedText getExtractedText(ExtractedTextRequest request, int flags) {
-            if (DEBUG) Log.w(TAG, "getExtractedText");
-            ExtractedText et = new ExtractedText();
-            Editable editable = getEditable();
-            et.text = editable.toString();
-            et.partialEndOffset = editable.length();
-            et.selectionStart = Selection.getSelectionStart(editable);
-            et.selectionEnd = Selection.getSelectionEnd(editable);
-            et.flags = mSingleLine ? ExtractedText.FLAG_SINGLE_LINE : 0;
-            return et;
-        }
-
-        @Override
-        public boolean beginBatchEdit() {
-            if (DEBUG) Log.w(TAG, "beginBatchEdit [" + (mNumNestedBatchEdits == 0) + "]");
-            if (mNumNestedBatchEdits == 0) mImeAdapter.batchStateChanged(true);
-
-            mNumNestedBatchEdits++;
-            return false;
-        }
-
-        @Override
-        public boolean endBatchEdit() {
-            if (mNumNestedBatchEdits == 0) return false;
-
-            --mNumNestedBatchEdits;
-            if (DEBUG) Log.w(TAG, "endBatchEdit [" + (mNumNestedBatchEdits == 0) + "]");
-            if (mNumNestedBatchEdits == 0) mImeAdapter.batchStateChanged(false);
-            return false;
-        }
-
-        @Override
-        public boolean deleteSurroundingText(int leftLength, int rightLength) {
-            if (DEBUG) {
-                Log.w(TAG, "deleteSurroundingText [" + leftLength + " " + rightLength + "]");
-            }
-            if (!super.deleteSurroundingText(leftLength, rightLength)) {
-                return false;
-            }
-            return mImeAdapter.deleteSurroundingText(leftLength, rightLength);
-        }
-
-        @Override
-        public boolean sendKeyEvent(KeyEvent event) {
-            if (DEBUG) Log.w(TAG, "sendKeyEvent [" + event.getAction() + "]");
-            mImeAdapter.mSelectionHandleController.hideAndDisallowAutomaticShowing();
-            mImeAdapter.mInsertionHandleController.hideAndDisallowAutomaticShowing();
-
-            // If this is a key-up, and backspace/del or if the key has a character representation,
-            // need to update the underlying Editable (i.e. the local representation of the text
-            // being edited).
-            if (event.getAction() == KeyEvent.ACTION_UP) {
-                if (event.getKeyCode() == KeyEvent.KEYCODE_DEL) {
-                    super.deleteSurroundingText(1, 0);
-                } else if (event.getKeyCode() == KeyEvent.KEYCODE_FORWARD_DEL) {
-                    super.deleteSurroundingText(0, 1);
-                } else {
-                    int unicodeChar = event.getUnicodeChar();
-                    if (unicodeChar != 0) {
-                        Editable editable = getEditable();
-                        int selectionStart = Selection.getSelectionStart(editable);
-                        int selectionEnd = Selection.getSelectionEnd(editable);
-                        if (selectionStart > selectionEnd) {
-                            int temp = selectionStart;
-                            selectionStart = selectionEnd;
-                            selectionEnd = temp;
-                        }
-                        editable.replace(selectionStart, selectionEnd,
-                                Character.toString((char)unicodeChar));
-                    }
-                }
-            }
-            mImeAdapter.translateAndSendNativeEvents(event);
-            return true;
-        }
-
-        @Override
-        public boolean finishComposingText() {
-            if (DEBUG) Log.w(TAG, "finishComposingText");
-            Editable editable = getEditable();
-            if (getComposingSpanStart(editable) == getComposingSpanEnd(editable)) {
-                return true;
-            }
-            super.finishComposingText();
-            return mImeAdapter.checkCompositionQueueAndCallNative("", 0, true);
-        }
-
-        @Override
-        public boolean setSelection(int start, int end) {
-            if (DEBUG) Log.w(TAG, "setSelection");
-            if (start < 0 || end < 0) return true;
-            super.setSelection(start, end);
-            return mImeAdapter.setEditableSelectionOffsets(start, end);
-        }
-
-        /**
-         * Informs the InputMethodManager and InputMethodSession (i.e. the IME) that the text
-         * state is no longer what the IME has and that it needs to be updated.
-         */
-        void restartInput() {
-            if (DEBUG) Log.w(TAG, "restartInput");
-            getInputMethodManagerWrapper().restartInput(mInternalView);
-            mIgnoreTextInputStateUpdates = false;
-            mNumNestedBatchEdits = 0;
-        }
-
-        @Override
-        public boolean setComposingRegion(int start, int end) {
-            if (DEBUG) Log.w(TAG, "setComposingRegion [" + start + " " + end + "]");
-            int a = Math.min(start, end);
-            int b = Math.max(start, end);
-            super.setComposingRegion(a, b);
-            return mImeAdapter.setComposingRegion(a, b);
-        }
-
-        boolean isActive() {
-            return getInputMethodManagerWrapper().isActive(mInternalView);
-        }
-
-        void setIgnoreTextInputStateUpdates(boolean shouldIgnore) {
-            mIgnoreTextInputStateUpdates = shouldIgnore;
-            if (shouldIgnore) return;
-
-            Editable editable = getEditable();
-            updateSelection(Selection.getSelectionStart(editable),
-                    Selection.getSelectionEnd(editable),
-                    getComposingSpanStart(editable),
-                    getComposingSpanEnd(editable));
-        }
-
-        @VisibleForTesting
-        protected boolean isIgnoringTextInputStateUpdates() {
-            return mIgnoreTextInputStateUpdates;
-        }
-
-        private InputMethodManagerWrapper getInputMethodManagerWrapper() {
-            return mImeAdapter.getInputMethodManagerWrapper();
-        }
-
-        @VisibleForTesting
-        protected AdapterInputConnection(View view, ImeAdapter imeAdapter, EditorInfo outAttrs) {
-            super(view, true);
-            mInternalView = view;
-            mImeAdapter = imeAdapter;
-            mImeAdapter.setInputConnection(this);
-            mSingleLine = true;
-            outAttrs.imeOptions = EditorInfo.IME_FLAG_NO_FULLSCREEN;
-            outAttrs.inputType = EditorInfo.TYPE_CLASS_TEXT
-                    | EditorInfo.TYPE_TEXT_VARIATION_WEB_EDIT_TEXT;
-            if (imeAdapter.mTextInputType == ImeAdapter.sTextInputTypeText) {
-                // Normal text field
-                outAttrs.imeOptions |= EditorInfo.IME_ACTION_GO;
-            } else if (imeAdapter.mTextInputType == ImeAdapter.sTextInputTypeTextArea ||
-                    imeAdapter.mTextInputType == ImeAdapter.sTextInputTypeContentEditable) {
-                // TextArea or contenteditable.
-                outAttrs.inputType |= EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE
-                        | EditorInfo.TYPE_TEXT_FLAG_CAP_SENTENCES
-                        | EditorInfo.TYPE_TEXT_FLAG_AUTO_CORRECT;
-                outAttrs.imeOptions |= EditorInfo.IME_ACTION_NONE;
-                mSingleLine = false;
-            } else if (imeAdapter.mTextInputType == ImeAdapter.sTextInputTypePassword) {
-                // Password
-                outAttrs.inputType = InputType.TYPE_CLASS_TEXT
-                        | InputType.TYPE_TEXT_VARIATION_WEB_PASSWORD;
-                outAttrs.imeOptions |= EditorInfo.IME_ACTION_GO;
-            } else if (imeAdapter.mTextInputType == ImeAdapter.sTextInputTypeSearch) {
-                // Search
-                outAttrs.imeOptions |= EditorInfo.IME_ACTION_SEARCH;
-            } else if (imeAdapter.mTextInputType == ImeAdapter.sTextInputTypeUrl) {
-                // Url
-                // TYPE_TEXT_VARIATION_URI prevents Tab key from showing, so
-                // exclude it for now.
-                outAttrs.imeOptions |= EditorInfo.IME_ACTION_GO;
-            } else if (imeAdapter.mTextInputType == ImeAdapter.sTextInputTypeEmail) {
-                // Email
-                outAttrs.inputType = InputType.TYPE_CLASS_TEXT
-                        | InputType.TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS;
-                outAttrs.imeOptions |= EditorInfo.IME_ACTION_GO;
-            } else if (imeAdapter.mTextInputType == ImeAdapter.sTextInputTypeTel) {
-                // Telephone
-                // Number and telephone do not have both a Tab key and an
-                // action in default OSK, so set the action to NEXT
-                outAttrs.inputType = InputType.TYPE_CLASS_PHONE;
-                outAttrs.imeOptions |= EditorInfo.IME_ACTION_NEXT;
-            } else if (imeAdapter.mTextInputType == ImeAdapter.sTextInputTypeNumber) {
-                // Number
-                outAttrs.inputType = InputType.TYPE_CLASS_NUMBER
-                        | InputType.TYPE_NUMBER_VARIATION_NORMAL;
-                outAttrs.imeOptions |= EditorInfo.IME_ACTION_NEXT;
-            }
-
-            Editable editable = getEditable();
-            int selectionStart = Selection.getSelectionStart(editable);
-            int selectionEnd = Selection.getSelectionEnd(editable);
-            if (selectionStart < 0 || selectionEnd < 0) {
-                selectionStart = editable.length();
-                selectionEnd = selectionStart;
-            }
-            outAttrs.initialSelStart = selectionStart;
-            outAttrs.initialSelEnd = selectionEnd;
-        }
-    }
-
-    private native boolean nativeSendSyntheticKeyEvent(int nativeImeAdapterAndroid,
-            int eventType, long timestampMs, int keyCode, int unicodeChar);
-
-    private native boolean nativeSendKeyEvent(int nativeImeAdapterAndroid, KeyEvent event,
-            int action, int modifiers, long timestampMs, int keyCode, boolean isSystemKey,
-            int unicodeChar);
-
-    private native void nativeSetComposingText(int nativeImeAdapterAndroid, String text,
-            int newCursorPosition);
-
-    private native void nativeCommitText(int nativeImeAdapterAndroid, String text);
-
-    private native void nativeAttachImeAdapter(int nativeImeAdapterAndroid);
-
-    private native void nativeSetEditableSelectionOffsets(int nativeImeAdapterAndroid,
-            int start, int end);
-
-    private native void nativeSetComposingRegion(int nativeImeAdapterAndroid, int start, int end);
-
-    private native void nativeDeleteSurroundingText(int nativeImeAdapterAndroid,
-            int before, int after);
-
-    private native void nativeImeBatchStateChanged(int nativeImeAdapterAndroid, boolean isBegin);
-
-    private native void nativeUnselect(int nativeImeAdapterAndroid);
-    private native void nativeSelectAll(int nativeImeAdapterAndroid);
-    private native void nativeCut(int nativeImeAdapterAndroid);
-    private native void nativeCopy(int nativeImeAdapterAndroid);
-    private native void nativePaste(int nativeImeAdapterAndroid);
-}
diff --git a/content/public/android/java/src/org/chromium/content/browser/JellyBeanContentView.java b/content/public/android/java/src/org/chromium/content/browser/JellyBeanContentView.java
index 1bc2fae..80b8ccf 100644
--- a/content/public/android/java/src/org/chromium/content/browser/JellyBeanContentView.java
+++ b/content/public/android/java/src/org/chromium/content/browser/JellyBeanContentView.java
@@ -10,15 +10,15 @@
 import android.view.View;
 import android.view.accessibility.AccessibilityNodeInfo;
 
-import org.chromium.ui.gfx.NativeWindow;
+import org.chromium.ui.WindowAndroid;
 
 /**
  * A version of {@link ContentView} that supports JellyBean features.
  */
 class JellyBeanContentView extends ContentView {
-    JellyBeanContentView(Context context, int nativeWebContents, NativeWindow nativeWindow,
+    JellyBeanContentView(Context context, int nativeWebContents, WindowAndroid windowAndroid,
             AttributeSet attrs, int defStyle, int personality) {
-        super(context, nativeWebContents, nativeWindow, attrs, defStyle, personality);
+        super(context, nativeWebContents, windowAndroid, attrs, defStyle, personality);
     }
 
     @Override
diff --git a/content/public/android/java/src/org/chromium/content/browser/LongPressDetector.java b/content/public/android/java/src/org/chromium/content/browser/LongPressDetector.java
index 5bd73ad..d46d485 100644
--- a/content/public/android/java/src/org/chromium/content/browser/LongPressDetector.java
+++ b/content/public/android/java/src/org/chromium/content/browser/LongPressDetector.java
@@ -7,7 +7,6 @@
 import android.content.Context;
 import android.os.Handler;
 import android.os.Message;
-import android.util.Pair;
 import android.view.MotionEvent;
 import android.view.ViewConfiguration;
 
diff --git a/content/public/android/java/src/org/chromium/content/browser/MediaResourceGetter.java b/content/public/android/java/src/org/chromium/content/browser/MediaResourceGetter.java
new file mode 100644
index 0000000..5d0de5a
--- /dev/null
+++ b/content/public/android/java/src/org/chromium/content/browser/MediaResourceGetter.java
@@ -0,0 +1,117 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.content.browser;
+
+import android.content.Context;
+import android.media.MediaMetadataRetriever;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+import android.net.Uri;
+import android.text.TextUtils;
+import android.util.Log;
+
+import org.chromium.base.CalledByNative;
+import org.chromium.base.JNINamespace;
+import org.chromium.base.PathUtils;
+
+import java.io.File;
+import java.util.HashMap;
+
+/**
+ * Java counterpart of android MediaResourceGetter.
+ */
+@JNINamespace("content")
+class MediaResourceGetter {
+
+    private static final String TAG = "MediaResourceGetter";
+
+    private static class MediaMetadata {
+        private final int mDurationInMilliseconds;
+        private final int mWidth;
+        private final int mHeight;
+        private final boolean mSuccess;
+
+        private MediaMetadata(int durationInMilliseconds, int width, int height, boolean success) {
+            mDurationInMilliseconds = durationInMilliseconds;
+            mWidth = width;
+            mHeight = height;
+            mSuccess = success;
+        }
+
+        @CalledByNative("MediaMetadata")
+        private int getDurationInMilliseconds() { return mDurationInMilliseconds; }
+
+        @CalledByNative("MediaMetadata")
+        private int getWidth() { return mWidth; }
+
+        @CalledByNative("MediaMetadata")
+        private int getHeight() { return mHeight; }
+
+        @CalledByNative("MediaMetadata")
+        private boolean isSuccess() { return mSuccess; }
+    }
+
+    @CalledByNative
+    private static MediaMetadata extractMediaMetadata(Context context, String url, String cookies) {
+        int durationInMilliseconds = 0;
+        int width = 0;
+        int height = 0;
+        boolean success = false;
+        // TODO(qinmin): use ConnectionTypeObserver to listen to the network type change.
+        ConnectivityManager mConnectivityManager =
+                (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
+        if (mConnectivityManager != null) {
+            NetworkInfo info = mConnectivityManager.getActiveNetworkInfo();
+            if (info == null) {
+                return new MediaMetadata(durationInMilliseconds, width, height, success);
+            }
+            switch (info.getType()) {
+                case ConnectivityManager.TYPE_ETHERNET:
+                case ConnectivityManager.TYPE_WIFI:
+                    break;
+                case ConnectivityManager.TYPE_WIMAX:
+                case ConnectivityManager.TYPE_MOBILE:
+                default:
+                    return new MediaMetadata(durationInMilliseconds, width, height, success);
+            }
+        }
+
+        MediaMetadataRetriever retriever = new MediaMetadataRetriever();
+        try {
+            Uri uri = Uri.parse(url);
+            String scheme = uri.getScheme();
+            if (scheme == null || scheme.equals("file")) {
+                File file = new File(uri.getPath());
+                String path = file.getAbsolutePath();
+                if (file.exists() && (path.startsWith("/mnt/sdcard/") ||
+                        path.startsWith("/sdcard/") ||
+                        path.startsWith(PathUtils.getExternalStorageDirectory()))) {
+                    retriever.setDataSource(path);
+                } else {
+                    Log.e(TAG, "Unable to read file: " + url);
+                    return new MediaMetadata(durationInMilliseconds, width, height, success);
+                }
+            } else {
+                HashMap<String, String> headersMap = new HashMap<String, String>();
+                if (!TextUtils.isEmpty(cookies)) {
+                    headersMap.put("Cookie", cookies);
+                }
+                retriever.setDataSource(url, headersMap);
+            }
+            durationInMilliseconds = Integer.parseInt(
+                    retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION));
+            width = Integer.parseInt(
+                    retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH));
+            height = Integer.parseInt(
+                    retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT));
+            success = true;
+        } catch (IllegalArgumentException e) {
+            Log.e(TAG, "Invalid url: " + e);
+        } catch (RuntimeException e) {
+            Log.e(TAG, "Invalid url: " + e);
+        }
+        return new MediaMetadata(durationInMilliseconds, width, height, success);
+    }
+}
diff --git a/content/public/android/java/src/org/chromium/content/browser/PageInfo.java b/content/public/android/java/src/org/chromium/content/browser/PageInfo.java
new file mode 100644
index 0000000..1a80b20
--- /dev/null
+++ b/content/public/android/java/src/org/chromium/content/browser/PageInfo.java
@@ -0,0 +1,50 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.content.browser;
+
+import android.graphics.Bitmap;
+import android.view.View;
+
+/**
+ * A minimal interface for a View to implement to be shown in a Tab. The main implementation of
+ * this is ContentView but other Views can also implement this, enabling them to be shown in a Tab
+ * as well.
+ */
+public interface PageInfo {
+    /**
+     * @return The URL of the page.
+     */
+    String getUrl();
+
+    /**
+     * @return The title of the page.
+     */
+    String getTitle();
+
+    /**
+     * @return True, if the view is in a suitable state for a snapshot.
+     */
+    boolean isReadyForSnapshot();
+
+    /**
+     * @return An unscaled screenshot of the page.
+     */
+    Bitmap getBitmap();
+
+    /**
+     * @return A screenshot of the page scaled to the specified size.
+     */
+    Bitmap getBitmap(int width, int height);
+
+    /**
+     * @return The background color of the page.
+     */
+    int getBackgroundColor();
+
+    /**
+     * @return The View to display the page. This is always non-null.
+     */
+    View getView();
+}
diff --git a/content/public/android/java/src/org/chromium/content/browser/RenderCoordinates.java b/content/public/android/java/src/org/chromium/content/browser/RenderCoordinates.java
index 1506fab..be362fb 100644
--- a/content/public/android/java/src/org/chromium/content/browser/RenderCoordinates.java
+++ b/content/public/android/java/src/org/chromium/content/browser/RenderCoordinates.java
@@ -33,6 +33,8 @@
     // Cached device density.
     private float mDeviceScaleFactor;
 
+    private float mContentOffsetYPix;
+
     // Internally-visible set of update methods (used by ContentViewCore).
     void reset() {
         mScrollXCss = mScrollYCss = 0;
@@ -52,12 +54,14 @@
             float scrollXCss, float scrollYCss,
             float contentWidthCss, float contentHeightCss,
             float viewportWidthCss, float viewportHeightCss,
-            float pageScaleFactor, float minPageScaleFactor, float maxPageScaleFactor) {
+            float pageScaleFactor, float minPageScaleFactor, float maxPageScaleFactor,
+            float contentOffsetYPix) {
         mScrollXCss = scrollXCss;
         mScrollYCss = scrollYCss;
         mPageScaleFactor = pageScaleFactor;
         mMinPageScaleFactor = minPageScaleFactor;
         mMaxPageScaleFactor = maxPageScaleFactor;
+        mContentOffsetYPix = contentOffsetYPix;
 
         updateContentSizeCss(contentWidthCss, contentHeightCss);
         mLastFrameViewportWidthCss = viewportWidthCss;
@@ -102,7 +106,7 @@
         /**
          * @return Physical (screen) Y coordinate of the point.
          */
-        public float getYPix() { return getYLocalDip() * mDeviceScaleFactor; }
+        public float getYPix() { return getYLocalDip() * mDeviceScaleFactor + mContentOffsetYPix; }
 
         /**
          * Sets the point to the given absolute CSS (document) coordinates.
@@ -127,7 +131,7 @@
         public void setScreen(float xPix, float yPix) {
             setLocalDip(xPix / mDeviceScaleFactor, yPix / mDeviceScaleFactor);
         }
-}
+    }
 
     /**
      * @return A helper to convert a point between between absolute CSS and local DIP spaces.
@@ -235,6 +239,13 @@
     }
 
     /**
+     * @return The Physical on-screen Y offset amount below the top controls.
+     */
+    public float getContentOffsetYPix() {
+        return mContentOffsetYPix;
+    }
+
+    /**
      * @return Current page scale factor (maps CSS pixels to DIP pixels).
      */
     public float getPageScaleFactor() { return mPageScaleFactor; }
diff --git a/content/public/android/java/src/org/chromium/content/browser/ResourceExtractor.java b/content/public/android/java/src/org/chromium/content/browser/ResourceExtractor.java
index c9f3c31..2b650ce 100644
--- a/content/public/android/java/src/org/chromium/content/browser/ResourceExtractor.java
+++ b/content/public/android/java/src/org/chromium/content/browser/ResourceExtractor.java
@@ -13,8 +13,8 @@
 import android.preference.PreferenceManager;
 import android.util.Log;
 
-import org.chromium.base.LocaleUtils;
 import org.chromium.base.PathUtils;
+import org.chromium.ui.LocalizationUtils;
 
 import java.io.File;
 import java.io.FileOutputStream;
@@ -70,7 +70,7 @@
             SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(mContext);
             HashSet<String> filenames = (HashSet<String>) prefs.getStringSet(
                     PAK_FILENAMES, new HashSet<String>());
-            String currentLocale = LocaleUtils.getDefaultLocale();
+            String currentLocale = LocalizationUtils.getDefaultLocale();
             String currentLanguage = currentLocale.split("-", 2)[0];
 
             if (prefs.getString(LAST_LANGUAGE, "").equals(currentLanguage)
diff --git a/content/public/android/java/src/org/chromium/content/browser/SnapScrollController.java b/content/public/android/java/src/org/chromium/content/browser/SnapScrollController.java
index 68e1873..b457bef 100644
--- a/content/public/android/java/src/org/chromium/content/browser/SnapScrollController.java
+++ b/content/public/android/java/src/org/chromium/content/browser/SnapScrollController.java
@@ -4,6 +4,8 @@
 
 package org.chromium.content.browser;
 
+import android.content.Context;
+import android.util.DisplayMetrics;
 import android.util.Log;
 import android.view.MotionEvent;
 
@@ -16,8 +18,8 @@
     private static final int SNAP_HORIZ = 1;
     private static final int SNAP_VERT = 2;
     private static final int SNAP_BOUND = 16;
-    private static float CHANNEL_DISTANCE = 16f;
 
+    private float mChannelDistance = 16f;
     private int mSnapScrollMode = SNAP_NONE;
     private int mFirstTouchX = -1;
     private int mFirstTouchY = -1;
@@ -25,7 +27,8 @@
     private float mDistanceY = 0;
     private ZoomManager mZoomManager;
 
-    SnapScrollController(ZoomManager zoomManager) {
+    SnapScrollController(Context context, ZoomManager zoomManager) {
+        calculateChannelDistance(context);
         mZoomManager = zoomManager;
     }
 
@@ -40,16 +43,16 @@
             mDistanceX += Math.abs(distanceX);
             mDistanceY += Math.abs(distanceY);
             if (mSnapScrollMode == SNAP_HORIZ) {
-                if (mDistanceY > CHANNEL_DISTANCE) {
+                if (mDistanceY > mChannelDistance) {
                     mSnapScrollMode = SNAP_NONE;
-                } else if (mDistanceX > CHANNEL_DISTANCE) {
+                } else if (mDistanceX > mChannelDistance) {
                     mDistanceX = 0;
                     mDistanceY = 0;
                 }
             } else {
-                if (mDistanceX > CHANNEL_DISTANCE) {
+                if (mDistanceX > mChannelDistance) {
                     mSnapScrollMode = SNAP_NONE;
-                } else if (mDistanceY > CHANNEL_DISTANCE) {
+                } else if (mDistanceY > mChannelDistance) {
                     mDistanceX = 0;
                     mDistanceY = 0;
                 }
@@ -98,6 +101,24 @@
         }
     }
 
+    private void calculateChannelDistance(Context context) {
+        // The channel distance is adjusted for density and screen size.
+        final DisplayMetrics metrics = context.getResources().getDisplayMetrics();
+        final double screenSize = Math.hypot((double) metrics.widthPixels / metrics.densityDpi,
+                (double) metrics.heightPixels / metrics.densityDpi);
+        if (screenSize < 3.0) {
+            mChannelDistance = 16f;
+        } else if (screenSize < 5.0) {
+            mChannelDistance = 22f;
+        } else if (screenSize < 7.0) {
+            mChannelDistance = 28f;
+        } else {
+            mChannelDistance = 34f;
+        }
+        mChannelDistance = mChannelDistance * metrics.density;
+        if (mChannelDistance < 16f) mChannelDistance = 16f;
+    }
+
     /**
      * Resets the snap scroll mode to default.
      */
diff --git a/content/public/android/java/src/org/chromium/content/browser/VSyncManager.java b/content/public/android/java/src/org/chromium/content/browser/VSyncManager.java
new file mode 100644
index 0000000..438d7c7
--- /dev/null
+++ b/content/public/android/java/src/org/chromium/content/browser/VSyncManager.java
@@ -0,0 +1,36 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.content.browser;
+
+public abstract class VSyncManager {
+    /**
+     * Interface for requesting notification of the display vsync signal. The provider will call
+     * Listener.onVSync() to notify about vsync. The number of registrations and unregistrations of
+     * a given listener must be balanced.
+     */
+    public static interface Provider {
+        void registerVSyncListener(Listener listener);
+        void unregisterVSyncListener(Listener listener);
+    }
+
+    /**
+     * Interface for receiving vsync notifications and information about the display refresh
+     * interval.
+     */
+    public static interface Listener {
+        /**
+         * Notification of a vsync event.
+         * @param frameTimeMicros The latest vsync frame time in microseconds.
+         */
+        void onVSync(long frameTimeMicros);
+
+        /**
+         * Update with the latest vsync parameters.
+         * @param tickTimeMicros The latest vsync tick time in microseconds.
+         * @param intervalMicros The vsync interval in microseconds.
+         */
+        void updateVSync(long tickTimeMicros, long intervalMicros);
+    }
+}
diff --git a/content/public/android/java/src/org/chromium/content/browser/accessibility/AccessibilityInjector.java b/content/public/android/java/src/org/chromium/content/browser/accessibility/AccessibilityInjector.java
index d877798..db4b4d1 100644
--- a/content/public/android/java/src/org/chromium/content/browser/accessibility/AccessibilityInjector.java
+++ b/content/public/android/java/src/org/chromium/content/browser/accessibility/AccessibilityInjector.java
@@ -171,16 +171,23 @@
      * Checks whether or not touch to explore is enabled on the system.
      */
     public boolean accessibilityIsAvailable() {
-        // Need to make sure we actually have a service running that requires injecting
-        // this script.
-        List<AccessibilityServiceInfo> services =
-                getAccessibilityManager().getEnabledAccessibilityServiceList(
-                        FEEDBACK_BRAILLE | AccessibilityServiceInfo.FEEDBACK_SPOKEN);
+        if (!getAccessibilityManager().isEnabled() ||
+                mContentViewCore.getContentSettings() == null ||
+                !mContentViewCore.getContentSettings().getJavaScriptEnabled()) {
+            return false;
+        }
 
-        return getAccessibilityManager().isEnabled() &&
-                mContentViewCore.getContentSettings() != null &&
-                mContentViewCore.getContentSettings().getJavaScriptEnabled() &&
-                services.size() > 0;
+        try {
+            // Check that there is actually a service running that requires injecting this script.
+            List<AccessibilityServiceInfo> services =
+                    getAccessibilityManager().getEnabledAccessibilityServiceList(
+                            FEEDBACK_BRAILLE | AccessibilityServiceInfo.FEEDBACK_SPOKEN);
+            return services.size() > 0;
+        } catch (NullPointerException e) {
+            // getEnabledAccessibilityServiceList() can throw an NPE due to a bad
+            // AccessibilityService.
+            return false;
+        }
     }
 
     /**
diff --git a/content/public/android/java/src/org/chromium/content/browser/accessibility/JellyBeanAccessibilityInjector.java b/content/public/android/java/src/org/chromium/content/browser/accessibility/JellyBeanAccessibilityInjector.java
index 0df4a20..4dc2736 100644
--- a/content/public/android/java/src/org/chromium/content/browser/accessibility/JellyBeanAccessibilityInjector.java
+++ b/content/public/android/java/src/org/chromium/content/browser/accessibility/JellyBeanAccessibilityInjector.java
@@ -149,7 +149,15 @@
 
     private static class CallbackHandler {
         private static final String JAVASCRIPT_ACTION_TEMPLATE =
-                "(function() { %s.onResult(%d, %s); })()";
+                "(function() {" +
+                "  retVal = false;" +
+                "  try {" +
+                "    retVal = %s;" +
+                "  } catch (e) {" +
+                "    retVal = false;" +
+                "  }" +
+                "  %s.onResult(%d, retVal);" +
+                "})()";
 
         // Time in milliseconds to wait for a result before failing.
         private static final long RESULT_TIMEOUT = 5000;
@@ -174,8 +182,8 @@
          */
         private boolean performAction(ContentViewCore contentView, String code) {
             final int resultId = mResultIdCounter.getAndIncrement();
-            final String js = String.format(JAVASCRIPT_ACTION_TEMPLATE, mInterfaceName, resultId,
-                    code);
+            final String js = String.format(JAVASCRIPT_ACTION_TEMPLATE, code, mInterfaceName,
+                    resultId);
             contentView.evaluateJavaScript(js, null);
 
             return getResultAndClear(resultId);
diff --git a/content/public/android/java/src/org/chromium/content/browser/input/AdapterInputConnection.java b/content/public/android/java/src/org/chromium/content/browser/input/AdapterInputConnection.java
new file mode 100644
index 0000000..48cc4fe
--- /dev/null
+++ b/content/public/android/java/src/org/chromium/content/browser/input/AdapterInputConnection.java
@@ -0,0 +1,429 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.content.browser.input;
+
+import com.google.common.annotations.VisibleForTesting;
+
+import android.text.Editable;
+import android.text.InputType;
+import android.text.Selection;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.View;
+import android.view.inputmethod.BaseInputConnection;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.ExtractedText;
+import android.view.inputmethod.ExtractedTextRequest;
+
+/**
+ * InputConnection is created by ContentView.onCreateInputConnection.
+ * It then adapts android's IME to chrome's RenderWidgetHostView using the
+ * native ImeAdapterAndroid via the class ImeAdapter.
+ */
+public class AdapterInputConnection extends BaseInputConnection {
+    private static final String TAG =
+            "org.chromium.content.browser.input.AdapterInputConnection";
+    private static final boolean DEBUG = false;
+    /**
+     * Selection value should be -1 if not known. See EditorInfo.java for details.
+     */
+    public static final int INVALID_SELECTION = -1;
+    public static final int INVALID_COMPOSITION = -1;
+
+    private final View mInternalView;
+    private final ImeAdapter mImeAdapter;
+
+    private boolean mSingleLine;
+    private int mNumNestedBatchEdits = 0;
+    private boolean mIgnoreTextInputStateUpdates = false;
+
+    private int mLastUpdateSelectionStart = INVALID_SELECTION;
+    private int mLastUpdateSelectionEnd = INVALID_SELECTION;
+    private int mLastUpdateCompositionStart = INVALID_COMPOSITION;
+    private int mLastUpdateCompositionEnd = INVALID_COMPOSITION;
+
+    @VisibleForTesting
+    AdapterInputConnection(View view, ImeAdapter imeAdapter, EditorInfo outAttrs) {
+        super(view, true);
+        mInternalView = view;
+        mImeAdapter = imeAdapter;
+        mImeAdapter.setInputConnection(this);
+        mSingleLine = true;
+        outAttrs.imeOptions = EditorInfo.IME_FLAG_NO_FULLSCREEN;
+        outAttrs.inputType = EditorInfo.TYPE_CLASS_TEXT
+                | EditorInfo.TYPE_TEXT_VARIATION_WEB_EDIT_TEXT;
+
+        if (imeAdapter.getTextInputType() == ImeAdapter.sTextInputTypeText) {
+            // Normal text field
+            outAttrs.imeOptions |= EditorInfo.IME_ACTION_GO;
+        } else if (imeAdapter.getTextInputType() == ImeAdapter.sTextInputTypeTextArea ||
+                imeAdapter.getTextInputType() == ImeAdapter.sTextInputTypeContentEditable) {
+            // TextArea or contenteditable.
+            outAttrs.inputType |= EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE
+                    | EditorInfo.TYPE_TEXT_FLAG_CAP_SENTENCES
+                    | EditorInfo.TYPE_TEXT_FLAG_AUTO_CORRECT;
+            outAttrs.imeOptions |= EditorInfo.IME_ACTION_NONE;
+            mSingleLine = false;
+        } else if (imeAdapter.getTextInputType() == ImeAdapter.sTextInputTypePassword) {
+            // Password
+            outAttrs.inputType = InputType.TYPE_CLASS_TEXT
+                    | InputType.TYPE_TEXT_VARIATION_WEB_PASSWORD;
+            outAttrs.imeOptions |= EditorInfo.IME_ACTION_GO;
+        } else if (imeAdapter.getTextInputType() == ImeAdapter.sTextInputTypeSearch) {
+            // Search
+            outAttrs.imeOptions |= EditorInfo.IME_ACTION_SEARCH;
+        } else if (imeAdapter.getTextInputType() == ImeAdapter.sTextInputTypeUrl) {
+            // Url
+            // TYPE_TEXT_VARIATION_URI prevents Tab key from showing, so
+            // exclude it for now.
+            outAttrs.imeOptions |= EditorInfo.IME_ACTION_GO;
+        } else if (imeAdapter.getTextInputType() == ImeAdapter.sTextInputTypeEmail) {
+            // Email
+            outAttrs.inputType = InputType.TYPE_CLASS_TEXT
+                    | InputType.TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS;
+            outAttrs.imeOptions |= EditorInfo.IME_ACTION_GO;
+        } else if (imeAdapter.getTextInputType() == ImeAdapter.sTextInputTypeTel) {
+            // Telephone
+            // Number and telephone do not have both a Tab key and an
+            // action in default OSK, so set the action to NEXT
+            outAttrs.inputType = InputType.TYPE_CLASS_PHONE;
+            outAttrs.imeOptions |= EditorInfo.IME_ACTION_NEXT;
+        } else if (imeAdapter.getTextInputType() == ImeAdapter.sTextInputTypeNumber) {
+            // Number
+            outAttrs.inputType = InputType.TYPE_CLASS_NUMBER
+                    | InputType.TYPE_NUMBER_VARIATION_NORMAL;
+            outAttrs.imeOptions |= EditorInfo.IME_ACTION_NEXT;
+        }
+        outAttrs.initialSelStart = imeAdapter.getInitialSelectionStart();
+        outAttrs.initialSelEnd = imeAdapter.getInitialSelectionStart();
+    }
+
+    /**
+     * Updates the AdapterInputConnection's internal representation of the text
+     * being edited and its selection and composition properties. The resulting
+     * Editable is accessible through the getEditable() method.
+     * If the text has not changed, this also calls updateSelection on the InputMethodManager.
+     * @param text The String contents of the field being edited
+     * @param selectionStart The character offset of the selection start, or the caret
+     * position if there is no selection
+     * @param selectionEnd The character offset of the selection end, or the caret
+     * position if there is no selection
+     * @param compositionStart The character offset of the composition start, or -1
+     * if there is no composition
+     * @param compositionEnd The character offset of the composition end, or -1
+     * if there is no selection
+     */
+    public void setEditableText(String text, int selectionStart, int selectionEnd,
+            int compositionStart, int compositionEnd) {
+        if (DEBUG) {
+            Log.w(TAG, "setEditableText [" + text + "] [" + selectionStart + " " + selectionEnd
+                    + "] [" + compositionStart + " " + compositionEnd + "]");
+        }
+        // Non-breaking spaces can cause the IME to get confused. Replace with normal spaces.
+        text = text.replace('\u00A0', ' ');
+
+        Editable editable = getEditable();
+
+        int prevSelectionStart = Selection.getSelectionStart(editable);
+        int prevSelectionEnd = Selection.getSelectionEnd(editable);
+        int prevCompositionStart = getComposingSpanStart(editable);
+        int prevCompositionEnd = getComposingSpanEnd(editable);
+        String prevText = editable.toString();
+
+        selectionStart = Math.min(selectionStart, text.length());
+        selectionEnd = Math.min(selectionEnd, text.length());
+        compositionStart = Math.min(compositionStart, text.length());
+        compositionEnd = Math.min(compositionEnd, text.length());
+
+        boolean textUnchanged = prevText.equals(text);
+
+        if (!textUnchanged) {
+            editable.replace(0, editable.length(), text);
+        }
+
+        if (prevSelectionStart == selectionStart && prevSelectionEnd == selectionEnd
+                && prevCompositionStart == compositionStart
+                && prevCompositionEnd == compositionEnd) {
+            // Nothing has changed; don't need to do anything
+            return;
+        }
+
+        Selection.setSelection(editable, selectionStart, selectionEnd);
+
+        if (compositionStart == compositionEnd) {
+            removeComposingSpans(editable);
+        } else {
+            super.setComposingRegion(compositionStart, compositionEnd);
+        }
+
+        if (mIgnoreTextInputStateUpdates) return;
+        updateSelection(selectionStart, selectionEnd, compositionStart, compositionEnd);
+    }
+
+    @VisibleForTesting
+    protected void updateSelection(
+            int selectionStart, int selectionEnd,
+            int compositionStart, int compositionEnd) {
+        // Avoid sending update if we sent an exact update already previously.
+        if (mLastUpdateSelectionStart == selectionStart &&
+                mLastUpdateSelectionEnd == selectionEnd &&
+                mLastUpdateCompositionStart == compositionStart &&
+                mLastUpdateCompositionEnd == compositionEnd) {
+            return;
+        }
+        if (DEBUG) {
+            Log.w(TAG, "updateSelection [" + selectionStart + " " + selectionEnd + "] ["
+                    + compositionStart + " " + compositionEnd + "]");
+        }
+        // updateSelection should be called every time the selection or composition changes
+        // if it happens not within a batch edit, or at the end of each top level batch edit.
+        getInputMethodManagerWrapper().updateSelection(mInternalView,
+                selectionStart, selectionEnd, compositionStart, compositionEnd);
+        mLastUpdateSelectionStart = selectionStart;
+        mLastUpdateSelectionEnd = selectionEnd;
+        mLastUpdateCompositionStart = compositionStart;
+        mLastUpdateCompositionEnd = compositionEnd;
+    }
+
+    /**
+     * @see BaseInputConnection#setComposingText(java.lang.CharSequence, int)
+     */
+    @Override
+    public boolean setComposingText(CharSequence text, int newCursorPosition) {
+        if (DEBUG) Log.w(TAG, "setComposingText [" + text + "] [" + newCursorPosition + "]");
+        super.setComposingText(text, newCursorPosition);
+        return mImeAdapter.checkCompositionQueueAndCallNative(text.toString(),
+                newCursorPosition, false);
+    }
+
+    /**
+     * @see BaseInputConnection#commitText(java.lang.CharSequence, int)
+     */
+    @Override
+    public boolean commitText(CharSequence text, int newCursorPosition) {
+        if (DEBUG) Log.w(TAG, "commitText [" + text + "] [" + newCursorPosition + "]");
+        super.commitText(text, newCursorPosition);
+        return mImeAdapter.checkCompositionQueueAndCallNative(text.toString(),
+                newCursorPosition, text.length() > 0);
+    }
+
+    /**
+     * @see BaseInputConnection#performEditorAction(int)
+     */
+    @Override
+    public boolean performEditorAction(int actionCode) {
+        if (DEBUG) Log.w(TAG, "performEditorAction [" + actionCode + "]");
+        if (actionCode == EditorInfo.IME_ACTION_NEXT) {
+            restartInput();
+            // Send TAB key event
+            long timeStampMs = System.currentTimeMillis();
+            mImeAdapter.sendSyntheticKeyEvent(
+                    ImeAdapter.sEventTypeRawKeyDown, timeStampMs, KeyEvent.KEYCODE_TAB, 0);
+        } else {
+            mImeAdapter.sendKeyEventWithKeyCode(KeyEvent.KEYCODE_ENTER,
+                    KeyEvent.FLAG_SOFT_KEYBOARD | KeyEvent.FLAG_KEEP_TOUCH_MODE
+                    | KeyEvent.FLAG_EDITOR_ACTION);
+        }
+        return true;
+    }
+
+    /**
+     * @see BaseInputConnection#performContextMenuAction(int)
+     */
+    @Override
+    public boolean performContextMenuAction(int id) {
+        if (DEBUG) Log.w(TAG, "performContextMenuAction [" + id + "]");
+        switch (id) {
+            case android.R.id.selectAll:
+                return mImeAdapter.selectAll();
+            case android.R.id.cut:
+                return mImeAdapter.cut();
+            case android.R.id.copy:
+                return mImeAdapter.copy();
+            case android.R.id.paste:
+                return mImeAdapter.paste();
+            default:
+                return false;
+        }
+    }
+
+    /**
+     * @see BaseInputConnection#getExtractedText(android.view.inputmethod.ExtractedTextRequest,
+     *                                           int)
+     */
+    @Override
+    public ExtractedText getExtractedText(ExtractedTextRequest request, int flags) {
+        if (DEBUG) Log.w(TAG, "getExtractedText");
+        ExtractedText et = new ExtractedText();
+        Editable editable = getEditable();
+        et.text = editable.toString();
+        et.partialEndOffset = editable.length();
+        et.selectionStart = Selection.getSelectionStart(editable);
+        et.selectionEnd = Selection.getSelectionEnd(editable);
+        et.flags = mSingleLine ? ExtractedText.FLAG_SINGLE_LINE : 0;
+        return et;
+    }
+
+    /**
+     * @see BaseInputConnection#beginBatchEdit()
+     */
+    @Override
+    public boolean beginBatchEdit() {
+        if (DEBUG) Log.w(TAG, "beginBatchEdit [" + (mNumNestedBatchEdits == 0) + "]");
+        if (mNumNestedBatchEdits == 0) mImeAdapter.batchStateChanged(true);
+
+        mNumNestedBatchEdits++;
+        return false;
+    }
+
+    /**
+     * @see BaseInputConnection#endBatchEdit()
+     */
+    @Override
+    public boolean endBatchEdit() {
+        if (mNumNestedBatchEdits == 0) return false;
+
+        --mNumNestedBatchEdits;
+        if (DEBUG) Log.w(TAG, "endBatchEdit [" + (mNumNestedBatchEdits == 0) + "]");
+        if (mNumNestedBatchEdits == 0) mImeAdapter.batchStateChanged(false);
+        return false;
+    }
+
+    /**
+     * @see BaseInputConnection#deleteSurroundingText(int, int)
+     */
+    @Override
+    public boolean deleteSurroundingText(int leftLength, int rightLength) {
+        if (DEBUG) {
+            Log.w(TAG, "deleteSurroundingText [" + leftLength + " " + rightLength + "]");
+        }
+        if (!super.deleteSurroundingText(leftLength, rightLength)) {
+            return false;
+        }
+        return mImeAdapter.deleteSurroundingText(leftLength, rightLength);
+    }
+
+    /**
+     * @see BaseInputConnection#sendKeyEvent(android.view.KeyEvent)
+     */
+    @Override
+    public boolean sendKeyEvent(KeyEvent event) {
+        if (DEBUG) Log.w(TAG, "sendKeyEvent [" + event.getAction() + "]");
+        mImeAdapter.hideSelectionAndInsertionHandleControllers();
+
+        // If this is a key-up, and backspace/del or if the key has a character representation,
+        // need to update the underlying Editable (i.e. the local representation of the text
+        // being edited).
+        if (event.getAction() == KeyEvent.ACTION_UP) {
+            if (event.getKeyCode() == KeyEvent.KEYCODE_DEL) {
+                super.deleteSurroundingText(1, 0);
+            } else if (event.getKeyCode() == KeyEvent.KEYCODE_FORWARD_DEL) {
+                super.deleteSurroundingText(0, 1);
+            } else {
+                int unicodeChar = event.getUnicodeChar();
+                if (unicodeChar != 0) {
+                    Editable editable = getEditable();
+                    int selectionStart = Selection.getSelectionStart(editable);
+                    int selectionEnd = Selection.getSelectionEnd(editable);
+                    if (selectionStart > selectionEnd) {
+                        int temp = selectionStart;
+                        selectionStart = selectionEnd;
+                        selectionEnd = temp;
+                    }
+                    editable.replace(selectionStart, selectionEnd,
+                            Character.toString((char)unicodeChar));
+                }
+            }
+        }
+        mImeAdapter.translateAndSendNativeEvents(event);
+        return true;
+    }
+
+    /**
+     * @see BaseInputConnection#finishComposingText()
+     */
+    @Override
+    public boolean finishComposingText() {
+        if (DEBUG) Log.w(TAG, "finishComposingText");
+        Editable editable = getEditable();
+        if (getComposingSpanStart(editable) == getComposingSpanEnd(editable)) {
+            return true;
+        }
+        super.finishComposingText();
+
+        beginBatchEdit();
+        int selectionStart = Selection.getSelectionStart(editable);
+        int selectionEnd = Selection.getSelectionEnd(editable);
+        if (!mImeAdapter.checkCompositionQueueAndCallNative("", 0, true)) return false;
+        if (!mImeAdapter.setEditableSelectionOffsets(selectionStart, selectionEnd)) return false;
+        endBatchEdit();
+        return true;
+    }
+
+    /**
+     * @see BaseInputConnection#setSelection(int, int)
+     */
+    @Override
+    public boolean setSelection(int start, int end) {
+        if (DEBUG) Log.w(TAG, "setSelection");
+        if (start < 0 || end < 0) return true;
+        super.setSelection(start, end);
+        return mImeAdapter.setEditableSelectionOffsets(start, end);
+    }
+
+    /**
+     * Informs the InputMethodManager and InputMethodSession (i.e. the IME) that the text
+     * state is no longer what the IME has and that it needs to be updated.
+     */
+    void restartInput() {
+        if (DEBUG) Log.w(TAG, "restartInput");
+        getInputMethodManagerWrapper().restartInput(mInternalView);
+        mIgnoreTextInputStateUpdates = false;
+        mNumNestedBatchEdits = 0;
+    }
+
+    /**
+     * @see BaseInputConnection#setComposingRegion(int, int)
+     */
+    @Override
+    public boolean setComposingRegion(int start, int end) {
+        if (DEBUG) Log.w(TAG, "setComposingRegion [" + start + " " + end + "]");
+        int a = Math.min(start, end);
+        int b = Math.max(start, end);
+        if (a < 0) a = 0;
+        if (b < 0) b = 0;
+
+        if (a == b) {
+            removeComposingSpans(getEditable());
+        } else {
+            super.setComposingRegion(a, b);
+        }
+        return mImeAdapter.setComposingRegion(a, b);
+    }
+
+    boolean isActive() {
+        return getInputMethodManagerWrapper().isActive(mInternalView);
+    }
+
+    public void setIgnoreTextInputStateUpdates(boolean shouldIgnore) {
+        mIgnoreTextInputStateUpdates = shouldIgnore;
+        if (shouldIgnore) return;
+
+        Editable editable = getEditable();
+        updateSelection(Selection.getSelectionStart(editable),
+                Selection.getSelectionEnd(editable),
+                getComposingSpanStart(editable),
+                getComposingSpanEnd(editable));
+    }
+
+    @VisibleForTesting
+    protected boolean isIgnoringTextInputStateUpdates() {
+        return mIgnoreTextInputStateUpdates;
+    }
+
+    private InputMethodManagerWrapper getInputMethodManagerWrapper() {
+        return mImeAdapter.getInputMethodManagerWrapper();
+    }
+}
diff --git a/content/public/android/java/src/org/chromium/content/browser/CursorController.java b/content/public/android/java/src/org/chromium/content/browser/input/CursorController.java
similarity index 95%
rename from content/public/android/java/src/org/chromium/content/browser/CursorController.java
rename to content/public/android/java/src/org/chromium/content/browser/input/CursorController.java
index 6e572c8..10e3064 100644
--- a/content/public/android/java/src/org/chromium/content/browser/CursorController.java
+++ b/content/public/android/java/src/org/chromium/content/browser/input/CursorController.java
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-package org.chromium.content.browser;
+package org.chromium.content.browser.input;
 
 import android.view.ViewTreeObserver;
 
diff --git a/content/public/android/java/src/org/chromium/content/browser/DateTimeChooserAndroid.java b/content/public/android/java/src/org/chromium/content/browser/input/DateTimeChooserAndroid.java
similarity index 96%
rename from content/public/android/java/src/org/chromium/content/browser/DateTimeChooserAndroid.java
rename to content/public/android/java/src/org/chromium/content/browser/input/DateTimeChooserAndroid.java
index 7fc146b..f8fca54 100644
--- a/content/public/android/java/src/org/chromium/content/browser/DateTimeChooserAndroid.java
+++ b/content/public/android/java/src/org/chromium/content/browser/input/DateTimeChooserAndroid.java
@@ -2,10 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-package org.chromium.content.browser;
+package org.chromium.content.browser.input;
 
 import org.chromium.base.CalledByNative;
 import org.chromium.base.JNINamespace;
+import org.chromium.content.browser.ContentViewCore;
 
 import android.content.Context;
 
diff --git a/content/public/android/java/src/org/chromium/content/browser/DateTimePickerDialog.java b/content/public/android/java/src/org/chromium/content/browser/input/DateTimePickerDialog.java
similarity index 99%
rename from content/public/android/java/src/org/chromium/content/browser/DateTimePickerDialog.java
rename to content/public/android/java/src/org/chromium/content/browser/input/DateTimePickerDialog.java
index c122c29..29bca66 100644
--- a/content/public/android/java/src/org/chromium/content/browser/DateTimePickerDialog.java
+++ b/content/public/android/java/src/org/chromium/content/browser/input/DateTimePickerDialog.java
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-package org.chromium.content.browser;
+package org.chromium.content.browser.input;
 
 import android.app.AlertDialog;
 import android.content.Context;
diff --git a/content/public/android/java/src/org/chromium/content/browser/HandleView.java b/content/public/android/java/src/org/chromium/content/browser/input/HandleView.java
similarity index 97%
rename from content/public/android/java/src/org/chromium/content/browser/HandleView.java
rename to content/public/android/java/src/org/chromium/content/browser/input/HandleView.java
index a772d5d..a220894 100644
--- a/content/public/android/java/src/org/chromium/content/browser/HandleView.java
+++ b/content/public/android/java/src/org/chromium/content/browser/input/HandleView.java
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-package org.chromium.content.browser;
+package org.chromium.content.browser.input;
 
 import android.content.Context;
 import android.content.res.TypedArray;
@@ -27,7 +27,7 @@
 /**
  * View that displays a selection or insertion handle for text editing.
  */
-class HandleView extends View {
+public class HandleView extends View {
     private static final float FADE_DURATION = 200.f;
 
     private Drawable mDrawable;
@@ -113,7 +113,7 @@
             }
             mDrawable = mSelectHandleLeft;
             handleWidth = mDrawable.getIntrinsicWidth();
-            mHotspotX = (handleWidth * 3) / 4;
+            mHotspotX = (handleWidth * 3) / 4f;
             break;
         }
 
@@ -124,7 +124,7 @@
             }
             mDrawable = mSelectHandleRight;
             handleWidth = mDrawable.getIntrinsicWidth();
-            mHotspotX = handleWidth / 4;
+            mHotspotX = handleWidth / 4f;
             break;
         }
 
@@ -136,7 +136,7 @@
             }
             mDrawable = mSelectHandleCenter;
             handleWidth = mDrawable.getIntrinsicWidth();
-            mHotspotX = handleWidth / 2;
+            mHotspotX = handleWidth / 2f;
             mIsInsertionHandle = true;
             break;
         }
@@ -306,6 +306,9 @@
             case MotionEvent.ACTION_CANCEL:
                 mIsDragging = false;
                 break;
+
+            default:
+                return false;
         }
         return true;
     }
diff --git a/content/public/android/java/src/org/chromium/content/browser/input/ImeAdapter.java b/content/public/android/java/src/org/chromium/content/browser/input/ImeAdapter.java
new file mode 100644
index 0000000..354b242
--- /dev/null
+++ b/content/public/android/java/src/org/chromium/content/browser/input/ImeAdapter.java
@@ -0,0 +1,579 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.content.browser.input;
+
+import android.content.Context;
+import android.os.Handler;
+import android.os.ResultReceiver;
+import android.view.KeyCharacterMap;
+import android.view.KeyEvent;
+import android.view.View;
+import android.view.inputmethod.EditorInfo;
+
+import com.google.common.annotations.VisibleForTesting;
+
+import org.chromium.base.CalledByNative;
+import org.chromium.base.JNINamespace;
+
+/**
+ * Adapts and plumbs android IME service onto the chrome text input API.
+ * ImeAdapter provides an interface in both ways native <-> java:
+ * 1. InputConnectionAdapter notifies native code of text composition state and
+ *    dispatch key events from java -> WebKit.
+ * 2. Native ImeAdapter notifies java side to clear composition text.
+ *
+ * The basic flow is:
+ * 1. When InputConnectionAdapter gets called with composition or result text:
+ *    If we receive a composition text or a result text, then we just need to
+ *    dispatch a synthetic key event with special keycode 229, and then dispatch
+ *    the composition or result text.
+ * 2. Intercept dispatchKeyEvent() method for key events not handled by IME, we
+ *   need to dispatch them to webkit and check webkit's reply. Then inject a
+ *   new key event for further processing if webkit didn't handle it.
+ *
+ * Note that the native peer object does not take any strong reference onto the
+ * instance of this java object, hence it is up to the client of this class (e.g.
+ * the ViewEmbedder implementor) to hold a strong reference to it for the required
+ * lifetime of the object.
+ */
+@JNINamespace("content")
+public class ImeAdapter {
+    public interface ViewEmbedder {
+        /**
+         * @param isFinish whether the event is occurring because input is finished.
+         */
+        void onImeEvent(boolean isFinish);
+        void onSetFieldValue();
+        void onDismissInput();
+        View getAttachedView();
+        ResultReceiver getNewShowKeyboardReceiver();
+    }
+
+    private class DelayedDismissInput implements Runnable {
+        private final int mNativeImeAdapter;
+
+        DelayedDismissInput(int nativeImeAdapter) {
+            mNativeImeAdapter = nativeImeAdapter;
+        }
+
+        @Override
+        public void run() {
+            attach(mNativeImeAdapter, sTextInputTypeNone, AdapterInputConnection.INVALID_SELECTION,
+                    AdapterInputConnection.INVALID_SELECTION);
+            dismissInput(true);
+        }
+    }
+
+    private static final int COMPOSITION_KEY_CODE = 229;
+
+    // Delay introduced to avoid hiding the keyboard if new show requests are received.
+    // The time required by the unfocus-focus events triggered by tab has been measured in soju:
+    // Mean: 18.633 ms, Standard deviation: 7.9837 ms.
+    // The value here should be higher enough to cover these cases, but not too high to avoid
+    // letting the user perceiving important delays.
+    private static final int INPUT_DISMISS_DELAY = 150;
+
+    // All the constants that are retrieved from the C++ code.
+    // They get set through initializeWebInputEvents and initializeTextInputTypes calls.
+    static int sEventTypeRawKeyDown;
+    static int sEventTypeKeyUp;
+    static int sEventTypeChar;
+    static int sTextInputTypeNone;
+    static int sTextInputTypeText;
+    static int sTextInputTypeTextArea;
+    static int sTextInputTypePassword;
+    static int sTextInputTypeSearch;
+    static int sTextInputTypeUrl;
+    static int sTextInputTypeEmail;
+    static int sTextInputTypeTel;
+    static int sTextInputTypeNumber;
+    static int sTextInputTypeWeek;
+    static int sTextInputTypeContentEditable;
+    static int sModifierShift;
+    static int sModifierAlt;
+    static int sModifierCtrl;
+    static int sModifierCapsLockOn;
+    static int sModifierNumLockOn;
+
+    private int mNativeImeAdapterAndroid;
+    private final Context mContext;
+    private InputMethodManagerWrapper mInputMethodManagerWrapper;
+    private AdapterInputConnection mInputConnection;
+    private final ViewEmbedder mViewEmbedder;
+    private final Handler mHandler;
+    private DelayedDismissInput mDismissInput = null;
+    private final SelectionHandleController mSelectionHandleController;
+    private final InsertionHandleController mInsertionHandleController;
+    private int mTextInputType;
+    private int mInitialSelectionStart;
+    private int mInitialSelectionEnd;
+
+    @VisibleForTesting
+    boolean mIsShowWithoutHideOutstanding = false;
+
+    /**
+     * @param context View context.
+     * @param selectionHandleController The controller that handles selection.
+     * @param insertionHandleController The controller that handles insertion.
+     * @param embedder The view that is used for callbacks from ImeAdapter.
+     */
+    public ImeAdapter(Context context, SelectionHandleController selectionHandleController,
+            InsertionHandleController insertionHandleController, ViewEmbedder embedder) {
+        mContext = context;
+        mInputMethodManagerWrapper = new InputMethodManagerWrapper(context);
+        mSelectionHandleController = selectionHandleController;
+        mInsertionHandleController = insertionHandleController;
+        mViewEmbedder = embedder;
+        mHandler = new Handler();
+    }
+
+    public static class AdapterInputConnectionFactory {
+        public AdapterInputConnection get(View view, ImeAdapter imeAdapter,
+                EditorInfo outAttrs) {
+            return new AdapterInputConnection(view, imeAdapter, outAttrs);
+        }
+    }
+
+    @VisibleForTesting
+    protected void setInputMethodManagerWrapper(InputMethodManagerWrapper immw) {
+        mInputMethodManagerWrapper = immw;
+    }
+
+    /**
+     * Should be only used by AdapterInputConnection.
+     * @return InputMethodManagerWrapper that should receive all the calls directed to
+     *         InputMethodManager.
+     */
+    InputMethodManagerWrapper getInputMethodManagerWrapper() {
+        return mInputMethodManagerWrapper;
+    }
+
+    /**
+     * Set the current active InputConnection when a new InputConnection is constructed.
+     * @param inputConnection The input connection that is currently used with IME.
+     */
+    void setInputConnection(AdapterInputConnection inputConnection) {
+        mInputConnection = inputConnection;
+    }
+
+    /**
+     * Should be only used by AdapterInputConnection.
+     * @return The input type of currently focused element.
+     */
+    int getTextInputType() {
+        return mTextInputType;
+    }
+
+    /**
+     * Should be only used by AdapterInputConnection.
+     * @return The starting index of the initial text selection.
+     */
+    int getInitialSelectionStart() {
+        return mInitialSelectionStart;
+    }
+
+    /**
+     * Should be only used by AdapterInputConnection.
+     * @return The ending index of the initial text selection.
+     */
+    int getInitialSelectionEnd() {
+        return mInitialSelectionEnd;
+    }
+
+    public static int getTextInputTypeNone() {
+        return sTextInputTypeNone;
+    }
+
+    private static int getModifiers(int metaState) {
+        int modifiers = 0;
+        if ((metaState & KeyEvent.META_SHIFT_ON) != 0) {
+          modifiers |= sModifierShift;
+        }
+        if ((metaState & KeyEvent.META_ALT_ON) != 0) {
+          modifiers |= sModifierAlt;
+        }
+        if ((metaState & KeyEvent.META_CTRL_ON) != 0) {
+          modifiers |= sModifierCtrl;
+        }
+        if ((metaState & KeyEvent.META_CAPS_LOCK_ON) != 0) {
+          modifiers |= sModifierCapsLockOn;
+        }
+        if ((metaState & KeyEvent.META_NUM_LOCK_ON) != 0) {
+          modifiers |= sModifierNumLockOn;
+        }
+        return modifiers;
+    }
+
+    void hideSelectionAndInsertionHandleControllers() {
+        mSelectionHandleController.hideAndDisallowAutomaticShowing();
+        mInsertionHandleController.hideAndDisallowAutomaticShowing();
+    }
+
+    public boolean isActive() {
+        return mInputConnection != null && mInputConnection.isActive();
+    }
+
+    private boolean isFor(int nativeImeAdapter, int textInputType) {
+        return mNativeImeAdapterAndroid == nativeImeAdapter &&
+               mTextInputType == textInputType;
+    }
+
+    public void attachAndShowIfNeeded(int nativeImeAdapter, int textInputType,
+            int selectionStart, int selectionEnd, boolean showIfNeeded) {
+        mHandler.removeCallbacks(mDismissInput);
+
+        // If current input type is none and showIfNeeded is false, IME should not be shown
+        // and input type should remain as none.
+        if (mTextInputType == sTextInputTypeNone && !showIfNeeded) {
+            return;
+        }
+
+        if (!isFor(nativeImeAdapter, textInputType)) {
+            // Set a delayed task to perform unfocus. This avoids hiding the keyboard when tabbing
+            // through text inputs or when JS rapidly changes focus to another text element.
+            if (textInputType == sTextInputTypeNone) {
+                mDismissInput = new DelayedDismissInput(nativeImeAdapter);
+                mHandler.postDelayed(mDismissInput, INPUT_DISMISS_DELAY);
+                return;
+            }
+
+            int previousType = mTextInputType;
+            attach(nativeImeAdapter, textInputType, selectionStart, selectionEnd);
+
+            mInputMethodManagerWrapper.restartInput(mViewEmbedder.getAttachedView());
+            if (showIfNeeded) {
+                showKeyboard();
+            }
+        } else if (hasInputType() && showIfNeeded) {
+            showKeyboard();
+        }
+    }
+
+    public void attach(int nativeImeAdapter, int textInputType, int selectionStart,
+            int selectionEnd) {
+        if (mNativeImeAdapterAndroid != 0) {
+            nativeResetImeAdapter(mNativeImeAdapterAndroid);
+        }
+        mNativeImeAdapterAndroid = nativeImeAdapter;
+        mTextInputType = textInputType;
+        mInitialSelectionStart = selectionStart;
+        mInitialSelectionEnd = selectionEnd;
+        nativeAttachImeAdapter(mNativeImeAdapterAndroid);
+    }
+
+    /**
+     * Attaches the imeAdapter to its native counterpart. This is needed to start forwarding
+     * keyboard events to WebKit.
+     * @param nativeImeAdapter The pointer to the native ImeAdapter object.
+     */
+    public void attach(int nativeImeAdapter) {
+        if (mNativeImeAdapterAndroid != 0) {
+            nativeResetImeAdapter(mNativeImeAdapterAndroid);
+        }
+        mNativeImeAdapterAndroid = nativeImeAdapter;
+        if (nativeImeAdapter != 0) {
+            nativeAttachImeAdapter(mNativeImeAdapterAndroid);
+        }
+    }
+
+    /**
+     * Used to check whether the native counterpart of the ImeAdapter has been attached yet.
+     * @return Whether native ImeAdapter has been attached and its pointer is currently nonzero.
+     */
+    public boolean isNativeImeAdapterAttached() {
+        return mNativeImeAdapterAndroid != 0;
+    }
+
+    private void showKeyboard() {
+        mIsShowWithoutHideOutstanding = true;
+        mInputMethodManagerWrapper.showSoftInput(mViewEmbedder.getAttachedView(), 0,
+                mViewEmbedder.getNewShowKeyboardReceiver());
+    }
+
+    private void dismissInput(boolean unzoomIfNeeded) {
+        hideKeyboard(unzoomIfNeeded);
+        mViewEmbedder.onDismissInput();
+    }
+
+    private void hideKeyboard(boolean unzoomIfNeeded) {
+        mIsShowWithoutHideOutstanding  = false;
+        View view = mViewEmbedder.getAttachedView();
+        if (mInputMethodManagerWrapper.isActive(view)) {
+            mInputMethodManagerWrapper.hideSoftInputFromWindow(view.getWindowToken(), 0,
+                    unzoomIfNeeded ? mViewEmbedder.getNewShowKeyboardReceiver() : null);
+        }
+    }
+
+    private boolean hasInputType() {
+        return mTextInputType != sTextInputTypeNone;
+    }
+
+    static boolean isTextInputType(int type) {
+        return type != sTextInputTypeNone && !InputDialogContainer.isDialogInputType(type);
+    }
+
+    public boolean hasTextInputType() {
+        return isTextInputType(mTextInputType);
+    }
+
+    public boolean dispatchKeyEvent(KeyEvent event) {
+        return translateAndSendNativeEvents(event);
+    }
+
+    private int shouldSendKeyEventWithKeyCode(String text) {
+        if (text.length() != 1) return COMPOSITION_KEY_CODE;
+
+        if (text.equals("\n")) return KeyEvent.KEYCODE_ENTER;
+        else if (text.equals("\t")) return KeyEvent.KEYCODE_TAB;
+        else return COMPOSITION_KEY_CODE;
+    }
+
+    void sendKeyEventWithKeyCode(int keyCode, int flags) {
+        long eventTime = System.currentTimeMillis();
+        translateAndSendNativeEvents(new KeyEvent(eventTime, eventTime,
+                KeyEvent.ACTION_DOWN, keyCode, 0, 0,
+                KeyCharacterMap.VIRTUAL_KEYBOARD, 0,
+                flags));
+        translateAndSendNativeEvents(new KeyEvent(System.currentTimeMillis(), eventTime,
+                KeyEvent.ACTION_UP, keyCode, 0, 0,
+                KeyCharacterMap.VIRTUAL_KEYBOARD, 0,
+                flags));
+    }
+
+    // Calls from Java to C++
+
+    @VisibleForTesting
+    boolean checkCompositionQueueAndCallNative(String text, int newCursorPosition,
+            boolean isCommit) {
+        if (mNativeImeAdapterAndroid == 0) return false;
+
+        // Committing an empty string finishes the current composition.
+        boolean isFinish = text.isEmpty();
+        if (!isFinish) {
+            mSelectionHandleController.hideAndDisallowAutomaticShowing();
+            mInsertionHandleController.hideAndDisallowAutomaticShowing();
+        }
+        mViewEmbedder.onImeEvent(isFinish);
+        int keyCode = shouldSendKeyEventWithKeyCode(text);
+        long timeStampMs = System.currentTimeMillis();
+
+        if (keyCode != COMPOSITION_KEY_CODE) {
+            sendKeyEventWithKeyCode(keyCode,
+                    KeyEvent.FLAG_SOFT_KEYBOARD | KeyEvent.FLAG_KEEP_TOUCH_MODE);
+        } else {
+            nativeSendSyntheticKeyEvent(mNativeImeAdapterAndroid, sEventTypeRawKeyDown,
+                    timeStampMs, keyCode, 0);
+            if (isCommit) {
+                nativeCommitText(mNativeImeAdapterAndroid, text);
+            } else {
+                nativeSetComposingText(mNativeImeAdapterAndroid, text, newCursorPosition);
+            }
+            nativeSendSyntheticKeyEvent(mNativeImeAdapterAndroid, sEventTypeKeyUp,
+                    timeStampMs, keyCode, 0);
+        }
+
+        return true;
+    }
+
+    boolean translateAndSendNativeEvents(KeyEvent event) {
+        if (mNativeImeAdapterAndroid == 0) return false;
+
+        int action = event.getAction();
+        if (action != KeyEvent.ACTION_DOWN &&
+            action != KeyEvent.ACTION_UP) {
+            // action == KeyEvent.ACTION_MULTIPLE
+            // TODO(bulach): confirm the actual behavior. Apparently:
+            // If event.getKeyCode() == KEYCODE_UNKNOWN, we can send a
+            // composition key down (229) followed by a commit text with the
+            // string from event.getUnicodeChars().
+            // Otherwise, we'd need to send an event with a
+            // WebInputEvent::IsAutoRepeat modifier. We also need to verify when
+            // we receive ACTION_MULTIPLE: we may receive it after an ACTION_DOWN,
+            // and if that's the case, we'll need to review when to send the Char
+            // event.
+            return false;
+        }
+        mViewEmbedder.onImeEvent(false);
+        return nativeSendKeyEvent(mNativeImeAdapterAndroid, event, event.getAction(),
+                getModifiers(event.getMetaState()), event.getEventTime(), event.getKeyCode(),
+                                event.isSystem(), event.getUnicodeChar());
+    }
+
+    boolean sendSyntheticKeyEvent(
+            int eventType, long timestampMs, int keyCode, int unicodeChar) {
+        if (mNativeImeAdapterAndroid == 0) return false;
+
+        nativeSendSyntheticKeyEvent(
+                mNativeImeAdapterAndroid, eventType, timestampMs, keyCode, unicodeChar);
+        return true;
+    }
+
+    boolean deleteSurroundingText(int leftLength, int rightLength) {
+        if (mNativeImeAdapterAndroid == 0) return false;
+        nativeDeleteSurroundingText(mNativeImeAdapterAndroid, leftLength, rightLength);
+        return true;
+    }
+
+    @VisibleForTesting
+    protected boolean setEditableSelectionOffsets(int start, int end) {
+        if (mNativeImeAdapterAndroid == 0) return false;
+        nativeSetEditableSelectionOffsets(mNativeImeAdapterAndroid, start, end);
+        return true;
+    }
+
+    void batchStateChanged(boolean isBegin) {
+        if (mNativeImeAdapterAndroid == 0) return;
+        nativeImeBatchStateChanged(mNativeImeAdapterAndroid, isBegin);
+    }
+
+    void commitText() {
+        cancelComposition();
+        if (mNativeImeAdapterAndroid != 0) {
+            nativeCommitText(mNativeImeAdapterAndroid, "");
+        }
+    }
+
+    /**
+     * Send a request to the native counterpart to set compositing region to given indices.
+     * @param start The start of the composition.
+     * @param end The end of the composition.
+     * @return Whether the native counterpart of ImeAdapter received the call.
+     */
+    boolean setComposingRegion(int start, int end) {
+        if (mNativeImeAdapterAndroid == 0) return false;
+        nativeSetComposingRegion(mNativeImeAdapterAndroid, start, end);
+        return true;
+    }
+
+    /**
+     * Send a request to the native counterpart to unselect text.
+     * @return Whether the native counterpart of ImeAdapter received the call.
+     */
+    public boolean unselect() {
+        if (mNativeImeAdapterAndroid == 0) return false;
+        nativeUnselect(mNativeImeAdapterAndroid);
+        return true;
+    }
+
+    /**
+     * Send a request to the native counterpart of ImeAdapter to select all the text.
+     * @return Whether the native counterpart of ImeAdapter received the call.
+     */
+    public boolean selectAll() {
+        if (mNativeImeAdapterAndroid == 0) return false;
+        nativeSelectAll(mNativeImeAdapterAndroid);
+        return true;
+    }
+
+    /**
+     * Send a request to the native counterpart of ImeAdapter to cut the selected text.
+     * @return Whether the native counterpart of ImeAdapter received the call.
+     */
+    public boolean cut() {
+        if (mNativeImeAdapterAndroid == 0) return false;
+        nativeCut(mNativeImeAdapterAndroid);
+        return true;
+    }
+
+    /**
+     * Send a request to the native counterpart of ImeAdapter to copy the selected text.
+     * @return Whether the native counterpart of ImeAdapter received the call.
+     */
+    public boolean copy() {
+        if (mNativeImeAdapterAndroid == 0) return false;
+        nativeCopy(mNativeImeAdapterAndroid);
+        return true;
+    }
+
+    /**
+     * Send a request to the native counterpart of ImeAdapter to paste the text from the clipboard.
+     * @return Whether the native counterpart of ImeAdapter received the call.
+     */
+    public boolean paste() {
+        if (mNativeImeAdapterAndroid == 0) return false;
+        nativePaste(mNativeImeAdapterAndroid);
+        return true;
+    }
+
+    // Calls from C++ to Java
+
+    @CalledByNative
+    private static void initializeWebInputEvents(int eventTypeRawKeyDown, int eventTypeKeyUp,
+            int eventTypeChar, int modifierShift, int modifierAlt, int modifierCtrl,
+            int modifierCapsLockOn, int modifierNumLockOn) {
+        sEventTypeRawKeyDown = eventTypeRawKeyDown;
+        sEventTypeKeyUp = eventTypeKeyUp;
+        sEventTypeChar = eventTypeChar;
+        sModifierShift = modifierShift;
+        sModifierAlt = modifierAlt;
+        sModifierCtrl = modifierCtrl;
+        sModifierCapsLockOn = modifierCapsLockOn;
+        sModifierNumLockOn = modifierNumLockOn;
+    }
+
+    @CalledByNative
+    private static void initializeTextInputTypes(int textInputTypeNone, int textInputTypeText,
+            int textInputTypeTextArea, int textInputTypePassword, int textInputTypeSearch,
+            int textInputTypeUrl, int textInputTypeEmail, int textInputTypeTel,
+            int textInputTypeNumber, int textInputTypeDate, int textInputTypeDateTime,
+            int textInputTypeDateTimeLocal, int textInputTypeMonth, int textInputTypeTime,
+            int textInputTypeWeek, int textInputTypeContentEditable) {
+        sTextInputTypeNone = textInputTypeNone;
+        sTextInputTypeText = textInputTypeText;
+        sTextInputTypeTextArea = textInputTypeTextArea;
+        sTextInputTypePassword = textInputTypePassword;
+        sTextInputTypeSearch = textInputTypeSearch;
+        sTextInputTypeUrl = textInputTypeUrl;
+        sTextInputTypeEmail = textInputTypeEmail;
+        sTextInputTypeTel = textInputTypeTel;
+        sTextInputTypeNumber = textInputTypeNumber;
+        sTextInputTypeWeek = textInputTypeWeek;
+        sTextInputTypeContentEditable = textInputTypeContentEditable;
+    }
+
+    @CalledByNative
+    private void cancelComposition() {
+        if (mInputConnection != null) {
+            mInputConnection.restartInput();
+        }
+    }
+
+    @CalledByNative
+    void detach() {
+        mNativeImeAdapterAndroid = 0;
+        mTextInputType = 0;
+    }
+
+    private native boolean nativeSendSyntheticKeyEvent(int nativeImeAdapterAndroid,
+            int eventType, long timestampMs, int keyCode, int unicodeChar);
+
+    private native boolean nativeSendKeyEvent(int nativeImeAdapterAndroid, KeyEvent event,
+            int action, int modifiers, long timestampMs, int keyCode, boolean isSystemKey,
+            int unicodeChar);
+
+    private native void nativeSetComposingText(int nativeImeAdapterAndroid, String text,
+            int newCursorPosition);
+
+    private native void nativeCommitText(int nativeImeAdapterAndroid, String text);
+
+    private native void nativeAttachImeAdapter(int nativeImeAdapterAndroid);
+
+    private native void nativeSetEditableSelectionOffsets(int nativeImeAdapterAndroid,
+            int start, int end);
+
+    private native void nativeSetComposingRegion(int nativeImeAdapterAndroid, int start, int end);
+
+    private native void nativeDeleteSurroundingText(int nativeImeAdapterAndroid,
+            int before, int after);
+
+    private native void nativeImeBatchStateChanged(int nativeImeAdapterAndroid, boolean isBegin);
+
+    private native void nativeUnselect(int nativeImeAdapterAndroid);
+    private native void nativeSelectAll(int nativeImeAdapterAndroid);
+    private native void nativeCut(int nativeImeAdapterAndroid);
+    private native void nativeCopy(int nativeImeAdapterAndroid);
+    private native void nativePaste(int nativeImeAdapterAndroid);
+    private native void nativeResetImeAdapter(int nativeImeAdapterAndroid);
+}
diff --git a/content/public/android/java/src/org/chromium/content/browser/InputDialogContainer.java b/content/public/android/java/src/org/chromium/content/browser/input/InputDialogContainer.java
similarity index 97%
rename from content/public/android/java/src/org/chromium/content/browser/InputDialogContainer.java
rename to content/public/android/java/src/org/chromium/content/browser/input/InputDialogContainer.java
index 466665d..11189c5 100644
--- a/content/public/android/java/src/org/chromium/content/browser/InputDialogContainer.java
+++ b/content/public/android/java/src/org/chromium/content/browser/input/InputDialogContainer.java
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-package org.chromium.content.browser;
+package org.chromium.content.browser.input;
 
 import android.app.AlertDialog;
 import android.app.DatePickerDialog;
@@ -18,8 +18,8 @@
 import android.widget.DatePicker;
 import android.widget.TimePicker;
 
-import org.chromium.content.browser.DateTimePickerDialog.OnDateTimeSetListener;
-import org.chromium.content.browser.MonthPickerDialog.OnMonthSetListener;
+import org.chromium.content.browser.input.DateTimePickerDialog.OnDateTimeSetListener;
+import org.chromium.content.browser.input.MonthPickerDialog.OnMonthSetListener;
 import org.chromium.content.R;
 
 import java.text.ParseException;
@@ -27,7 +27,7 @@
 import java.util.Calendar;
 import java.util.Date;
 
-class InputDialogContainer {
+public class InputDialogContainer {
 
     interface InputActionDelegate {
         void cancelDateTimeDialog();
diff --git a/content/public/android/java/src/org/chromium/content/browser/InputMethodManagerWrapper.java b/content/public/android/java/src/org/chromium/content/browser/input/InputMethodManagerWrapper.java
similarity index 96%
rename from content/public/android/java/src/org/chromium/content/browser/InputMethodManagerWrapper.java
rename to content/public/android/java/src/org/chromium/content/browser/input/InputMethodManagerWrapper.java
index 572582e..34b8b4e 100644
--- a/content/public/android/java/src/org/chromium/content/browser/InputMethodManagerWrapper.java
+++ b/content/public/android/java/src/org/chromium/content/browser/input/InputMethodManagerWrapper.java
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-package org.chromium.content.browser;
+package org.chromium.content.browser.input;
 
 import android.content.Context;
 import android.os.IBinder;
@@ -13,7 +13,7 @@
 /**
  * Wrapper around Android's InputMethodManager
  */
-public class InputMethodManagerWrapper {
+class InputMethodManagerWrapper {
     private final Context mContext;
 
     public InputMethodManagerWrapper(Context context) {
diff --git a/content/public/android/java/src/org/chromium/content/browser/InsertionHandleController.java b/content/public/android/java/src/org/chromium/content/browser/input/InsertionHandleController.java
similarity index 93%
rename from content/public/android/java/src/org/chromium/content/browser/InsertionHandleController.java
rename to content/public/android/java/src/org/chromium/content/browser/input/InsertionHandleController.java
index 18fb7a4..e3ab838 100644
--- a/content/public/android/java/src/org/chromium/content/browser/InsertionHandleController.java
+++ b/content/public/android/java/src/org/chromium/content/browser/input/InsertionHandleController.java
@@ -2,13 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-package org.chromium.content.browser;
+package org.chromium.content.browser.input;
 
 import android.content.ClipboardManager;
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.graphics.drawable.Drawable;
-import android.graphics.PointF;
 import android.view.Gravity;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -20,7 +19,7 @@
 /**
  * CursorController for inserting text at the cursor position.
  */
-abstract class InsertionHandleController implements CursorController {
+public abstract class InsertionHandleController implements CursorController {
 
     /** The handle view, lazily created when first shown */
     private HandleView mHandle;
@@ -36,18 +35,18 @@
 
     private Context mContext;
 
-    InsertionHandleController(View parent) {
+    public InsertionHandleController(View parent) {
         mParent = parent;
         mContext = parent.getContext();
     }
 
     /** Allows the handle to be shown automatically when cursor position changes */
-    void allowAutomaticShowing() {
+    public void allowAutomaticShowing() {
         mAllowAutomaticShowing = true;
     }
 
     /** Disallows the handle from being shown automatically when cursor position changes */
-    void hideAndDisallowAutomaticShowing() {
+    public void hideAndDisallowAutomaticShowing() {
         hide();
         mAllowAutomaticShowing = false;
     }
@@ -55,7 +54,7 @@
     /**
      * Shows the handle.
      */
-    void showHandle() {
+    public void showHandle() {
         createHandleIfNeeded();
         showHandleIfNeeded();
     }
@@ -66,13 +65,13 @@
         }
     }
 
-    void showHandleWithPastePopup() {
+    public void showHandleWithPastePopup() {
         showHandle();
         showPastePopup();
     }
 
     /** Shows the handle at the given coordinates, as long as automatic showing is allowed */
-    void onCursorPositionChanged() {
+    public void onCursorPositionChanged() {
         if (mAllowAutomaticShowing) {
             showHandle();
         }
@@ -83,25 +82,21 @@
      * @param x Handle x in physical pixels.
      * @param y Handle y in physical pixels.
      */
-    void setHandlePosition(int x, int y) {
-        mHandle.positionAt(x, y);
-    }
-
-    void setHandlePosition(float x, float y) {
-        setHandlePosition((int) x, (int) y);
+    public void setHandlePosition(float x, float y) {
+        mHandle.positionAt((int) x, (int) y);
     }
 
     /**
      * If the handle is not visible, sets its visibility to View.VISIBLE and begins fading it in.
      */
-    void beginHandleFadeIn() {
+    public void beginHandleFadeIn() {
         mHandle.beginFadeIn();
     }
 
     /**
      * Sets the handle to the given visibility.
      */
-    void setHandleVisibility(int visibility) {
+    public void setHandleVisibility(int visibility) {
         mHandle.setVisibility(visibility);
     }
 
diff --git a/content/public/android/java/src/org/chromium/content/browser/MonthPicker.java b/content/public/android/java/src/org/chromium/content/browser/input/MonthPicker.java
similarity index 89%
rename from content/public/android/java/src/org/chromium/content/browser/MonthPicker.java
rename to content/public/android/java/src/org/chromium/content/browser/input/MonthPicker.java
index 75794ee..01e636e 100644
--- a/content/public/android/java/src/org/chromium/content/browser/MonthPicker.java
+++ b/content/public/android/java/src/org/chromium/content/browser/input/MonthPicker.java
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-package org.chromium.content.browser;
+package org.chromium.content.browser.input;
 
 import android.content.Context;
 import android.content.res.Configuration;
@@ -15,10 +15,10 @@
 import android.view.accessibility.AccessibilityEvent;
 import android.widget.DatePicker;
 import android.widget.FrameLayout;
-import android.widget.LinearLayout;
 import android.widget.NumberPicker;
 import android.widget.NumberPicker.OnValueChangeListener;
 
+import java.text.DateFormatSymbols;
 import java.util.Arrays;
 import java.util.Calendar;
 import java.util.Locale;
@@ -35,8 +35,6 @@
 
     private static final boolean DEFAULT_ENABLED_STATE = true;
 
-    private final LinearLayout mSpinners;
-
     private final NumberPicker mMonthSpinner;
 
     private final NumberPicker mYearSpinner;
@@ -49,8 +47,6 @@
 
     private int mNumberOfMonths;
 
-    private Calendar mTempDate;
-
     private Calendar mMinDate;
 
     private Calendar mMaxDate;
@@ -97,31 +93,33 @@
         inflater.inflate(R.layout.month_picker, this, true);
 
         OnValueChangeListener onChangeListener = new OnValueChangeListener() {
+            @Override
             public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
-                mTempDate.setTimeInMillis(mCurrentDate.getTimeInMillis());
+                Calendar tempDate = getCalendarForLocale(null, mCurrentLocale);
+                tempDate.setTimeInMillis(mCurrentDate.getTimeInMillis());
+
                 // take care of wrapping of days and months to update greater fields
                 if (picker == mMonthSpinner) {
                     if (oldVal == 11 && newVal == 0) {
-                        mTempDate.add(Calendar.MONTH, 1);
+                        tempDate.add(Calendar.MONTH, 1);
                     } else if (oldVal == 0 && newVal == 11) {
-                        mTempDate.add(Calendar.MONTH, -1);
+                        tempDate.add(Calendar.MONTH, -1);
                     } else {
-                        mTempDate.add(Calendar.MONTH, newVal - oldVal);
+                        tempDate.add(Calendar.MONTH, newVal - oldVal);
                     }
                 } else if (picker == mYearSpinner) {
-                    mTempDate.set(Calendar.YEAR, newVal);
+                    tempDate.set(Calendar.YEAR, newVal);
                 } else {
                     throw new IllegalArgumentException();
                 }
+
                 // now set the date to the adjusted one
-                setDate(mTempDate.get(Calendar.YEAR), mTempDate.get(Calendar.MONTH));
+                setDate(tempDate.get(Calendar.YEAR), tempDate.get(Calendar.MONTH));
                 updateSpinners();
                 notifyDateChanged();
             }
         };
 
-        mSpinners = (LinearLayout) findViewById(R.id.pickers);
-
         // month
         mMonthSpinner = (NumberPicker) findViewById(R.id.month);
         mMonthSpinner.setMinValue(0);
@@ -135,14 +133,12 @@
         mYearSpinner.setOnLongPressUpdateInterval(100);
         mYearSpinner.setOnValueChangedListener(onChangeListener);
 
-        mTempDate.clear();
-        mTempDate.set(startYear, 0, 1);
+        Calendar tempDate = getCalendarForLocale(null, mCurrentLocale);
+        tempDate.set(startYear, 0, 1);
 
-        setMinDate(mTempDate.getTimeInMillis());
-
-        mTempDate.clear();
-        mTempDate.set(endYear, 11, 31);
-        setMaxDate(mTempDate.getTimeInMillis());
+        setMinDate(tempDate.getTimeInMillis());
+        tempDate.set(endYear, 11, 31);
+        setMaxDate(tempDate.getTimeInMillis());
 
         // initialize to current date
         mCurrentDate.setTimeInMillis(System.currentTimeMillis());
@@ -171,9 +167,10 @@
      * @param minDate The minimal supported date.
      */
     public void setMinDate(long minDate) {
-        mTempDate.setTimeInMillis(minDate);
-        if (mTempDate.get(Calendar.YEAR) == mMinDate.get(Calendar.YEAR)
-                && mTempDate.get(Calendar.DAY_OF_YEAR) != mMinDate.get(Calendar.DAY_OF_YEAR)) {
+        Calendar tempDate = getCalendarForLocale(null, mCurrentLocale);
+        tempDate.setTimeInMillis(minDate);
+        if (tempDate.get(Calendar.YEAR) == mMinDate.get(Calendar.YEAR)
+                && tempDate.get(Calendar.DAY_OF_YEAR) != mMinDate.get(Calendar.DAY_OF_YEAR)) {
             return;
         }
         mMinDate.setTimeInMillis(minDate);
@@ -205,9 +202,10 @@
      * @param maxDate The maximal supported date.
      */
     public void setMaxDate(long maxDate) {
-        mTempDate.setTimeInMillis(maxDate);
-        if (mTempDate.get(Calendar.YEAR) == mMaxDate.get(Calendar.YEAR)
-                && mTempDate.get(Calendar.DAY_OF_YEAR) != mMaxDate.get(Calendar.DAY_OF_YEAR)) {
+        Calendar tempDate = getCalendarForLocale(null, mCurrentLocale);
+        tempDate.setTimeInMillis(maxDate);
+        if (tempDate.get(Calendar.YEAR) == mMaxDate.get(Calendar.YEAR)
+                && tempDate.get(Calendar.DAY_OF_YEAR) != mMaxDate.get(Calendar.DAY_OF_YEAR)) {
             return;
         }
         mMaxDate.setTimeInMillis(maxDate);
@@ -266,18 +264,13 @@
         }
 
         mCurrentLocale = locale;
-
-        mTempDate = getCalendarForLocale(mTempDate, locale);
         mMinDate = getCalendarForLocale(mMinDate, locale);
         mMaxDate = getCalendarForLocale(mMaxDate, locale);
         mCurrentDate = getCalendarForLocale(mCurrentDate, locale);
 
-        mNumberOfMonths = mTempDate.getActualMaximum(Calendar.MONTH) + 1;
-        mShortMonths = new String[mNumberOfMonths];
-        for (int i = 0; i < mNumberOfMonths; i++) {
-            mShortMonths[i] = DateUtils.getMonthString(Calendar.JANUARY + i,
-                    DateUtils.LENGTH_MEDIUM);
-        }
+        mShortMonths =
+                DateFormatSymbols.getInstance(mCurrentLocale).getShortMonths();
+        mNumberOfMonths = mShortMonths.length;
     }
 
     /**
diff --git a/content/public/android/java/src/org/chromium/content/browser/MonthPickerDialog.java b/content/public/android/java/src/org/chromium/content/browser/input/MonthPickerDialog.java
similarity index 97%
rename from content/public/android/java/src/org/chromium/content/browser/MonthPickerDialog.java
rename to content/public/android/java/src/org/chromium/content/browser/input/MonthPickerDialog.java
index cf8c770..354810e 100644
--- a/content/public/android/java/src/org/chromium/content/browser/MonthPickerDialog.java
+++ b/content/public/android/java/src/org/chromium/content/browser/input/MonthPickerDialog.java
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-package org.chromium.content.browser;
+package org.chromium.content.browser.input;
 
 import android.app.AlertDialog;
 import android.content.Context;
@@ -12,7 +12,7 @@
 import android.os.Bundle;
 import android.view.View;
 
-import org.chromium.content.browser.MonthPicker.OnMonthChangedListener;
+import org.chromium.content.browser.input.MonthPicker.OnMonthChangedListener;
 import org.chromium.content.R;
 
 public class MonthPickerDialog extends AlertDialog implements OnClickListener,
diff --git a/content/public/android/java/src/org/chromium/content/browser/SelectPopupDialog.java b/content/public/android/java/src/org/chromium/content/browser/input/SelectPopupDialog.java
similarity index 97%
rename from content/public/android/java/src/org/chromium/content/browser/SelectPopupDialog.java
rename to content/public/android/java/src/org/chromium/content/browser/input/SelectPopupDialog.java
index b5d00a5..d32266b 100644
--- a/content/public/android/java/src/org/chromium/content/browser/SelectPopupDialog.java
+++ b/content/public/android/java/src/org/chromium/content/browser/input/SelectPopupDialog.java
@@ -2,7 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-package org.chromium.content.browser;
+package org.chromium.content.browser.input;
+
+import org.chromium.content.browser.ContentViewCore;
 
 import android.app.AlertDialog;
 import android.content.DialogInterface;
@@ -18,7 +20,7 @@
 /**
  * Handles the popup dialog for the <select> HTML tag support.
  */
-class SelectPopupDialog {
+public class SelectPopupDialog {
     // The currently showing popup dialog, null if none is showing.
     private static SelectPopupDialog sShownDialog;
 
@@ -211,7 +213,7 @@
     }
 
     // The methods below are used by tests.
-    static SelectPopupDialog getCurrent() {
+    public static SelectPopupDialog getCurrent() {
         return sShownDialog;
     }
 }
diff --git a/content/public/android/java/src/org/chromium/content/browser/SelectionHandleController.java b/content/public/android/java/src/org/chromium/content/browser/input/SelectionHandleController.java
similarity index 81%
rename from content/public/android/java/src/org/chromium/content/browser/SelectionHandleController.java
rename to content/public/android/java/src/org/chromium/content/browser/input/SelectionHandleController.java
index 8c5a969..f65c6a5 100644
--- a/content/public/android/java/src/org/chromium/content/browser/SelectionHandleController.java
+++ b/content/public/android/java/src/org/chromium/content/browser/input/SelectionHandleController.java
@@ -2,15 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-package org.chromium.content.browser;
+package org.chromium.content.browser.input;
 
-import android.graphics.PointF;
 import android.view.View;
 
 /**
  * CursorController for selecting a range of text.
  */
-abstract class SelectionHandleController implements CursorController {
+public abstract class SelectionHandleController implements CursorController {
 
     // The following constants match the ones in
     // third_party/WebKit/Source/WebKit/chromium/public/WebTextDirection.h
@@ -32,17 +31,17 @@
     private int mFixedHandleX;
     private int mFixedHandleY;
 
-    SelectionHandleController(View parent) {
+    public SelectionHandleController(View parent) {
         mParent = parent;
     }
 
     /** Automatically show selection anchors when text is selected. */
-    void allowAutomaticShowing() {
+    public void allowAutomaticShowing() {
         mAllowAutomaticShowing = true;
     }
 
     /** Hide selection anchors, and don't automatically show them. */
-    void hideAndDisallowAutomaticShowing() {
+    public void hideAndDisallowAutomaticShowing() {
         hide();
         mAllowAutomaticShowing = false;
     }
@@ -101,7 +100,7 @@
     /**
      * @return true iff this controller is being used to drag either the selection start or end.
      */
-    boolean isDragging() {
+    public boolean isDragging() {
         return (mStartHandle != null && mStartHandle.isDragging()) ||
                (mEndHandle != null && mEndHandle.isDragging());
     }
@@ -121,17 +120,8 @@
      * @param x The start handle position X in physical pixels.
      * @param y The start handle position Y in physical pixels.
      */
-    void setStartHandlePosition(int x, int y) {
-        mStartHandle.positionAt(x, y);
-    }
-
-    /**
-     * Moves the start handle so that it points at the given coordinates.
-     * @param x The start handle position X in physical pixels.
-     * @param y The start handle position Y in physical pixels.
-     */
-    void setStartHandlePosition(float x, float y) {
-        setStartHandlePosition((int) x, (int) y);
+    public void setStartHandlePosition(float x, float y) {
+        mStartHandle.positionAt((int) x, (int) y);
     }
 
     /**
@@ -139,24 +129,15 @@
      * @param x The end handle position X in physical pixels.
      * @param y The end handle position Y in physical pixels.
      */
-    void setEndHandlePosition(int x, int y) {
-        mEndHandle.positionAt(x, y);
-    }
-
-    /**
-     * Moves the end handle so that it points at the given coordinates.
-     * @param x The end handle position X in physical pixels.
-     * @param y The end handle position Y in physical pixels.
-     */
-    void setEndHandlePosition(float x, float y) {
-        setEndHandlePosition((int) x, (int) y);
+    public void setEndHandlePosition(float x, float y) {
+        mEndHandle.positionAt((int) x, (int) y);
     }
 
     /**
      * If the handles are not visible, sets their visibility to View.VISIBLE and begins fading them
      * in.
      */
-    void beginHandleFadeIn() {
+    public void beginHandleFadeIn() {
         mStartHandle.beginFadeIn();
         mEndHandle.beginFadeIn();
     }
@@ -164,7 +145,7 @@
     /**
      * Sets the start and end handles to the given visibility.
      */
-    void setHandleVisibility(int visibility) {
+    public void setHandleVisibility(int visibility) {
         mStartHandle.setVisibility(visibility);
         mEndHandle.setVisibility(visibility);
     }
@@ -175,7 +156,7 @@
      * @param startDir Direction (left/right) of start handle.
      * @param endDir Direction (left/right) of end handle.
      */
-    void onSelectionChanged(int startDir, int endDir) {
+    public void onSelectionChanged(int startDir, int endDir) {
         if (mAllowAutomaticShowing) {
             showHandles(startDir, endDir);
         }
@@ -189,7 +170,7 @@
      * @param startDir Direction (left/right) of start handle.
      * @param endDir Direction (left/right) of end handle.
      */
-    void showHandles(int startDir, int endDir) {
+    public void showHandles(int startDir, int endDir) {
         createHandlesIfNeeded(startDir, endDir);
         showHandlesIfNeeded();
     }
diff --git a/content/public/android/java/src/org/chromium/content/common/CommandLine.java b/content/public/android/java/src/org/chromium/content/common/CommandLine.java
index 32ae2cd..83cb348 100644
--- a/content/public/android/java/src/org/chromium/content/common/CommandLine.java
+++ b/content/public/android/java/src/org/chromium/content/common/CommandLine.java
@@ -67,6 +67,9 @@
     // How much of the top controls need to be hidden before they will auto hide.
     public static final String TOP_CONTROLS_HIDE_THRESHOLD = "top-controls-hide-threshold";
 
+    // Native switch - chrome_switches::kEnableInstantExtendedAPI
+    public static final String ENABLE_INSTANT_EXTENDED_API = "enable-instant-extended-api";
+
     // Public abstract interface, implemented in derived classes.
     // All these methods reflect their native-side counterparts.
     /**
diff --git a/content/public/android/java/src/org/chromium/content/common/PerfTraceEvent.java b/content/public/android/java/src/org/chromium/content/common/PerfTraceEvent.java
index 11e24b9..6516efa 100644
--- a/content/public/android/java/src/org/chromium/content/common/PerfTraceEvent.java
+++ b/content/public/android/java/src/org/chromium/content/common/PerfTraceEvent.java
@@ -48,7 +48,7 @@
         INSTANT("I");
 
         // The string understood by the trace scripts.
-        private String mTypeStr;
+        private final String mTypeStr;
 
         EventType(String typeStr) {
             mTypeStr = typeStr;
@@ -82,7 +82,7 @@
      *
      * @param strings Event names we will record.
      */
-    public static void setFilter(List<String> strings) {
+    public static synchronized void setFilter(List<String> strings) {
         sFilter = new LinkedList<String>(strings);
     }
 
@@ -143,7 +143,7 @@
      * It is safe to call trace methods without checking if PerfTraceEvent
      * is enabled.
      */
-    public static boolean enabled() {
+    public static synchronized boolean enabled() {
         return sEnabled;
     }
 
@@ -333,7 +333,7 @@
      * @param file Which file to append the performance data to.  If {@code null}, the performance
      *             data will be sent to STDOUT.
      */
-    public static void setOutputFile(File file) {
+    public static synchronized void setOutputFile(File file) {
         sOutputFile = file;
     }
 
diff --git a/content/public/android/java/src/org/chromium/content/common/SurfaceTextureListener.java b/content/public/android/java/src/org/chromium/content/common/SurfaceTextureListener.java
deleted file mode 100644
index d6ed16f..0000000
--- a/content/public/android/java/src/org/chromium/content/common/SurfaceTextureListener.java
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.content.common;
-
-import android.graphics.SurfaceTexture;
-
-import org.chromium.base.CalledByNative;
-import org.chromium.base.JNINamespace;
-
-/**
- * Listener to an android SurfaceTexture object for frame availability.
- */
-@JNINamespace("content")
-class SurfaceTextureListener implements SurfaceTexture.OnFrameAvailableListener {
-    // Used to determine the class instance to dispatch the native call to.
-    private int mNativeSurfaceTextureListener = 0;
-
-    private SurfaceTextureListener(int nativeSurfaceTextureListener) {
-        assert nativeSurfaceTextureListener != 0;
-        mNativeSurfaceTextureListener = nativeSurfaceTextureListener;
-    }
-
-    @Override
-    public void onFrameAvailable(SurfaceTexture surfaceTexture) {
-        nativeFrameAvailable(mNativeSurfaceTextureListener);
-    }
-
-    @Override
-    protected void finalize() throws Throwable {
-        try {
-            nativeDestroy(mNativeSurfaceTextureListener);
-        } finally {
-            super.finalize();
-        }
-    }
-
-    @CalledByNative
-    private static SurfaceTextureListener create(int nativeSurfaceTextureListener) {
-        return new SurfaceTextureListener(nativeSurfaceTextureListener);
-    }
-
-    private native void nativeFrameAvailable(int nativeSurfaceTextureListener);
-    private native void nativeDestroy(int nativeSurfaceTextureListener);
-}
diff --git a/content/public/android/java/src/org/chromium/content/common/TraceEvent.java b/content/public/android/java/src/org/chromium/content/common/TraceEvent.java
index ffd2528..2ee8114 100644
--- a/content/public/android/java/src/org/chromium/content/common/TraceEvent.java
+++ b/content/public/android/java/src/org/chromium/content/common/TraceEvent.java
@@ -74,16 +74,11 @@
             try {
                 Class<?> traceClass = Class.forName("android.os.Trace");
                 long traceTagView = traceClass.getField("TRACE_TAG_VIEW").getLong(null);
-                String propertyTraceTagEnableFlags = (String) traceClass.getField(
-                        "PROPERTY_TRACE_TAG_ENABLEFLAGS").get(null);
-
-                Class<?> systemPropertiesClass = Class.forName("android.os.SystemProperties");
-                Method systemPropertiesGetLongMethod = systemPropertiesClass.getDeclaredMethod(
-                        "getLong", String.class, Long.TYPE);
-                long enabledFlags = (Long) systemPropertiesGetLongMethod.invoke(
-                        null, propertyTraceTagEnableFlags, 0);
-                Log.d("TraceEvent", "New enabled flags: " + enabledFlags);
-                if ((enabledFlags & traceTagView) != 0) {
+                Method isTagEnabledMethod = traceClass.getDeclaredMethod(
+                        "isTagEnabled", Long.TYPE);
+                Boolean viewTagEnabled = (Boolean) isTagEnabledMethod.invoke(null, traceTagView);
+                Log.d("TraceEvent", "View tag enabled: " + viewTagEnabled.booleanValue());
+                if (viewTagEnabled.booleanValue()) {
                     nativeStartATrace();
                     enabled = true;
                 } else {
diff --git a/content/public/android/java/strings/android_content_strings.grd b/content/public/android/java/strings/android_content_strings.grd
index 26c801e..30b3853 100644
--- a/content/public/android/java/strings/android_content_strings.grd
+++ b/content/public/android/java/strings/android_content_strings.grd
@@ -56,6 +56,7 @@
     </messages>
   </release>
   <translations>
+    <file lang="am" path="translations/android_content_strings_am.xtb" />
     <file lang="ar" path="translations/android_content_strings_ar.xtb" />
     <file lang="bg" path="translations/android_content_strings_bg.xtb" />
     <file lang="ca" path="translations/android_content_strings_ca.xtb" />
@@ -91,6 +92,7 @@
     <file lang="sl" path="translations/android_content_strings_sl.xtb" />
     <file lang="sr" path="translations/android_content_strings_sr.xtb" />
     <file lang="sv" path="translations/android_content_strings_sv.xtb" />
+    <file lang="sw" path="translations/android_content_strings_sw.xtb" />
     <file lang="th" path="translations/android_content_strings_th.xtb" />
     <file lang="tr" path="translations/android_content_strings_tr.xtb" />
     <file lang="uk" path="translations/android_content_strings_uk.xtb" />
@@ -99,47 +101,49 @@
     <file lang="zh-TW" path="translations/android_content_strings_zh-TW.xtb" />
   </translations>
   <outputs>
-    <output filename="values-ar/strings.xml" lang="ar" type="android" />
-    <output filename="values-bg/strings.xml" lang="bg" type="android" />
-    <output filename="values-ca/strings.xml" lang="ca" type="android" />
-    <output filename="values-cs/strings.xml" lang="cs" type="android" />
-    <output filename="values-da/strings.xml" lang="da" type="android" />
-    <output filename="values-de/strings.xml" lang="de" type="android" />
-    <output filename="values-el/strings.xml" lang="el" type="android" />
-    <output filename="values/strings.xml" lang="en" type="android" />
-    <output filename="values-en-rGB/strings.xml" lang="en-GB" type="android" />
-    <output filename="values-es/strings.xml" lang="es" type="android" />
-    <output filename="values-es-rUS/strings.xml" lang="es-419" type="android" />
-    <output filename="values-fa/strings.xml" lang="fa" type="android" />
-    <output filename="values-fi/strings.xml" lang="fi" type="android" />
-    <output filename="values-tl/strings.xml" lang="fil" type="android" />
-    <output filename="values-fr/strings.xml" lang="fr" type="android" />
-    <output filename="values-hi/strings.xml" lang="hi" type="android" />
-    <output filename="values-hr/strings.xml" lang="hr" type="android" />
-    <output filename="values-hu/strings.xml" lang="hu" type="android" />
-    <output filename="values-in/strings.xml" lang="id" type="android" />
-    <output filename="values-it/strings.xml" lang="it" type="android" />
-    <output filename="values-iw/strings.xml" lang="iw" type="android" />
-    <output filename="values-ja/strings.xml" lang="ja" type="android" />
-    <output filename="values-ko/strings.xml" lang="ko" type="android" />
-    <output filename="values-lt/strings.xml" lang="lt" type="android" />
-    <output filename="values-lv/strings.xml" lang="lv" type="android" />
-    <output filename="values-nl/strings.xml" lang="nl" type="android" />
-    <output filename="values-nb/strings.xml" lang="no" type="android" />
-    <output filename="values-pl/strings.xml" lang="pl" type="android" />
-    <output filename="values-pt-rBR/strings.xml" lang="pt-BR" type="android" />
-    <output filename="values-pt-rPT/strings.xml" lang="pt-PT" type="android" />
-    <output filename="values-ro/strings.xml" lang="ro" type="android" />
-    <output filename="values-ru/strings.xml" lang="ru" type="android" />
-    <output filename="values-sk/strings.xml" lang="sk" type="android" />
-    <output filename="values-sl/strings.xml" lang="sl" type="android" />
-    <output filename="values-sr/strings.xml" lang="sr" type="android" />
-    <output filename="values-sv/strings.xml" lang="sv" type="android" />
-    <output filename="values-th/strings.xml" lang="th" type="android" />
-    <output filename="values-tr/strings.xml" lang="tr" type="android" />
-    <output filename="values-uk/strings.xml" lang="uk" type="android" />
-    <output filename="values-vi/strings.xml" lang="vi" type="android" />
-    <output filename="values-zh-rCN/strings.xml" lang="zh-CN" type="android" />
-    <output filename="values-zh-rTW/strings.xml" lang="zh-TW" type="android" />
+    <output filename="values-am/android_content_strings.xml" lang="am" type="android" />
+    <output filename="values-ar/android_content_strings.xml" lang="ar" type="android" />
+    <output filename="values-bg/android_content_strings.xml" lang="bg" type="android" />
+    <output filename="values-ca/android_content_strings.xml" lang="ca" type="android" />
+    <output filename="values-cs/android_content_strings.xml" lang="cs" type="android" />
+    <output filename="values-da/android_content_strings.xml" lang="da" type="android" />
+    <output filename="values-de/android_content_strings.xml" lang="de" type="android" />
+    <output filename="values-el/android_content_strings.xml" lang="el" type="android" />
+    <output filename="values/android_content_strings.xml" lang="en" type="android" />
+    <output filename="values-en-rGB/android_content_strings.xml" lang="en-GB" type="android" />
+    <output filename="values-es/android_content_strings.xml" lang="es" type="android" />
+    <output filename="values-es-rUS/android_content_strings.xml" lang="es-419" type="android" />
+    <output filename="values-fa/android_content_strings.xml" lang="fa" type="android" />
+    <output filename="values-fi/android_content_strings.xml" lang="fi" type="android" />
+    <output filename="values-tl/android_content_strings.xml" lang="fil" type="android" />
+    <output filename="values-fr/android_content_strings.xml" lang="fr" type="android" />
+    <output filename="values-hi/android_content_strings.xml" lang="hi" type="android" />
+    <output filename="values-hr/android_content_strings.xml" lang="hr" type="android" />
+    <output filename="values-hu/android_content_strings.xml" lang="hu" type="android" />
+    <output filename="values-in/android_content_strings.xml" lang="id" type="android" />
+    <output filename="values-it/android_content_strings.xml" lang="it" type="android" />
+    <output filename="values-iw/android_content_strings.xml" lang="iw" type="android" />
+    <output filename="values-ja/android_content_strings.xml" lang="ja" type="android" />
+    <output filename="values-ko/android_content_strings.xml" lang="ko" type="android" />
+    <output filename="values-lt/android_content_strings.xml" lang="lt" type="android" />
+    <output filename="values-lv/android_content_strings.xml" lang="lv" type="android" />
+    <output filename="values-nl/android_content_strings.xml" lang="nl" type="android" />
+    <output filename="values-nb/android_content_strings.xml" lang="no" type="android" />
+    <output filename="values-pl/android_content_strings.xml" lang="pl" type="android" />
+    <output filename="values-pt-rBR/android_content_strings.xml" lang="pt-BR" type="android" />
+    <output filename="values-pt-rPT/android_content_strings.xml" lang="pt-PT" type="android" />
+    <output filename="values-ro/android_content_strings.xml" lang="ro" type="android" />
+    <output filename="values-ru/android_content_strings.xml" lang="ru" type="android" />
+    <output filename="values-sk/android_content_strings.xml" lang="sk" type="android" />
+    <output filename="values-sl/android_content_strings.xml" lang="sl" type="android" />
+    <output filename="values-sr/android_content_strings.xml" lang="sr" type="android" />
+    <output filename="values-sv/android_content_strings.xml" lang="sv" type="android" />
+    <output filename="values-sw/android_content_strings.xml" lang="sw" type="android" />
+    <output filename="values-th/android_content_strings.xml" lang="th" type="android" />
+    <output filename="values-tr/android_content_strings.xml" lang="tr" type="android" />
+    <output filename="values-uk/android_content_strings.xml" lang="uk" type="android" />
+    <output filename="values-vi/android_content_strings.xml" lang="vi" type="android" />
+    <output filename="values-zh-rCN/android_content_strings.xml" lang="zh-CN" type="android" />
+    <output filename="values-zh-rTW/android_content_strings.xml" lang="zh-TW" type="android" />
   </outputs>
-</grit>
\ No newline at end of file
+</grit>
diff --git a/content/public/android/java/strings/translations/android_content_strings_am.xtb b/content/public/android/java/strings/translations/android_content_strings_am.xtb
new file mode 100644
index 0000000..cc8a0c3
--- /dev/null
+++ b/content/public/android/java/strings/translations/android_content_strings_am.xtb
@@ -0,0 +1,21 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="am">
+<translation id="6015796118275082299">ዓመት</translation>
+<translation id="1256337885411059545">ቪዲዮ ማጫወት አልተቻለም</translation>
+<translation id="7821540960913969614">ቀን ያዘጋጁ</translation>
+<translation id="4932733599132424254">ቀን</translation>
+<translation id="6727102863431372879">አዘጋጅ</translation>
+<translation id="273860350361291195">ይቅርታ፣ ይህ ቪዲዮ ወደዚህ መሣሪያ በዥረት ለመልቀቅ ልክ የሆነ አይደለም።</translation>
+<translation id="2410828433627930127">ይቅርታ፣ ይህ ቪዲዮ ሊጫወት አልቻለም።</translation>
+<translation id="8987927404178983737">ወር</translation>
+<translation id="2532336938189706096">የድር ዕይታ</translation>
+<translation id="7096034533295549981">ቪዲዮን በመጫን ላይ</translation>
+<translation id="1542044944667958430">የድር ፍለጋ</translation>
+<translation id="6527303717912515753">አጋራ</translation>
+<translation id="2841013758207633010">ሰዓት</translation>
+<translation id="6643016212128521049">አጽዳ</translation>
+<translation id="7781164152564914424">ወር ያዘጋጁ</translation>
+<translation id="6965382102122355670">ይሁን</translation>
+<translation id="6444070574980481588">ቀን እና ሰዓት ያዘጋጁ</translation>
+</translationbundle>
\ No newline at end of file
diff --git a/content/public/android/java/strings/translations/android_content_strings_ar.xtb b/content/public/android/java/strings/translations/android_content_strings_ar.xtb
index 5c4cfce..e9615ba 100644
--- a/content/public/android/java/strings/translations/android_content_strings_ar.xtb
+++ b/content/public/android/java/strings/translations/android_content_strings_ar.xtb
@@ -1,14 +1,14 @@
 <?xml version="1.0" ?>
 <!DOCTYPE translationbundle>
 <translationbundle lang="ar">
-<translation id="6015796118275082299">عام</translation>
+<translation id="6015796118275082299">السنة</translation>
 <translation id="1256337885411059545">لا يمكن تشغيل الفيديو</translation>
 <translation id="7821540960913969614">تعيين التاريخ</translation>
 <translation id="4932733599132424254">التاريخ</translation>
 <translation id="6727102863431372879">تعيين</translation>
-<translation id="273860350361291195">عذرًا، هذا الفيديو غير صالح للبث على هذا الجهاز.</translation>
+<translation id="273860350361291195">عذرًا، هذا الفيديو غير صالح للبث إلى هذا الجهاز.</translation>
 <translation id="2410828433627930127">عذرًا، لا يمكن تشغيل هذا الفيديو.</translation>
-<translation id="8987927404178983737">الشهر</translation>
+<translation id="8987927404178983737">شهر</translation>
 <translation id="2532336938189706096">عرض الويب</translation>
 <translation id="7096034533295549981">تحميل الفيديو</translation>
 <translation id="1542044944667958430">بحث الويب</translation>
diff --git a/content/public/android/java/strings/translations/android_content_strings_bg.xtb b/content/public/android/java/strings/translations/android_content_strings_bg.xtb
index 5815bb9..7f21d6e 100644
--- a/content/public/android/java/strings/translations/android_content_strings_bg.xtb
+++ b/content/public/android/java/strings/translations/android_content_strings_bg.xtb
@@ -6,8 +6,8 @@
 <translation id="7821540960913969614">Задаване на датата</translation>
 <translation id="4932733599132424254">Дата</translation>
 <translation id="6727102863431372879">Задаване</translation>
-<translation id="273860350361291195">Клипът не е валиден за поточно предаване към у-вото.</translation>
-<translation id="2410828433627930127">Клипът не може да се пусне.</translation>
+<translation id="273860350361291195">За съжаление видеоклипът не е валиден за поточно предаване към устройството.</translation>
+<translation id="2410828433627930127">За съжаление видеоклипът не може да се пусне.</translation>
 <translation id="8987927404178983737">Месец</translation>
 <translation id="2532336938189706096">Изглед в мрежата</translation>
 <translation id="7096034533295549981">Клип: Зарежда се</translation>
diff --git a/content/public/android/java/strings/translations/android_content_strings_ca.xtb b/content/public/android/java/strings/translations/android_content_strings_ca.xtb
index 39923c4..10adc64 100644
--- a/content/public/android/java/strings/translations/android_content_strings_ca.xtb
+++ b/content/public/android/java/strings/translations/android_content_strings_ca.xtb
@@ -3,10 +3,10 @@
 <translationbundle lang="ca">
 <translation id="6015796118275082299">Any</translation>
 <translation id="1256337885411059545">No es pot reproduir el vídeo</translation>
-<translation id="7821540960913969614">Establiment de la data</translation>
+<translation id="7821540960913969614">Definir la data</translation>
 <translation id="4932733599132424254">Data</translation>
 <translation id="6727102863431372879">Defineix</translation>
-<translation id="273860350361291195">Aquest vídeo no és vàlid per a la transmissió en aquest dispositiu.</translation>
+<translation id="273860350361291195">Aquest vídeo no és vàlid per a l'emissió en aquest dispositiu.</translation>
 <translation id="2410828433627930127">No es pot reproduir aquest vídeo.</translation>
 <translation id="8987927404178983737">Mes</translation>
 <translation id="2532336938189706096">Visualització web</translation>
@@ -15,7 +15,7 @@
 <translation id="6527303717912515753">Comparteix</translation>
 <translation id="2841013758207633010">Hora</translation>
 <translation id="6643016212128521049">Esborra</translation>
-<translation id="7781164152564914424">Establiment de mes</translation>
+<translation id="7781164152564914424">Definir el mes</translation>
 <translation id="6965382102122355670">D'acord</translation>
-<translation id="6444070574980481588">Establiment de data i d'hora</translation>
+<translation id="6444070574980481588">Definir la data i l'hora</translation>
 </translationbundle>
\ No newline at end of file
diff --git a/content/public/android/java/strings/translations/android_content_strings_cs.xtb b/content/public/android/java/strings/translations/android_content_strings_cs.xtb
index b6f3407..489539f 100644
--- a/content/public/android/java/strings/translations/android_content_strings_cs.xtb
+++ b/content/public/android/java/strings/translations/android_content_strings_cs.xtb
@@ -6,9 +6,9 @@
 <translation id="7821540960913969614">Nastavení data</translation>
 <translation id="4932733599132424254">Datum</translation>
 <translation id="6727102863431372879">Nastavit</translation>
-<translation id="273860350361291195">Video do zař. nelze streamovat.</translation>
+<translation id="273860350361291195">Video do zařizení nelze streamovat.</translation>
 <translation id="2410828433627930127">Toto video nelze přehrát.</translation>
-<translation id="8987927404178983737">Měsíc</translation>
+<translation id="8987927404178983737">měsíc</translation>
 <translation id="2532336938189706096">Webové zobrazení</translation>
 <translation id="7096034533295549981">Načítání videa</translation>
 <translation id="1542044944667958430">Vyhledávání na webu</translation>
diff --git a/content/public/android/java/strings/translations/android_content_strings_da.xtb b/content/public/android/java/strings/translations/android_content_strings_da.xtb
index f6aaa2c..b4a8951 100644
--- a/content/public/android/java/strings/translations/android_content_strings_da.xtb
+++ b/content/public/android/java/strings/translations/android_content_strings_da.xtb
@@ -5,7 +5,7 @@
 <translation id="1256337885411059545">Videoen kan ikke afspilles</translation>
 <translation id="7821540960913969614">Indstil dato</translation>
 <translation id="4932733599132424254">Dato</translation>
-<translation id="6727102863431372879">Angiv</translation>
+<translation id="6727102863431372879">Indstil</translation>
 <translation id="273860350361291195">Denne video er ikke gyldig til streaming på denne enhed.</translation>
 <translation id="2410828433627930127">Denne video kan ikke afspilles.</translation>
 <translation id="8987927404178983737">Måned</translation>
@@ -13,7 +13,7 @@
 <translation id="7096034533295549981">Indlæser video</translation>
 <translation id="1542044944667958430">Websøgning</translation>
 <translation id="6527303717912515753">Del</translation>
-<translation id="2841013758207633010">Tid</translation>
+<translation id="2841013758207633010">Tidspunkt</translation>
 <translation id="6643016212128521049">Ryd</translation>
 <translation id="7781164152564914424">Angiv måned</translation>
 <translation id="6965382102122355670">OK</translation>
diff --git a/content/public/android/java/strings/translations/android_content_strings_de.xtb b/content/public/android/java/strings/translations/android_content_strings_de.xtb
index f14eb37..d8f5250 100644
--- a/content/public/android/java/strings/translations/android_content_strings_de.xtb
+++ b/content/public/android/java/strings/translations/android_content_strings_de.xtb
@@ -5,7 +5,7 @@
 <translation id="1256337885411059545">Videowiedergabe nicht möglich</translation>
 <translation id="7821540960913969614">Datum festlegen</translation>
 <translation id="4932733599132424254">Datum</translation>
-<translation id="6727102863431372879">Festlegen</translation>
+<translation id="6727102863431372879">Übernehmen</translation>
 <translation id="273860350361291195">Dieses Video ist zum Streaming auf diesem Gerät ungültig.</translation>
 <translation id="2410828433627930127">Videowiedergabe nicht möglich</translation>
 <translation id="8987927404178983737">Monat</translation>
@@ -13,7 +13,7 @@
 <translation id="7096034533295549981">Lädt Video...</translation>
 <translation id="1542044944667958430">Websuche</translation>
 <translation id="6527303717912515753">Teilen</translation>
-<translation id="2841013758207633010">Zeit</translation>
+<translation id="2841013758207633010">Uhrzeit</translation>
 <translation id="6643016212128521049">Löschen</translation>
 <translation id="7781164152564914424">Monat einstellen</translation>
 <translation id="6965382102122355670">OK</translation>
diff --git a/content/public/android/java/strings/translations/android_content_strings_es-419.xtb b/content/public/android/java/strings/translations/android_content_strings_es-419.xtb
index da571d8..f7b8849 100644
--- a/content/public/android/java/strings/translations/android_content_strings_es-419.xtb
+++ b/content/public/android/java/strings/translations/android_content_strings_es-419.xtb
@@ -5,8 +5,8 @@
 <translation id="1256337885411059545">No se puede reproducir el video.</translation>
 <translation id="7821540960913969614">Establecer una fecha</translation>
 <translation id="4932733599132424254">Fecha</translation>
-<translation id="6727102863431372879">Configurar</translation>
-<translation id="273860350361291195">Error al transmitir video</translation>
+<translation id="6727102863431372879">Establecer</translation>
+<translation id="273860350361291195">El video no se puede transmitir a este dispositivo.</translation>
 <translation id="2410828433627930127">El video no se puede reproducir.</translation>
 <translation id="8987927404178983737">Mes</translation>
 <translation id="2532336938189706096">Vista web</translation>
@@ -15,7 +15,7 @@
 <translation id="6527303717912515753">Compartir</translation>
 <translation id="2841013758207633010">Hora</translation>
 <translation id="6643016212128521049">Borrar</translation>
-<translation id="7781164152564914424">Configurar el mes</translation>
+<translation id="7781164152564914424">Establecer el mes</translation>
 <translation id="6965382102122355670">Aceptar</translation>
-<translation id="6444070574980481588">Configurar fecha y hora</translation>
+<translation id="6444070574980481588">Establecer fecha y hora</translation>
 </translationbundle>
\ No newline at end of file
diff --git a/content/public/android/java/strings/translations/android_content_strings_es.xtb b/content/public/android/java/strings/translations/android_content_strings_es.xtb
index ea53af9..afde6de 100644
--- a/content/public/android/java/strings/translations/android_content_strings_es.xtb
+++ b/content/public/android/java/strings/translations/android_content_strings_es.xtb
@@ -6,15 +6,15 @@
 <translation id="7821540960913969614">Definir fecha</translation>
 <translation id="4932733599132424254">Fecha</translation>
 <translation id="6727102863431372879">Establecer</translation>
-<translation id="273860350361291195">Error al transmitir vídeo</translation>
-<translation id="2410828433627930127">El vídeo no se puede reproducir.</translation>
+<translation id="273860350361291195">Este vídeo no se puede reproducir en este dispositivo.</translation>
+<translation id="2410828433627930127">Este vídeo no se puede reproducir.</translation>
 <translation id="8987927404178983737">Mes</translation>
 <translation id="2532336938189706096">Vista web</translation>
 <translation id="7096034533295549981">Cargando vídeo...</translation>
 <translation id="1542044944667958430">Búsqueda web</translation>
 <translation id="6527303717912515753">Compartir</translation>
-<translation id="2841013758207633010">Hora</translation>
-<translation id="6643016212128521049">Eliminar</translation>
+<translation id="2841013758207633010">Tiempo</translation>
+<translation id="6643016212128521049">Borrar</translation>
 <translation id="7781164152564914424">Establecer mes</translation>
 <translation id="6965382102122355670">Aceptar</translation>
 <translation id="6444070574980481588">Establecer fecha y hora</translation>
diff --git a/content/public/android/java/strings/translations/android_content_strings_fa.xtb b/content/public/android/java/strings/translations/android_content_strings_fa.xtb
index 2bf23c4..8266b88 100644
--- a/content/public/android/java/strings/translations/android_content_strings_fa.xtb
+++ b/content/public/android/java/strings/translations/android_content_strings_fa.xtb
@@ -2,17 +2,17 @@
 <!DOCTYPE translationbundle>
 <translationbundle lang="fa">
 <translation id="6015796118275082299">سال</translation>
-<translation id="1256337885411059545">نمی‌توان ویدئو پخش کرد</translation>
+<translation id="1256337885411059545">نمی‌توان ویدیو پخش کرد</translation>
 <translation id="7821540960913969614">تنظیم تاریخ</translation>
 <translation id="4932733599132424254">تاریخ</translation>
 <translation id="6727102863431372879">تنظیم</translation>
-<translation id="273860350361291195">متأسفیم، این ویدئو برای پخش جریانی بااین دستگاه معتبر نیست.</translation>
-<translation id="2410828433627930127">متأسفیم، این ویدئو پخش نمی‌شود.</translation>
+<translation id="273860350361291195">متأسفانه، این ویدیو برای پخش در این دستگاه معتبر نیست.</translation>
+<translation id="2410828433627930127">متأسفانه، این ویدیو قابل پخش نیست.</translation>
 <translation id="8987927404178983737">ماه</translation>
 <translation id="2532336938189706096">بازدید از وب</translation>
 <translation id="7096034533295549981">بارگیری ویدیو</translation>
 <translation id="1542044944667958430">جستجوی وب</translation>
-<translation id="6527303717912515753">اشتراک‌گذاری</translation>
+<translation id="6527303717912515753">اشتراک‌گذاری‌</translation>
 <translation id="2841013758207633010">زمان</translation>
 <translation id="6643016212128521049">پاک کردن</translation>
 <translation id="7781164152564914424">تنظیم ماه</translation>
diff --git a/content/public/android/java/strings/translations/android_content_strings_fil.xtb b/content/public/android/java/strings/translations/android_content_strings_fil.xtb
index 9d225c5..ffeb50a 100644
--- a/content/public/android/java/strings/translations/android_content_strings_fil.xtb
+++ b/content/public/android/java/strings/translations/android_content_strings_fil.xtb
@@ -6,8 +6,8 @@
 <translation id="7821540960913969614">Magtakda ng petsa</translation>
 <translation id="4932733599132424254">Petsa</translation>
 <translation id="6727102863431372879">Itakda</translation>
-<translation id="273860350361291195">Paumnhn,d wsto strmng dvce vdeo.</translation>
-<translation id="2410828433627930127">Paumanhin, di ma-play video ito.</translation>
+<translation id="273860350361291195">Paumanhin, di-wasto ang video para sa pag-stream sa device na ito.</translation>
+<translation id="2410828433627930127">Paumanhin, hindi mape-play ang video na ito.</translation>
 <translation id="8987927404178983737">Buwan</translation>
 <translation id="2532336938189706096">View ng Web</translation>
 <translation id="7096034533295549981">Nilo-load video</translation>
diff --git a/content/public/android/java/strings/translations/android_content_strings_hi.xtb b/content/public/android/java/strings/translations/android_content_strings_hi.xtb
index 9df7a31..955e22f 100644
--- a/content/public/android/java/strings/translations/android_content_strings_hi.xtb
+++ b/content/public/android/java/strings/translations/android_content_strings_hi.xtb
@@ -6,8 +6,8 @@
 <translation id="7821540960913969614">दिनांक सेट करें</translation>
 <translation id="4932733599132424254">दिनांक</translation>
 <translation id="6727102863431372879">सेट करें</translation>
-<translation id="273860350361291195">उपकरण पर वीडियो स्‍ट्रीम अमान्य.</translation>
-<translation id="2410828433627930127">यह वीडियो नहीं चलाया जा सकता.</translation>
+<translation id="273860350361291195">क्षमा करें, यह वीडियो इस उपकरण पर स्‍ट्रीम करने के लिए मान्य नहीं है.</translation>
+<translation id="2410828433627930127">क्षमा करें, यह वीडियो नहीं चलाया जा सकता.</translation>
 <translation id="8987927404178983737">माह</translation>
 <translation id="2532336938189706096">वेब दृश्य</translation>
 <translation id="7096034533295549981">वीडियो लोड हो रहा है</translation>
diff --git a/content/public/android/java/strings/translations/android_content_strings_hr.xtb b/content/public/android/java/strings/translations/android_content_strings_hr.xtb
index fbb6b66..027da65 100644
--- a/content/public/android/java/strings/translations/android_content_strings_hr.xtb
+++ b/content/public/android/java/strings/translations/android_content_strings_hr.xtb
@@ -6,8 +6,8 @@
 <translation id="7821540960913969614">Postavite datum</translation>
 <translation id="4932733599132424254">Datum</translation>
 <translation id="6727102863431372879">Postavi</translation>
-<translation id="273860350361291195">Video nije valjan za str. na ur.</translation>
-<translation id="2410828433627930127">Videoz. nije moguće reproducir.</translation>
+<translation id="273860350361291195">Video nije valjan za strujanje na uređaj.</translation>
+<translation id="2410828433627930127">Nije moguće reproducirati taj videozapis.</translation>
 <translation id="8987927404178983737">Mjesec</translation>
 <translation id="2532336938189706096">Web-prikaz</translation>
 <translation id="7096034533295549981">Učitavanje videa</translation>
diff --git a/content/public/android/java/strings/translations/android_content_strings_id.xtb b/content/public/android/java/strings/translations/android_content_strings_id.xtb
index beda171..09ce365 100644
--- a/content/public/android/java/strings/translations/android_content_strings_id.xtb
+++ b/content/public/android/java/strings/translations/android_content_strings_id.xtb
@@ -12,7 +12,7 @@
 <translation id="2532336938189706096">Tampilan Web</translation>
 <translation id="7096034533295549981">Memuat video</translation>
 <translation id="1542044944667958430">Penelusuran web</translation>
-<translation id="6527303717912515753">Bagikan</translation>
+<translation id="6527303717912515753">Berbagi</translation>
 <translation id="2841013758207633010">Waktu</translation>
 <translation id="6643016212128521049">Hapus</translation>
 <translation id="7781164152564914424">Setel bulan</translation>
diff --git a/content/public/android/java/strings/translations/android_content_strings_it.xtb b/content/public/android/java/strings/translations/android_content_strings_it.xtb
index b4854bb..086a3db 100644
--- a/content/public/android/java/strings/translations/android_content_strings_it.xtb
+++ b/content/public/android/java/strings/translations/android_content_strings_it.xtb
@@ -13,7 +13,7 @@
 <translation id="7096034533295549981">Caricamento video</translation>
 <translation id="1542044944667958430">Ricerca Google</translation>
 <translation id="6527303717912515753">Condividi</translation>
-<translation id="2841013758207633010">Ora</translation>
+<translation id="2841013758207633010">Data/ora</translation>
 <translation id="6643016212128521049">Cancella</translation>
 <translation id="7781164152564914424">Imposta mese</translation>
 <translation id="6965382102122355670">OK</translation>
diff --git a/content/public/android/java/strings/translations/android_content_strings_ja.xtb b/content/public/android/java/strings/translations/android_content_strings_ja.xtb
index 8205ed0..48a2d03 100644
--- a/content/public/android/java/strings/translations/android_content_strings_ja.xtb
+++ b/content/public/android/java/strings/translations/android_content_strings_ja.xtb
@@ -6,15 +6,15 @@
 <translation id="7821540960913969614">日付の設定</translation>
 <translation id="4932733599132424254">日付</translation>
 <translation id="6727102863431372879">設定</translation>
-<translation id="273860350361291195">この動画はご使用の端末ではストリーミングできません。</translation>
+<translation id="273860350361291195">この動画はご使用のデバイスではストリーミングできません。</translation>
 <translation id="2410828433627930127">この動画は再生できません。</translation>
 <translation id="8987927404178983737">月</translation>
 <translation id="2532336938189706096">ウェブ表示</translation>
 <translation id="7096034533295549981">動画を読み込み中</translation>
 <translation id="1542044944667958430">ウェブ検索</translation>
 <translation id="6527303717912515753">共有</translation>
-<translation id="2841013758207633010">時間</translation>
-<translation id="6643016212128521049">消去</translation>
+<translation id="2841013758207633010">時刻</translation>
+<translation id="6643016212128521049">クリア</translation>
 <translation id="7781164152564914424">月の設定</translation>
 <translation id="6965382102122355670">OK</translation>
 <translation id="6444070574980481588">日時の設定</translation>
diff --git a/content/public/android/java/strings/translations/android_content_strings_lt.xtb b/content/public/android/java/strings/translations/android_content_strings_lt.xtb
index eb559ab..06603f9 100644
--- a/content/public/android/java/strings/translations/android_content_strings_lt.xtb
+++ b/content/public/android/java/strings/translations/android_content_strings_lt.xtb
@@ -6,8 +6,8 @@
 <translation id="7821540960913969614">Nustatykite datą</translation>
 <translation id="4932733599132424254">Data</translation>
 <translation id="6727102863431372879">Nustatyti</translation>
-<translation id="273860350361291195">Deja, šis vaizdo įrašas netinka perduoti srautu į šį įrenginį.</translation>
-<translation id="2410828433627930127">Vaizdo įrašo paleisti nepavyksta</translation>
+<translation id="273860350361291195">Apgailestaujame, šis vaizdo įrašas yra netinkamas perduoti srautu į šį įrenginį.</translation>
+<translation id="2410828433627930127">Apgailestaujame, šis vaizdo įrašas negali būti paleistas.</translation>
 <translation id="8987927404178983737">Mėnuo</translation>
 <translation id="2532336938189706096">Žiniatinklio rodinys</translation>
 <translation id="7096034533295549981">Įkel. v. įrašas</translation>
diff --git a/content/public/android/java/strings/translations/android_content_strings_lv.xtb b/content/public/android/java/strings/translations/android_content_strings_lv.xtb
index 49917d9..17b6175 100644
--- a/content/public/android/java/strings/translations/android_content_strings_lv.xtb
+++ b/content/public/android/java/strings/translations/android_content_strings_lv.xtb
@@ -2,12 +2,12 @@
 <!DOCTYPE translationbundle>
 <translationbundle lang="lv">
 <translation id="6015796118275082299">Gads</translation>
-<translation id="1256337885411059545">Nevar demonstrēt videoklipu</translation>
+<translation id="1256337885411059545">Nevar demonstrēt videoklipu.</translation>
 <translation id="7821540960913969614">Datuma iestatīšana</translation>
 <translation id="4932733599132424254">Datums</translation>
 <translation id="6727102863431372879">Iestatīt</translation>
-<translation id="273860350361291195">Šo video nevar straumēt ierīcē.</translation>
-<translation id="2410828433627930127">Šo video nevar demonstrēt.</translation>
+<translation id="273860350361291195">Diemžēl šo videoklipu nevar straumēt šajā ierīcē.</translation>
+<translation id="2410828433627930127">Diemžēl šo videoklipu nevar demonstrēt.</translation>
 <translation id="8987927404178983737">Mēnesis</translation>
 <translation id="2532336938189706096">Tīmekļa skatījums</translation>
 <translation id="7096034533295549981">Video ielāde</translation>
@@ -15,7 +15,7 @@
 <translation id="6527303717912515753">Kopīgot</translation>
 <translation id="2841013758207633010">Laiks</translation>
 <translation id="6643016212128521049">Notīrīt</translation>
-<translation id="7781164152564914424">Iestatīt mēnesi</translation>
+<translation id="7781164152564914424">Mēneša iestatīšana</translation>
 <translation id="6965382102122355670">Labi</translation>
-<translation id="6444070574980481588">Iestatīt datumu un laiku</translation>
+<translation id="6444070574980481588">Datuma un laika iestatīšana</translation>
 </translationbundle>
\ No newline at end of file
diff --git a/content/public/android/java/strings/translations/android_content_strings_no.xtb b/content/public/android/java/strings/translations/android_content_strings_no.xtb
index 1847d96..c3efd81 100644
--- a/content/public/android/java/strings/translations/android_content_strings_no.xtb
+++ b/content/public/android/java/strings/translations/android_content_strings_no.xtb
@@ -6,7 +6,7 @@
 <translation id="7821540960913969614">Angi dato</translation>
 <translation id="4932733599132424254">Dato</translation>
 <translation id="6727102863431372879">Angi</translation>
-<translation id="273860350361291195">Videoen er ikke gyldig for direkteavsp. på enheten.</translation>
+<translation id="273860350361291195">Videoen er ikke gyldig for direkteavspilling på enheten.</translation>
 <translation id="2410828433627930127">Videoen kan ikke spilles av.</translation>
 <translation id="8987927404178983737">Måned</translation>
 <translation id="2532336938189706096">Nettvisning</translation>
diff --git a/content/public/android/java/strings/translations/android_content_strings_pl.xtb b/content/public/android/java/strings/translations/android_content_strings_pl.xtb
index 2ad7806..04efc58 100644
--- a/content/public/android/java/strings/translations/android_content_strings_pl.xtb
+++ b/content/public/android/java/strings/translations/android_content_strings_pl.xtb
@@ -2,12 +2,12 @@
 <!DOCTYPE translationbundle>
 <translationbundle lang="pl">
 <translation id="6015796118275082299">Rok</translation>
-<translation id="1256337885411059545">Nie można odtworzyć filmu.</translation>
+<translation id="1256337885411059545">Nie można odtworzyć filmu</translation>
 <translation id="7821540960913969614">Ustaw datę</translation>
 <translation id="4932733599132424254">Data</translation>
 <translation id="6727102863431372879">Ustaw</translation>
-<translation id="273860350361291195">Przepraszamy, ten film nie nadaje się do strumieniowego przesyłania do tego urządzenia.</translation>
-<translation id="2410828433627930127">Niestety, nie można odtworzyć tego filmu.</translation>
+<translation id="273860350361291195">Ten film nie nadaje się do strumieniowego przesyłania do tego urządzenia.</translation>
+<translation id="2410828433627930127">Nie można odtworzyć tego filmu.</translation>
 <translation id="8987927404178983737">Miesiąc</translation>
 <translation id="2532336938189706096">Widok sieci</translation>
 <translation id="7096034533295549981">Wczytuję film</translation>
diff --git a/content/public/android/java/strings/translations/android_content_strings_pt-BR.xtb b/content/public/android/java/strings/translations/android_content_strings_pt-BR.xtb
index c7e5410..7643b5e 100644
--- a/content/public/android/java/strings/translations/android_content_strings_pt-BR.xtb
+++ b/content/public/android/java/strings/translations/android_content_strings_pt-BR.xtb
@@ -11,7 +11,7 @@
 <translation id="8987927404178983737">Mês</translation>
 <translation id="2532336938189706096">Visualização da Web</translation>
 <translation id="7096034533295549981">Carregando vídeo</translation>
-<translation id="1542044944667958430">Pesquisa na web</translation>
+<translation id="1542044944667958430">Pesquisa na Web</translation>
 <translation id="6527303717912515753">Compartilhar</translation>
 <translation id="2841013758207633010">Tempo</translation>
 <translation id="6643016212128521049">Limpar</translation>
diff --git a/content/public/android/java/strings/translations/android_content_strings_pt-PT.xtb b/content/public/android/java/strings/translations/android_content_strings_pt-PT.xtb
index f8ed30b..0f8206b 100644
--- a/content/public/android/java/strings/translations/android_content_strings_pt-PT.xtb
+++ b/content/public/android/java/strings/translations/android_content_strings_pt-PT.xtb
@@ -6,14 +6,14 @@
 <translation id="7821540960913969614">Definir data</translation>
 <translation id="4932733599132424254">Data</translation>
 <translation id="6727102863431372879">Definir</translation>
-<translation id="273860350361291195">Lamentamos, este vídeo não é válido para transmissão em fluxo contínuo neste aparelho.</translation>
-<translation id="2410828433627930127">Lamentamos, não é possível reproduzir este vídeo.</translation>
+<translation id="273860350361291195">Lamentamos, este vídeo não é válido para transmissão em fluxo contínuo neste dispositivo.</translation>
+<translation id="2410828433627930127">Lamentamos, mas não é possível reproduzir este vídeo.</translation>
 <translation id="8987927404178983737">Mês</translation>
 <translation id="2532336938189706096">Visualização na Web</translation>
 <translation id="7096034533295549981">A carregar vídeo</translation>
 <translation id="1542044944667958430">Pesquisa Web</translation>
 <translation id="6527303717912515753">Partilhar</translation>
-<translation id="2841013758207633010">Tempo</translation>
+<translation id="2841013758207633010">Hora</translation>
 <translation id="6643016212128521049">Limpar</translation>
 <translation id="7781164152564914424">Definir mês</translation>
 <translation id="6965382102122355670">OK</translation>
diff --git a/content/public/android/java/strings/translations/android_content_strings_ro.xtb b/content/public/android/java/strings/translations/android_content_strings_ro.xtb
index db352c1..9329a5c 100644
--- a/content/public/android/java/strings/translations/android_content_strings_ro.xtb
+++ b/content/public/android/java/strings/translations/android_content_strings_ro.xtb
@@ -1,20 +1,20 @@
 <?xml version="1.0" ?>
 <!DOCTYPE translationbundle>
 <translationbundle lang="ro">
-<translation id="6015796118275082299">An</translation>
+<translation id="6015796118275082299">Anul</translation>
 <translation id="1256337885411059545">Nu se poate reda videoclipul</translation>
 <translation id="7821540960913969614">Setați data</translation>
-<translation id="4932733599132424254">Dată</translation>
+<translation id="4932733599132424254">Data</translation>
 <translation id="6727102863431372879">Setați</translation>
-<translation id="273860350361291195">Video nevalid pt. flux dispoz.</translation>
-<translation id="2410828433627930127">Acest clip nu poate fi redat.</translation>
-<translation id="8987927404178983737">Lună</translation>
+<translation id="273860350361291195">Videoclipul nu este valid pentru fluxul către acest dispozitiv.</translation>
+<translation id="2410828433627930127">Ne pare rău, acest videoclip nu poate fi redat.</translation>
+<translation id="8987927404178983737">Luna</translation>
 <translation id="2532336938189706096">Vizualizare pe web</translation>
 <translation id="7096034533295549981">Încărcare video</translation>
 <translation id="1542044944667958430">Căutare pe web</translation>
-<translation id="6527303717912515753">Distribuiți</translation>
-<translation id="2841013758207633010">Oră</translation>
-<translation id="6643016212128521049">Goliți</translation>
+<translation id="6527303717912515753">Trimiteți</translation>
+<translation id="2841013758207633010">Ora</translation>
+<translation id="6643016212128521049">Ștergeţi</translation>
 <translation id="7781164152564914424">Setați luna</translation>
 <translation id="6965382102122355670">OK</translation>
 <translation id="6444070574980481588">Setați data și ora</translation>
diff --git a/content/public/android/java/strings/translations/android_content_strings_ru.xtb b/content/public/android/java/strings/translations/android_content_strings_ru.xtb
index d4dd3f7..6027b0a 100644
--- a/content/public/android/java/strings/translations/android_content_strings_ru.xtb
+++ b/content/public/android/java/strings/translations/android_content_strings_ru.xtb
@@ -5,17 +5,17 @@
 <translation id="1256337885411059545">Не удается воспроизвести видео</translation>
 <translation id="7821540960913969614">Установка даты</translation>
 <translation id="4932733599132424254">Дата</translation>
-<translation id="6727102863431372879">Применить</translation>
-<translation id="273860350361291195">Невозможно воспроизвести видео.</translation>
+<translation id="6727102863431372879">Установить</translation>
+<translation id="273860350361291195">Невозможно воспроизвести видео на этом устройстве.</translation>
 <translation id="2410828433627930127">Невозможно воспроизвести видео.</translation>
 <translation id="8987927404178983737">Месяц</translation>
 <translation id="2532336938189706096">Веб-версия</translation>
 <translation id="7096034533295549981">Загрузка видео…</translation>
-<translation id="1542044944667958430">Результаты веб-поиска</translation>
+<translation id="1542044944667958430">Веб-поиск</translation>
 <translation id="6527303717912515753">Поделиться</translation>
 <translation id="2841013758207633010">Время</translation>
 <translation id="6643016212128521049">Очистить</translation>
-<translation id="7781164152564914424">Установите месяц</translation>
+<translation id="7781164152564914424">Установка месяца</translation>
 <translation id="6965382102122355670">ОК</translation>
-<translation id="6444070574980481588">Установите дату и время</translation>
+<translation id="6444070574980481588">Установка даты и времени</translation>
 </translationbundle>
\ No newline at end of file
diff --git a/content/public/android/java/strings/translations/android_content_strings_sk.xtb b/content/public/android/java/strings/translations/android_content_strings_sk.xtb
index d9832ae..73ec836 100644
--- a/content/public/android/java/strings/translations/android_content_strings_sk.xtb
+++ b/content/public/android/java/strings/translations/android_content_strings_sk.xtb
@@ -2,12 +2,12 @@
 <!DOCTYPE translationbundle>
 <translationbundle lang="sk">
 <translation id="6015796118275082299">Rok</translation>
-<translation id="1256337885411059545">Video sa nepodarilo prehrať</translation>
+<translation id="1256337885411059545">Video sa nedá prehrať</translation>
 <translation id="7821540960913969614">Nastaviť dátum</translation>
 <translation id="4932733599132424254">Dátum</translation>
 <translation id="6727102863431372879">Nastaviť</translation>
-<translation id="273860350361291195">Video sa nedá stream. do zariad.</translation>
-<translation id="2410828433627930127">Toto video sa nedá prehrať.</translation>
+<translation id="273860350361291195">Je nám to ľúto, ale toto video sa nedá streamovať do tohto zariadenia.</translation>
+<translation id="2410828433627930127">Je nám to ľúto, ale toto video sa nedá prehrať.</translation>
 <translation id="8987927404178983737">Mesiac</translation>
 <translation id="2532336938189706096">Webové zobrazenie</translation>
 <translation id="7096034533295549981">Načítanie videa</translation>
diff --git a/content/public/android/java/strings/translations/android_content_strings_sl.xtb b/content/public/android/java/strings/translations/android_content_strings_sl.xtb
index 9279e5c..60747f2 100644
--- a/content/public/android/java/strings/translations/android_content_strings_sl.xtb
+++ b/content/public/android/java/strings/translations/android_content_strings_sl.xtb
@@ -5,17 +5,17 @@
 <translation id="1256337885411059545">Videa ni mogoče predvajati</translation>
 <translation id="7821540960913969614">Nastavitev datuma</translation>
 <translation id="4932733599132424254">Datum</translation>
-<translation id="6727102863431372879">Nastavi</translation>
+<translation id="6727102863431372879">Nastavitev</translation>
 <translation id="273860350361291195">Ta videoposnetek ni veljaven za pretakanje v to napravo.</translation>
-<translation id="2410828433627930127">Tega videa ni mogoče predvajati.</translation>
+<translation id="2410828433627930127">Tega videoposnetka ni mogoče predvajati.</translation>
 <translation id="8987927404178983737">Mesec</translation>
 <translation id="2532336938189706096">Spletni pogled</translation>
 <translation id="7096034533295549981">Nalaganje videa</translation>
 <translation id="1542044944667958430">Spletno iskanje</translation>
-<translation id="6527303717912515753">Deli</translation>
+<translation id="6527303717912515753">Deli z drugimi</translation>
 <translation id="2841013758207633010">Čas</translation>
-<translation id="6643016212128521049">Izbriši</translation>
+<translation id="6643016212128521049">Počisti</translation>
 <translation id="7781164152564914424">Nastavitev meseca</translation>
 <translation id="6965382102122355670">V redu</translation>
-<translation id="6444070574980481588">Nastavitev datuma in ure</translation>
+<translation id="6444070574980481588">Nastavitev datuma in časa</translation>
 </translationbundle>
\ No newline at end of file
diff --git a/content/public/android/java/strings/translations/android_content_strings_sr.xtb b/content/public/android/java/strings/translations/android_content_strings_sr.xtb
index c668169..6d1aed7 100644
--- a/content/public/android/java/strings/translations/android_content_strings_sr.xtb
+++ b/content/public/android/java/strings/translations/android_content_strings_sr.xtb
@@ -6,7 +6,7 @@
 <translation id="7821540960913969614">Подешавање датума</translation>
 <translation id="4932733599132424254">Датум</translation>
 <translation id="6727102863431372879">Подеси</translation>
-<translation id="273860350361291195">Жао нам је, овај видео није погодан за стрим. на овај уређ.</translation>
+<translation id="273860350361291195">Жао нам је, овај видео није погодан за стриминг на овом уређају.</translation>
 <translation id="2410828433627930127">Жао нам је, овај видео не може да се пусти.</translation>
 <translation id="8987927404178983737">Месец</translation>
 <translation id="2532336938189706096">Веб-приказ</translation>
diff --git a/content/public/android/java/strings/translations/android_content_strings_sv.xtb b/content/public/android/java/strings/translations/android_content_strings_sv.xtb
index 414f66b..bb46f23 100644
--- a/content/public/android/java/strings/translations/android_content_strings_sv.xtb
+++ b/content/public/android/java/strings/translations/android_content_strings_sv.xtb
@@ -5,16 +5,16 @@
 <translation id="1256337885411059545">Det går inte att spela upp video</translation>
 <translation id="7821540960913969614">Ange datum</translation>
 <translation id="4932733599132424254">Datum</translation>
-<translation id="6727102863431372879">Spara</translation>
-<translation id="273860350361291195">Videon kan inte spelas upp.</translation>
-<translation id="2410828433627930127">Videon kan inte spelas upp.</translation>
+<translation id="6727102863431372879">Ange</translation>
+<translation id="273860350361291195">Det går tyvärr inte att spela upp videon direkt på den här enheten.</translation>
+<translation id="2410828433627930127">Det går tyvärr inte att spela upp den här videon.</translation>
 <translation id="8987927404178983737">Månad</translation>
 <translation id="2532336938189706096">Webbvy</translation>
 <translation id="7096034533295549981">Videon läses in</translation>
 <translation id="1542044944667958430">Webbsökning</translation>
 <translation id="6527303717912515753">Dela</translation>
 <translation id="2841013758207633010">Tid</translation>
-<translation id="6643016212128521049">Ta bort</translation>
+<translation id="6643016212128521049">Rensa</translation>
 <translation id="7781164152564914424">Ange månad</translation>
 <translation id="6965382102122355670">OK</translation>
 <translation id="6444070574980481588">Ange datum och tid</translation>
diff --git a/content/public/android/java/strings/translations/android_content_strings_sw.xtb b/content/public/android/java/strings/translations/android_content_strings_sw.xtb
new file mode 100644
index 0000000..7ec8346
--- /dev/null
+++ b/content/public/android/java/strings/translations/android_content_strings_sw.xtb
@@ -0,0 +1,21 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="sw">
+<translation id="6015796118275082299">Mwaka</translation>
+<translation id="1256337885411059545">Haiwezi kucheza video</translation>
+<translation id="7821540960913969614">Weka tarehe</translation>
+<translation id="4932733599132424254">Tarehe</translation>
+<translation id="6727102863431372879">Weka</translation>
+<translation id="273860350361291195">Samahani, video hii si halali kwa mtiririko katika kifaa hiki.</translation>
+<translation id="2410828433627930127">Samahani, video hii haiwezi kuchezwa.</translation>
+<translation id="8987927404178983737">Mwezi</translation>
+<translation id="2532336938189706096">Mwonekano wa Wavuti</translation>
+<translation id="7096034533295549981">Inapakia video</translation>
+<translation id="1542044944667958430">Tafuta kwenye wavuti</translation>
+<translation id="6527303717912515753">Shiriki</translation>
+<translation id="2841013758207633010">Wakati</translation>
+<translation id="6643016212128521049">Futa</translation>
+<translation id="7781164152564914424">Weka mwezi</translation>
+<translation id="6965382102122355670">Sawa</translation>
+<translation id="6444070574980481588">Weka tarehe na muda</translation>
+</translationbundle>
\ No newline at end of file
diff --git a/content/public/android/java/strings/translations/android_content_strings_th.xtb b/content/public/android/java/strings/translations/android_content_strings_th.xtb
index d880eb0..dc83adb 100644
--- a/content/public/android/java/strings/translations/android_content_strings_th.xtb
+++ b/content/public/android/java/strings/translations/android_content_strings_th.xtb
@@ -12,7 +12,7 @@
 <translation id="2532336938189706096">มุมมองเว็บ</translation>
 <translation id="7096034533295549981">กำลังโหลดวิดีโอ</translation>
 <translation id="1542044944667958430">ค้นเว็บ</translation>
-<translation id="6527303717912515753">แบ่งปัน</translation>
+<translation id="6527303717912515753">แชร์</translation>
 <translation id="2841013758207633010">เวลา</translation>
 <translation id="6643016212128521049">ล้าง</translation>
 <translation id="7781164152564914424">ตั้งเดือน</translation>
diff --git a/content/public/android/java/strings/translations/android_content_strings_tr.xtb b/content/public/android/java/strings/translations/android_content_strings_tr.xtb
index 1c62641..1328328 100644
--- a/content/public/android/java/strings/translations/android_content_strings_tr.xtb
+++ b/content/public/android/java/strings/translations/android_content_strings_tr.xtb
@@ -6,7 +6,7 @@
 <translation id="7821540960913969614">Tarih ayarla</translation>
 <translation id="4932733599132424254">Tarih</translation>
 <translation id="6727102863431372879">Ayarla</translation>
-<translation id="273860350361291195">Bu video cihaza akışla gönderilemez.</translation>
+<translation id="273860350361291195">Maalesef bu video bu cihaza akışla göndermek için uygun değil.</translation>
 <translation id="2410828433627930127">Maalesef bu video oynatılamıyor.</translation>
 <translation id="8987927404178983737">Ay</translation>
 <translation id="2532336938189706096">Web Görüntüleme</translation>
@@ -14,7 +14,7 @@
 <translation id="1542044944667958430">Web arama</translation>
 <translation id="6527303717912515753">Paylaş</translation>
 <translation id="2841013758207633010">Zaman</translation>
-<translation id="6643016212128521049">Temizle</translation>
+<translation id="6643016212128521049">Sil</translation>
 <translation id="7781164152564914424">Ayı ayarla</translation>
 <translation id="6965382102122355670">Tamam</translation>
 <translation id="6444070574980481588">Tarih ve saati ayarla</translation>
diff --git a/content/public/android/java/strings/translations/android_content_strings_uk.xtb b/content/public/android/java/strings/translations/android_content_strings_uk.xtb
index cff5d1b..7c0dc1e 100644
--- a/content/public/android/java/strings/translations/android_content_strings_uk.xtb
+++ b/content/public/android/java/strings/translations/android_content_strings_uk.xtb
@@ -6,13 +6,13 @@
 <translation id="7821540960913969614">Установити дату</translation>
 <translation id="4932733599132424254">Дата</translation>
 <translation id="6727102863431372879">Установити</translation>
-<translation id="273860350361291195">Відео не можна передати на цей пристрій.</translation>
-<translation id="2410828433627930127">Це відео неможливо відтворити.</translation>
+<translation id="273860350361291195">На жаль, це відео неможливо потоково передати на цей пристрій.</translation>
+<translation id="2410828433627930127">На жаль, це відео неможливо відтворити.</translation>
 <translation id="8987927404178983737">Місяць</translation>
 <translation id="2532336938189706096">Веб-версія</translation>
 <translation id="7096034533295549981">Завантаж. відео</translation>
 <translation id="1542044944667958430">Веб-пошук</translation>
-<translation id="6527303717912515753">Поділитися</translation>
+<translation id="6527303717912515753">Надіслати</translation>
 <translation id="2841013758207633010">Час</translation>
 <translation id="6643016212128521049">Очистити</translation>
 <translation id="7781164152564914424">Установити місяць</translation>
diff --git a/content/public/android/java/strings/translations/android_content_strings_vi.xtb b/content/public/android/java/strings/translations/android_content_strings_vi.xtb
index 5f29428..55b152a 100644
--- a/content/public/android/java/strings/translations/android_content_strings_vi.xtb
+++ b/content/public/android/java/strings/translations/android_content_strings_vi.xtb
@@ -4,9 +4,9 @@
 <translation id="6015796118275082299">Năm</translation>
 <translation id="1256337885411059545">Không thể phát video</translation>
 <translation id="7821540960913969614">Đặt ngày</translation>
-<translation id="4932733599132424254">Ngày</translation>
+<translation id="4932733599132424254">Ngày</translation>
 <translation id="6727102863431372879">Đặt</translation>
-<translation id="273860350361291195">Rất tiếc, không thể phát video.</translation>
+<translation id="273860350361291195">Rất tiếc, video này không hợp lệ để phát trực tuyến sang thiết bị này.</translation>
 <translation id="2410828433627930127">Rất tiếc, không thể phát video.</translation>
 <translation id="8987927404178983737">Tháng</translation>
 <translation id="2532336938189706096">Xem trên web</translation>
@@ -14,7 +14,7 @@
 <translation id="1542044944667958430">Tìm kiếm trên web</translation>
 <translation id="6527303717912515753">Chia sẻ</translation>
 <translation id="2841013758207633010">Thời gian</translation>
-<translation id="6643016212128521049">Xóa</translation>
+<translation id="6643016212128521049">Xoá</translation>
 <translation id="7781164152564914424">Đặt tháng</translation>
 <translation id="6965382102122355670">OK</translation>
 <translation id="6444070574980481588">Đặt ngày giờ</translation>
diff --git a/content/public/android/java/strings/translations/android_content_strings_zh-CN.xtb b/content/public/android/java/strings/translations/android_content_strings_zh-CN.xtb
index 6d96e16..23770f9 100644
--- a/content/public/android/java/strings/translations/android_content_strings_zh-CN.xtb
+++ b/content/public/android/java/strings/translations/android_content_strings_zh-CN.xtb
@@ -1,14 +1,14 @@
 <?xml version="1.0" ?>
 <!DOCTYPE translationbundle>
 <translationbundle lang="zh-CN">
-<translation id="6015796118275082299">年</translation>
+<translation id="6015796118275082299">年份</translation>
 <translation id="1256337885411059545">无法播放视频</translation>
 <translation id="7821540960913969614">设置日期</translation>
 <translation id="4932733599132424254">日期</translation>
 <translation id="6727102863431372879">设置</translation>
-<translation id="273860350361291195">抱歉,该视频不适合在此设备上播放。</translation>
-<translation id="2410828433627930127">很抱歉,无法播放此视频。</translation>
-<translation id="8987927404178983737">月</translation>
+<translation id="273860350361291195">抱歉,该视频无法流式传输到此设备。</translation>
+<translation id="2410828433627930127">抱歉,无法播放此视频。</translation>
+<translation id="8987927404178983737">月份</translation>
 <translation id="2532336938189706096">网络视图</translation>
 <translation id="7096034533295549981">正在加载视频</translation>
 <translation id="1542044944667958430">网页搜索</translation>
diff --git a/content/public/android/java/strings/translations/android_content_strings_zh-TW.xtb b/content/public/android/java/strings/translations/android_content_strings_zh-TW.xtb
index e7e85c3..515979c 100644
--- a/content/public/android/java/strings/translations/android_content_strings_zh-TW.xtb
+++ b/content/public/android/java/strings/translations/android_content_strings_zh-TW.xtb
@@ -6,14 +6,14 @@
 <translation id="7821540960913969614">設定日期</translation>
 <translation id="4932733599132424254">日期</translation>
 <translation id="6727102863431372879">設定</translation>
-<translation id="273860350361291195">很抱歉,這部影片的格式無效,因此無法在此裝置中串流播放。</translation>
+<translation id="273860350361291195">很抱歉,這部影片的格式有誤,無法透過這個裝置串流播放。</translation>
 <translation id="2410828433627930127">很抱歉,無法播放這部影片。</translation>
 <translation id="8987927404178983737">月</translation>
 <translation id="2532336938189706096">網頁檢視</translation>
 <translation id="7096034533295549981">正在載入影片</translation>
 <translation id="1542044944667958430">網頁搜尋</translation>
 <translation id="6527303717912515753">分享</translation>
-<translation id="2841013758207633010">時間</translation>
+<translation id="2841013758207633010">時間戳記</translation>
 <translation id="6643016212128521049">清除</translation>
 <translation id="7781164152564914424">設定月份</translation>
 <translation id="6965382102122355670">確定</translation>
diff --git a/content/public/android/java/templates/NativeLibraries.template b/content/public/android/java/templates/NativeLibraries.template
new file mode 100644
index 0000000..a54c2c7
--- /dev/null
+++ b/content/public/android/java/templates/NativeLibraries.template
@@ -0,0 +1,18 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.content.app;
+
+public class NativeLibraries {
+    // This is the list of native libraries to be loaded (in the correct order)
+    // by LibraryLoader.java.  The content java library is compiled with no
+    // array defined, and then the build system creates a version of the file
+    // with the real list of libraries required (which changes based upon which
+    // .apk is being built).
+    // TODO(cjhopman): This is public since it is referenced by ChromeNativeTestActivity.java
+    // directly. The two ways of library loading should be refactored into one.
+    public static String[] libraries
+#include <native_libraries_array.h>
+      ;
+}
diff --git a/content/public/android/java/templates/native_libraries_array.h b/content/public/android/java/templates/native_libraries_array.h
new file mode 100644
index 0000000..a86c574
--- /dev/null
+++ b/content/public/android/java/templates/native_libraries_array.h
@@ -0,0 +1,8 @@
+// Copyright 2013 The Chromium 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 placeholder for compiling content_java.  The content java library
+// is compiled with no array defined, and then the build system creates a
+// version of the file with the real list of libraries required (which changes
+// based upon which .apk is being built).
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/AddressDetectionTest.java b/content/public/android/javatests/src/org/chromium/content/browser/AddressDetectionTest.java
index 32ed9e7..ce7cfd6 100644
--- a/content/public/android/javatests/src/org/chromium/content/browser/AddressDetectionTest.java
+++ b/content/public/android/javatests/src/org/chromium/content/browser/AddressDetectionTest.java
@@ -6,7 +6,6 @@
 
 import android.test.suitebuilder.annotation.MediumTest;
 
-import org.chromium.base.test.util.DisabledTest;
 import org.chromium.base.test.util.Feature;
 
 /**
@@ -22,14 +21,11 @@
         return intentUrl.equals(expectedUrl);
     }
 
-    /*
     @MediumTest
     @Feature({"ContentDetection", "TabContents"})
-    http://crbug.com/172786
-    */
-    @DisabledTest
     public void testMultipleAddressesInText() throws Throwable {
         startActivityWithTestUrl("content/content_detection/geo_address_multiple.html");
+        assertWaitForPageScaleFactorMatch(1.0f);
 
         assertTrue(isExpectedGeoIntent(scrollAndTapExpectingIntent("test1"),
                 "1600 Amphitheatre Parkway Mountain View, CA 94043"));
@@ -38,14 +34,11 @@
                 "76 Ninth Avenue 4th Floor New York, NY 10011"));
     }
 
-    /*
     @MediumTest
     @Feature({"ContentDetection", "TabContents"})
-    http://crbug.com/172786
-    */
-    @DisabledTest
     public void testSplitAddresses() throws Throwable {
         startActivityWithTestUrl("content/content_detection/geo_address_split.html");
+        assertWaitForPageScaleFactorMatch(1.0f);
 
         assertTrue(isExpectedGeoIntent(scrollAndTapExpectingIntent("test1"),
                 "9606 North MoPac Expressway Suite 400 Austin, TX 78759"));
@@ -60,14 +53,11 @@
                 "1818 Library Street Suite 400, VA 20190"));
     }
 
-    /*
     @MediumTest
     @Feature({"ContentDetection", "TabContents"})
-    http://crbug.com/172786
-    */
-    @DisabledTest
     public void testAddressLimits() throws Throwable {
         startActivityWithTestUrl("content/content_detection/geo_address_limits.html");
+        assertWaitForPageScaleFactorMatch(1.0f);
 
         assertTrue(isExpectedGeoIntent(scrollAndTapExpectingIntent("test1"),
                 "2590 Pearl Street Suite 100 Boulder, CO 80302"));
@@ -82,14 +72,11 @@
                 "1600 Amphitheatre Parkway Mountain View, CA 94043"));
     }
 
-    /*
     @MediumTest
     @Feature({"ContentDetection", "TabContents"})
-    http://crbug.com/172786
-    */
-    @DisabledTest
     public void testRealAddresses() throws Throwable {
         startActivityWithTestUrl("content/content_detection/geo_address_real.html");
+        assertWaitForPageScaleFactorMatch(1.0f);
 
         assertTrue(isExpectedGeoIntent(scrollAndTapExpectingIntent("test1"),
                 "57th Street and Lake Shore Drive Chicago, IL 60637"));
@@ -104,14 +91,11 @@
                 "79th Street, New York, NY, 10024-5192"));
     }
 
-    /*
     @MediumTest
     @Feature({"ContentDetection", "TabContents"})
-    http://crbug.com/172786
-    */
-    @DisabledTest
     public void testSpecialChars() throws Throwable {
         startActivityWithTestUrl("content/content_detection/geo_address_special_chars.html");
+        assertWaitForPageScaleFactorMatch(1.0f);
 
         assertTrue(isExpectedGeoIntent(scrollAndTapExpectingIntent("test1"),
                 "100 34th Avenue , San Francisco, CA 94121"));
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/ContentDetectionTestBase.java b/content/public/android/javatests/src/org/chromium/content/browser/ContentDetectionTestBase.java
index 648bfde..5ee5d32 100644
--- a/content/public/android/javatests/src/org/chromium/content/browser/ContentDetectionTestBase.java
+++ b/content/public/android/javatests/src/org/chromium/content/browser/ContentDetectionTestBase.java
@@ -10,6 +10,8 @@
 import java.util.concurrent.TimeUnit;
 
 import org.chromium.base.test.util.UrlUtils;
+import org.chromium.content.browser.test.util.Criteria;
+import org.chromium.content.browser.test.util.CriteriaHelper;
 import org.chromium.content.browser.test.util.DOMUtils;
 import org.chromium.content.browser.test.util.JavaScriptUtils;
 import org.chromium.content.browser.test.util.TestCallbackHelperContainer;
@@ -94,4 +96,20 @@
                 TimeUnit.SECONDS);
         getInstrumentation().waitForIdleSync();
     }
+
+    // TODO(aelias): This method needs to be removed once http://crbug.com/179511 is fixed.
+    // Meanwhile, we have to wait if the page has the <meta viewport> tag.
+    /**
+     * Waits till the ContentViewCore receives the expected page scale factor
+     * from the compositor and asserts that this happens.
+     */
+    protected void assertWaitForPageScaleFactorMatch(final float expectedScale)
+            throws InterruptedException {
+        assertTrue(CriteriaHelper.pollForCriteria(new Criteria() {
+            @Override
+            public boolean isSatisfied() {
+                return getContentViewCore().getScale() == expectedScale;
+            }
+        }));
+    }
 }
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/ContentViewGestureHandlerTest.java b/content/public/android/javatests/src/org/chromium/content/browser/ContentViewGestureHandlerTest.java
index 0969efb..d4a846e 100644
--- a/content/public/android/javatests/src/org/chromium/content/browser/ContentViewGestureHandlerTest.java
+++ b/content/public/android/javatests/src/org/chromium/content/browser/ContentViewGestureHandlerTest.java
@@ -5,12 +5,14 @@
 package org.chromium.content.browser;
 
 import android.content.Context;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.SystemClock;
 import android.test.InstrumentationTestCase;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.util.Log;
 import android.view.MotionEvent;
+import android.view.ViewConfiguration;
 
 import org.chromium.base.test.util.Feature;
 import org.chromium.content.browser.ContentViewGestureHandler.MotionEventDelegate;
@@ -92,7 +94,8 @@
         }
 
         @Override
-        public boolean sendGesture(int type, long timeMs, int x, int y, Bundle extraParams) {
+        public boolean sendGesture(int type, long timeMs, int x, int y,
+                boolean lastInputEventForVSync, Bundle extraParams) {
             Log.i(TAG,"Gesture event received with type id " + type);
             return true;
         }
@@ -184,7 +187,7 @@
         mGestureHandler.hasTouchEventHandlers(true);
 
         assertTrue(mGestureHandler.onTouchEvent(event));
-        assertEquals(1, mGestureHandler.getNumberOfPendingMotionEvents());
+        assertEquals(1, mGestureHandler.getNumberOfPendingMotionEventsForTesting());
         assertTrue("Should not have a pending gesture", mMockGestureDetector.mLastEvent == null);
         assertFalse("Should not have a pending LONG_PRESS", mLongPressDetector.hasPendingMessage());
 
@@ -192,36 +195,36 @@
                 downTime, eventTime + 5, MotionEvent.ACTION_MOVE,
                 FAKE_COORD_X * 5, FAKE_COORD_Y * 5, 0);
         assertTrue(mGestureHandler.onTouchEvent(event));
-        assertEquals(2, mGestureHandler.getNumberOfPendingMotionEvents());
+        assertEquals(2, mGestureHandler.getNumberOfPendingMotionEventsForTesting());
 
         event = MotionEvent.obtain(
                 downTime, eventTime + 10, MotionEvent.ACTION_MOVE,
                 FAKE_COORD_X * 10, FAKE_COORD_Y * 10, 0);
         assertTrue(mGestureHandler.onTouchEvent(event));
         assertEquals("We should have coalesced move events into one"
-                , 2, mGestureHandler.getNumberOfPendingMotionEvents());
+                , 2, mGestureHandler.getNumberOfPendingMotionEventsForTesting());
 
         event = MotionEvent.obtain(
                 downTime, eventTime + 15, MotionEvent.ACTION_UP,
                 FAKE_COORD_X * 10, FAKE_COORD_Y * 10, 0);
         assertTrue(mGestureHandler.onTouchEvent(event));
-        assertEquals(3, mGestureHandler.getNumberOfPendingMotionEvents());
+        assertEquals(3, mGestureHandler.getNumberOfPendingMotionEventsForTesting());
 
         mGestureHandler.confirmTouchEvent(
                 ContentViewGestureHandler.INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
-        assertEquals(2, mGestureHandler.getNumberOfPendingMotionEvents());
+        assertEquals(2, mGestureHandler.getNumberOfPendingMotionEventsForTesting());
         assertEquals(MotionEvent.ACTION_MOVE,
-                mGestureHandler.peekFirstInPendingMotionEvents().getActionMasked());
+                mGestureHandler.peekFirstInPendingMotionEventsForTesting().getActionMasked());
         assertFalse("Pending LONG_PRESS should have been canceled",
                 mLongPressDetector.hasPendingMessage());
 
         mGestureHandler.confirmTouchEvent(ContentViewGestureHandler.INPUT_EVENT_ACK_STATE_CONSUMED);
-        assertEquals(1, mGestureHandler.getNumberOfPendingMotionEvents());
+        assertEquals(1, mGestureHandler.getNumberOfPendingMotionEventsForTesting());
         assertEquals(MotionEvent.ACTION_UP,
-                mGestureHandler.peekFirstInPendingMotionEvents().getActionMasked());
+                mGestureHandler.peekFirstInPendingMotionEventsForTesting().getActionMasked());
 
         mGestureHandler.confirmTouchEvent(ContentViewGestureHandler.INPUT_EVENT_ACK_STATE_CONSUMED);
-        assertEquals(0, mGestureHandler.getNumberOfPendingMotionEvents());
+        assertEquals(0, mGestureHandler.getNumberOfPendingMotionEventsForTesting());
 
         // Synchronous, no need to wait.
         assertTrue("Should not have a fling", mMockListener.mLastFling1 == null);
@@ -245,7 +248,7 @@
         mGestureHandler.hasTouchEventHandlers(true);
 
         assertTrue(mGestureHandler.onTouchEvent(event));
-        assertEquals(1, mGestureHandler.getNumberOfPendingMotionEvents());
+        assertEquals(1, mGestureHandler.getNumberOfPendingMotionEventsForTesting());
         assertTrue("Should not have a pending gesture", mMockGestureDetector.mLastEvent == null);
         assertFalse("Should not have a pending LONG_PRESS", mLongPressDetector.hasPendingMessage());
 
@@ -253,38 +256,38 @@
                 downTime, eventTime + 5, MotionEvent.ACTION_MOVE,
                 FAKE_COORD_X * 5, FAKE_COORD_Y * 5, 0);
         assertTrue(mGestureHandler.onTouchEvent(event));
-        assertEquals(2, mGestureHandler.getNumberOfPendingMotionEvents());
+        assertEquals(2, mGestureHandler.getNumberOfPendingMotionEventsForTesting());
 
         event = MotionEvent.obtain(
                 downTime, eventTime + 10, MotionEvent.ACTION_MOVE,
                 FAKE_COORD_X * 10, FAKE_COORD_Y * 10, 0);
         assertTrue(mGestureHandler.onTouchEvent(event));
         assertEquals("We should have coalesced move events into one"
-                , 2, mGestureHandler.getNumberOfPendingMotionEvents());
+                , 2, mGestureHandler.getNumberOfPendingMotionEventsForTesting());
 
         event = MotionEvent.obtain(
                 downTime, eventTime + 15, MotionEvent.ACTION_UP,
                 FAKE_COORD_X * 10, FAKE_COORD_Y * 10, 0);
         assertTrue(mGestureHandler.onTouchEvent(event));
-        assertEquals(3, mGestureHandler.getNumberOfPendingMotionEvents());
+        assertEquals(3, mGestureHandler.getNumberOfPendingMotionEventsForTesting());
 
         mGestureHandler.confirmTouchEvent(
                 ContentViewGestureHandler.INPUT_EVENT_ACK_STATE_CONSUMED);
-        assertEquals(2, mGestureHandler.getNumberOfPendingMotionEvents());
+        assertEquals(2, mGestureHandler.getNumberOfPendingMotionEventsForTesting());
         assertEquals(MotionEvent.ACTION_MOVE,
-                mGestureHandler.peekFirstInPendingMotionEvents().getActionMasked());
+                mGestureHandler.peekFirstInPendingMotionEventsForTesting().getActionMasked());
 
         mGestureHandler.confirmTouchEvent(
                 ContentViewGestureHandler.INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
-        assertEquals(1, mGestureHandler.getNumberOfPendingMotionEvents());
+        assertEquals(1, mGestureHandler.getNumberOfPendingMotionEventsForTesting());
         assertEquals(MotionEvent.ACTION_UP,
-                mGestureHandler.peekFirstInPendingMotionEvents().getActionMasked());
+                mGestureHandler.peekFirstInPendingMotionEventsForTesting().getActionMasked());
         assertTrue("Even though the last event was not consumed by JavaScript," +
                 "it shouldn't have been sent to the Gesture Detector",
                         mMockGestureDetector.mLastEvent == null);
 
         mGestureHandler.confirmTouchEvent(ContentViewGestureHandler.INPUT_EVENT_ACK_STATE_CONSUMED);
-        assertEquals(0, mGestureHandler.getNumberOfPendingMotionEvents());
+        assertEquals(0, mGestureHandler.getNumberOfPendingMotionEventsForTesting());
 
         // Synchronous, no need to wait.
         assertTrue("Should not have a fling", mMockListener.mLastFling1 == null);
@@ -313,48 +316,48 @@
         mGestureHandler.hasTouchEventHandlers(true);
 
         assertTrue(mGestureHandler.onTouchEvent(event));
-        assertEquals(1, mGestureHandler.getNumberOfPendingMotionEvents());
+        assertEquals(1, mGestureHandler.getNumberOfPendingMotionEventsForTesting());
         assertFalse("Should not have a pending LONG_PRESS", mLongPressDetector.hasPendingMessage());
 
         event = MotionEvent.obtain(
                 downTime, eventTime + 5, MotionEvent.ACTION_MOVE,
                 FAKE_COORD_X * 5, FAKE_COORD_Y * 5, 0);
         assertTrue(mGestureHandler.onTouchEvent(event));
-        assertEquals(2, mGestureHandler.getNumberOfPendingMotionEvents());
+        assertEquals(2, mGestureHandler.getNumberOfPendingMotionEventsForTesting());
 
         event = MotionEvent.obtain(
                 downTime, eventTime + 10, MotionEvent.ACTION_MOVE,
                 FAKE_COORD_X * 10, FAKE_COORD_Y * 10, 0);
         assertTrue(mGestureHandler.onTouchEvent(event));
-        assertEquals(2, mGestureHandler.getNumberOfPendingMotionEvents());
+        assertEquals(2, mGestureHandler.getNumberOfPendingMotionEventsForTesting());
 
         event = MotionEvent.obtain(
                 downTime, eventTime + 15, MotionEvent.ACTION_UP,
                 FAKE_COORD_X * 10, FAKE_COORD_Y * 10, 0);
         assertTrue(mGestureHandler.onTouchEvent(event));
-        assertEquals(3, mGestureHandler.getNumberOfPendingMotionEvents());
+        assertEquals(3, mGestureHandler.getNumberOfPendingMotionEventsForTesting());
 
         event = motionEvent(MotionEvent.ACTION_DOWN, eventTime + 20, eventTime + 20);
         assertTrue(mGestureHandler.onTouchEvent(event));
-        assertEquals(4, mGestureHandler.getNumberOfPendingMotionEvents());
+        assertEquals(4, mGestureHandler.getNumberOfPendingMotionEventsForTesting());
 
         event = MotionEvent.obtain(
                 downTime, eventTime + 20, MotionEvent.ACTION_UP,
                 FAKE_COORD_X, FAKE_COORD_Y, 0);
         assertTrue(mGestureHandler.onTouchEvent(event));
-        assertEquals(5, mGestureHandler.getNumberOfPendingMotionEvents());
+        assertEquals(5, mGestureHandler.getNumberOfPendingMotionEventsForTesting());
 
         mGestureHandler.confirmTouchEvent(
                 ContentViewGestureHandler.INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
         assertEquals("The queue should have been drained until first down since no consumer exists",
-                2, mGestureHandler.getNumberOfPendingMotionEvents());
+                2, mGestureHandler.getNumberOfPendingMotionEventsForTesting());
         assertEquals(MotionEvent.ACTION_DOWN,
-                mGestureHandler.peekFirstInPendingMotionEvents().getActionMasked());
+                mGestureHandler.peekFirstInPendingMotionEventsForTesting().getActionMasked());
 
         mGestureHandler.confirmTouchEvent(
                 ContentViewGestureHandler.INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
         assertEquals("The queue should have been drained",
-                0, mGestureHandler.getNumberOfPendingMotionEvents());
+                0, mGestureHandler.getNumberOfPendingMotionEventsForTesting());
     }
 
     /**
@@ -373,13 +376,13 @@
         mGestureHandler.hasTouchEventHandlers(true);
 
         assertTrue(mGestureHandler.onTouchEvent(event));
-        assertEquals(1, mGestureHandler.getNumberOfPendingMotionEvents());
+        assertEquals(1, mGestureHandler.getNumberOfPendingMotionEventsForTesting());
         assertTrue("Should not have a pending gesture", mMockGestureDetector.mLastEvent == null);
         assertFalse("Should not have a pending LONG_PRESS", mLongPressDetector.hasPendingMessage());
 
         mGestureHandler.confirmTouchEvent(
                 ContentViewGestureHandler.INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
-        assertEquals(0, mGestureHandler.getNumberOfPendingMotionEvents());
+        assertEquals(0, mGestureHandler.getNumberOfPendingMotionEventsForTesting());
         assertEquals("The down touch event should have been sent to the Gesture Detector",
                 event.getEventTime(), mMockGestureDetector.mLastEvent.getEventTime());
         assertEquals("The down touch event should have been sent to the Gesture Detector",
@@ -389,7 +392,7 @@
                 downTime, eventTime + 5, MotionEvent.ACTION_MOVE,
                 FAKE_COORD_X * 5, FAKE_COORD_Y * 5, 0);
         assertTrue(mGestureHandler.onTouchEvent(event));
-        assertEquals(0, mGestureHandler.getNumberOfPendingMotionEvents());
+        assertEquals(0, mGestureHandler.getNumberOfPendingMotionEventsForTesting());
         assertEquals("Motion events should be going to the Gesture Detector directly",
                 event.getEventTime(), mMockGestureDetector.mLastEvent.getEventTime());
         assertEquals("Motion events should be going to the Gesture Detector directly",
@@ -399,7 +402,7 @@
                 downTime, eventTime + 10, MotionEvent.ACTION_UP,
                 FAKE_COORD_X * 5, FAKE_COORD_Y * 5, 0);
         assertTrue(mGestureHandler.onTouchEvent(event));
-        assertEquals(0, mGestureHandler.getNumberOfPendingMotionEvents());
+        assertEquals(0, mGestureHandler.getNumberOfPendingMotionEventsForTesting());
         assertEquals("Motion events should be going to the Gesture Detector directly",
                 event.getEventTime(), mMockGestureDetector.mLastEvent.getEventTime());
         assertEquals("Motion events should be going to the Gesture Detector directly",
@@ -425,28 +428,28 @@
         mGestureHandler.hasTouchEventHandlers(true);
 
         assertTrue(mGestureHandler.onTouchEvent(event));
-        assertEquals(1, mGestureHandler.getNumberOfPendingMotionEvents());
+        assertEquals(1, mGestureHandler.getNumberOfPendingMotionEventsForTesting());
         assertTrue("Should not have a pending gesture", mMockGestureDetector.mLastEvent == null);
         assertFalse("Should not have a pending LONG_PRESS", mLongPressDetector.hasPendingMessage());
 
         event = motionEvent(MotionEvent.ACTION_UP, downTime, eventTime + 5);
         assertTrue(mGestureHandler.onTouchEvent(event));
-        assertEquals(2, mGestureHandler.getNumberOfPendingMotionEvents());
+        assertEquals(2, mGestureHandler.getNumberOfPendingMotionEventsForTesting());
 
         mGestureHandler.confirmTouchEvent(
                 ContentViewGestureHandler.INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
 
-        assertEquals(1, mGestureHandler.getNumberOfPendingMotionEvents());
+        assertEquals(1, mGestureHandler.getNumberOfPendingMotionEventsForTesting());
         assertEquals("The down touch event should have been sent to the Gesture Detector",
                 event.getDownTime(), mMockGestureDetector.mLastEvent.getEventTime());
         assertEquals("The next event should be ACTION_UP",
                 MotionEvent.ACTION_UP,
-                mGestureHandler.peekFirstInPendingMotionEvents().getActionMasked());
+                mGestureHandler.peekFirstInPendingMotionEventsForTesting().getActionMasked());
 
         mGestureHandler.confirmTouchEvent(
                 ContentViewGestureHandler.INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
 
-        assertEquals(0, mGestureHandler.getNumberOfPendingMotionEvents());
+        assertEquals(0, mGestureHandler.getNumberOfPendingMotionEventsForTesting());
         assertEquals("The up touch event should have been sent to the Gesture Detector",
                 event.getEventTime(), mMockGestureDetector.mLastEvent.getEventTime());
 
@@ -487,6 +490,59 @@
     }
 
     /**
+     * Verify that for a normal fling (fling after scroll) the following events are sent:
+     * - GESTURE_SCROLL_BEGIN
+     * - GESTURE_FLING_START
+     * @throws Exception
+     */
+    @SmallTest
+    @Feature({"Gestures"})
+    public void testFlingEventSequence() throws Exception {
+        final long downTime = SystemClock.uptimeMillis();
+        final long eventTime = SystemClock.uptimeMillis();
+
+        GestureRecordingMotionEventDelegate mockDelegate =
+                new GestureRecordingMotionEventDelegate();
+        mGestureHandler = new ContentViewGestureHandler(
+                getInstrumentation().getTargetContext(), mockDelegate,
+                new MockZoomManager(getInstrumentation().getTargetContext(), null));
+
+        MotionEvent event = motionEvent(MotionEvent.ACTION_DOWN, downTime, downTime);
+
+        assertTrue(mGestureHandler.onTouchEvent(event));
+
+        event = MotionEvent.obtain(
+                downTime, eventTime + 10, MotionEvent.ACTION_MOVE,
+                FAKE_COORD_X * 5, FAKE_COORD_Y * 5, 0);
+        assertTrue(mGestureHandler.onTouchEvent(event));
+
+        assertTrue("A flingCancel event should have been sent",
+                mockDelegate.mGestureTypeList.contains(
+                        ContentViewGestureHandler.GESTURE_FLING_CANCEL));
+        assertTrue("A scrollStart event should have been sent",
+                mockDelegate.mGestureTypeList.contains(
+                        ContentViewGestureHandler.GESTURE_SCROLL_START));
+        assertEquals("We should have started scrolling",
+                ContentViewGestureHandler.GESTURE_SCROLL_BY,
+                        mockDelegate.mMostRecentGestureEvent.mType);
+        assertEquals("Only flingCancel, scrollBegin and scrollBy should have been sent",
+                3, mockDelegate.mGestureTypeList.size());
+
+        event = MotionEvent.obtain(
+                downTime, eventTime + 15, MotionEvent.ACTION_UP,
+                FAKE_COORD_X * 10, FAKE_COORD_Y * 10, 0);
+        assertTrue(mGestureHandler.onTouchEvent(event));
+        assertEquals("We should have started flinging",
+                ContentViewGestureHandler.GESTURE_FLING_START,
+                        mockDelegate.mMostRecentGestureEvent.mType);
+        assertTrue("A scroll end event should not have been sent",
+                !mockDelegate.mGestureTypeList.contains(
+                        ContentViewGestureHandler.GESTURE_SCROLL_END));
+        assertEquals("The last up should have caused flingCancel and flingStart to be sent",
+                5, mockDelegate.mGestureTypeList.size());
+    }
+
+    /**
      * Verify that a recent show pressed state gesture is canceled when scrolling begins.
      * @throws Exception
      */
@@ -509,7 +565,7 @@
         assertTrue(mGestureHandler.onTouchEvent(event));
         assertFalse("Should not have a pending LONG_PRESS", mLongPressDetector.hasPendingMessage());
 
-        mGestureHandler.sendShowPressedStateGestureForTest();
+        mGestureHandler.sendShowPressedStateGestureForTesting();
 
         assertEquals("A show pressed state event should have been sent",
                 ContentViewGestureHandler.GESTURE_SHOW_PRESSED_STATE,
@@ -522,12 +578,6 @@
                 FAKE_COORD_X * 5, FAKE_COORD_Y * 5, 0);
         assertTrue(mGestureHandler.onTouchEvent(event));
 
-        // The first scroll event is ignored so submit a second one.
-        event = MotionEvent.obtain(
-                downTime, eventTime + 13, MotionEvent.ACTION_MOVE,
-                FAKE_COORD_X * 10, FAKE_COORD_Y * 10, 0);
-        assertTrue(mGestureHandler.onTouchEvent(event));
-
         assertEquals("We should have started scrolling",
                 ContentViewGestureHandler.GESTURE_SCROLL_BY,
                         mockDelegate.mMostRecentGestureEvent.mType);
@@ -545,12 +595,11 @@
         assertEquals("We should have started flinging",
                 ContentViewGestureHandler.GESTURE_FLING_START,
                         mockDelegate.mMostRecentGestureEvent.mType);
-        assertTrue("A scroll end event should have been sent",
-                mockDelegate.mGestureTypeList.contains(
+        assertTrue("A scroll end event should not have been sent",
+                !mockDelegate.mGestureTypeList.contains(
                         ContentViewGestureHandler.GESTURE_SCROLL_END));
-        assertEquals(
-                "The last up should have caused scrollEnd, flingCancel and flingStart to be sent",
-                        8, mockDelegate.mGestureTypeList.size());
+        assertEquals("The last up should have caused flingCancel and flingStart to be sent",
+                7, mockDelegate.mGestureTypeList.size());
     }
 
     /**
@@ -576,7 +625,7 @@
         assertTrue(mGestureHandler.onTouchEvent(event));
         assertFalse("Should not have a pending LONG_PRESS", mLongPressDetector.hasPendingMessage());
 
-        mGestureHandler.sendShowPressedStateGestureForTest();
+        mGestureHandler.sendShowPressedStateGestureForTesting();
 
         assertEquals("A show pressed state event should have been sent",
                 ContentViewGestureHandler.GESTURE_SHOW_PRESSED_STATE,
@@ -646,6 +695,7 @@
             }
         };
         private GestureEvent mMostRecentGestureEvent;
+        private boolean mMostRecentGestureEventWasLastForVSync;
         private final ArrayList<Integer> mGestureTypeList = new ArrayList<Integer>();
 
         @Override
@@ -655,8 +705,10 @@
         }
 
         @Override
-        public boolean sendGesture(int type, long timeMs, int x, int y, Bundle extraParams) {
+        public boolean sendGesture(int type, long timeMs, int x, int y,
+                boolean lastInputEventForVSync, Bundle extraParams) {
             mMostRecentGestureEvent = new GestureEvent(type, timeMs, x, y, extraParams);
+            mMostRecentGestureEventWasLastForVSync = lastInputEventForVSync;
             mGestureTypeList.add(mMostRecentGestureEvent.mType);
             return true;
         }
@@ -680,6 +732,59 @@
         public GestureEvent getMostRecentGestureEvent() {
             return mMostRecentGestureEvent;
         }
+
+        public boolean mostRecentGestureEventForLastForVSync() {
+            return mMostRecentGestureEventWasLastForVSync;
+        }
+    }
+
+    /**
+     * Verify that the first event sent while the page is scrolling will be
+     * converted to a touchcancel. The touchcancel event should stay in the
+     * pending queue. Acking the touchcancel event will consume all the touch
+     * events of the current session.
+     */
+    @SmallTest
+    @Feature({"Gestures"})
+    public void testTouchEventsCanceledWhileScrolling() {
+        final int deltaY = 84;
+        final long downTime = SystemClock.uptimeMillis();
+
+        MockMotionEventDelegate delegate = new MockMotionEventDelegate();
+        ContentViewGestureHandler gestureHandler = new ContentViewGestureHandler(
+                getInstrumentation().getTargetContext(), delegate,
+                new MockZoomManager(getInstrumentation().getTargetContext(), null));
+        gestureHandler.hasTouchEventHandlers(true);
+        MotionEvent event = motionEvent(MotionEvent.ACTION_DOWN, downTime, downTime);
+        assertTrue(gestureHandler.onTouchEvent(event));
+        gestureHandler.confirmTouchEvent(
+            ContentViewGestureHandler.INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+
+        event = MotionEvent.obtain(
+                downTime, downTime + 5, MotionEvent.ACTION_MOVE,
+                FAKE_COORD_X, FAKE_COORD_Y - deltaY / 2, 0);
+        assertTrue(gestureHandler.onTouchEvent(event));
+        gestureHandler.confirmTouchEvent(
+            ContentViewGestureHandler.INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+
+        // This event will be converted to touchcancel and put into the pending
+        // queue.
+        event = MotionEvent.obtain(
+                downTime, downTime + 10, MotionEvent.ACTION_MOVE,
+                FAKE_COORD_X, FAKE_COORD_Y - deltaY, 0);
+        assertTrue(gestureHandler.onTouchEvent(event));
+        assertEquals(1, gestureHandler.getNumberOfPendingMotionEventsForTesting());
+        assertTrue(gestureHandler.isEventCancelledForTesting(
+            gestureHandler.peekFirstInPendingMotionEventsForTesting()));
+
+        event = motionEvent(MotionEvent.ACTION_POINTER_DOWN, downTime + 15, downTime + 15);
+        assertTrue(gestureHandler.onTouchEvent(event));
+        assertEquals(2, gestureHandler.getNumberOfPendingMotionEventsForTesting());
+
+        // Acking the touchcancel will drain all the events.
+        gestureHandler.confirmTouchEvent(
+            ContentViewGestureHandler.INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+        assertEquals(0, gestureHandler.getNumberOfPendingMotionEventsForTesting());
     }
 
     /**
@@ -697,7 +802,6 @@
         ContentViewGestureHandler gestureHandler = new ContentViewGestureHandler(
                 getInstrumentation().getTargetContext(), delegate,
                 new MockZoomManager(getInstrumentation().getTargetContext(), null));
-
         MotionEvent event = motionEvent(MotionEvent.ACTION_DOWN, downTime, downTime);
         assertTrue(gestureHandler.onTouchEvent(event));
         assertNotNull(delegate.getMostRecentGestureEvent());
@@ -808,31 +912,98 @@
     }
 
     /**
-     * Verify that the first scroll delta is ignored to avoid a jump when starting to scroll.
+     * Verify that the touch slop region is removed from the first scroll delta to avoid a jump when
+     * starting to scroll.
      * @throws Exception
      */
     @SmallTest
     @Feature({"Gestures"})
-    public void testFirstScrollDeltaIgnored() throws Exception {
+    public void testTouchSlopRemovedFromScroll() throws Exception {
+        Context context = getInstrumentation().getTargetContext();
         final long downTime = SystemClock.uptimeMillis();
         final long eventTime = SystemClock.uptimeMillis();
+        final int scaledTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
+        final int scrollDelta = 5;
 
         GestureRecordingMotionEventDelegate mockDelegate =
                 new GestureRecordingMotionEventDelegate();
         mGestureHandler = new ContentViewGestureHandler(
-                getInstrumentation().getTargetContext(), mockDelegate,
-                new MockZoomManager(getInstrumentation().getTargetContext(), null));
+                context, mockDelegate,
+                new MockZoomManager(context, null));
 
         MotionEvent event = motionEvent(MotionEvent.ACTION_DOWN, downTime, downTime);
         assertTrue(mGestureHandler.onTouchEvent(event));
 
         event = MotionEvent.obtain(
                 downTime, eventTime + 10, MotionEvent.ACTION_MOVE,
-                FAKE_COORD_X * 10, FAKE_COORD_Y * 10, 0);
+                FAKE_COORD_X, FAKE_COORD_Y + scaledTouchSlop + scrollDelta, 0);
         assertTrue(mGestureHandler.onTouchEvent(event));
 
-        assertEquals("We should not have started scrolling yet",
-                ContentViewGestureHandler.GESTURE_FLING_CANCEL,
+        assertEquals("We should have started scrolling",
+                ContentViewGestureHandler.GESTURE_SCROLL_BY,
                 mockDelegate.mMostRecentGestureEvent.mType);
+
+        GestureRecordingMotionEventDelegate.GestureEvent gestureEvent =
+                mockDelegate.getMostRecentGestureEvent();
+        assertNotNull(gestureEvent);
+        Bundle extraParams = gestureEvent.getExtraParams();
+        assertEquals(0, extraParams.getInt(ContentViewGestureHandler.DISTANCE_X));
+        assertEquals(-scrollDelta, extraParams.getInt(ContentViewGestureHandler.DISTANCE_Y));
+    }
+
+    /**
+     * Verify that certain gesture events are sent with the "last for this vsync" flag set.
+     * @throws Exception
+     */
+    @SmallTest
+    @Feature({"Gestures"})
+    public void testFinalInputEventsForVSyncInterval() throws Exception {
+        Context context = getInstrumentation().getTargetContext();
+        final long downTime = SystemClock.uptimeMillis();
+        final long eventTime = SystemClock.uptimeMillis();
+        final boolean inputEventsDeliveredAtVSync =
+                Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN;
+
+        GestureRecordingMotionEventDelegate mockDelegate =
+                new GestureRecordingMotionEventDelegate();
+        mGestureHandler = new ContentViewGestureHandler(
+                context, mockDelegate,
+                new MockZoomManager(context, null));
+
+        MotionEvent event = motionEvent(MotionEvent.ACTION_DOWN, downTime, downTime);
+        assertTrue(mGestureHandler.onTouchEvent(event));
+        event = MotionEvent.obtain(
+                downTime, eventTime + 10, MotionEvent.ACTION_MOVE,
+                FAKE_COORD_X, FAKE_COORD_Y + 30, 0);
+        assertTrue(mGestureHandler.onTouchEvent(event));
+        assertEquals("We should have started scrolling",
+                ContentViewGestureHandler.GESTURE_SCROLL_BY,
+                mockDelegate.mMostRecentGestureEvent.mType);
+
+        if (inputEventsDeliveredAtVSync) {
+            assertEquals("Gesture should be last for vsync",
+                    true,
+                    mockDelegate.mostRecentGestureEventForLastForVSync());
+        } else {
+            assertEquals("Gesture should not be last for vsync",
+                    false,
+                    mockDelegate.mostRecentGestureEventForLastForVSync());
+        }
+
+        mGestureHandler.pinchBegin(downTime, FAKE_COORD_X, FAKE_COORD_Y);
+        mGestureHandler.pinchBy(eventTime + 10, FAKE_COORD_X, FAKE_COORD_Y, 2);
+        assertEquals("We should have started pinch-zooming",
+                ContentViewGestureHandler.GESTURE_PINCH_BY,
+                mockDelegate.mMostRecentGestureEvent.mType);
+
+        if (inputEventsDeliveredAtVSync) {
+            assertEquals("Gesture should be last for vsync",
+                    true,
+                    mockDelegate.mostRecentGestureEventForLastForVSync());
+        } else {
+            assertEquals("Gesture should not be last for vsync",
+                    false,
+                    mockDelegate.mostRecentGestureEventForLastForVSync());
+        }
     }
 }
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/ContentViewScrollingTest.java b/content/public/android/javatests/src/org/chromium/content/browser/ContentViewScrollingTest.java
index f40d30e..d880a96 100644
--- a/content/public/android/javatests/src/org/chromium/content/browser/ContentViewScrollingTest.java
+++ b/content/public/android/javatests/src/org/chromium/content/browser/ContentViewScrollingTest.java
@@ -4,6 +4,7 @@
 
 package org.chromium.content.browser;
 
+import android.test.FlakyTest;
 import android.test.suitebuilder.annotation.SmallTest;
 
 import org.chromium.base.test.util.Feature;
@@ -84,8 +85,12 @@
         assertEquals(0, getContentViewCore().getNativeScrollYForTest());
     }
 
-    @SmallTest
-    @Feature({"Main"})
+    /**
+     * @SmallTest
+     * @Feature({"Main"})
+     * crbug.com/224458
+     */
+    @FlakyTest
     public void testFling() throws Throwable {
         // Vertical fling to lower-left.
         fling(0, -1000);
@@ -108,8 +113,12 @@
         assertWaitForScroll(false, false);
     }
 
-    @SmallTest
-    @Feature({"Main"})
+    /**
+     * @SmallTest
+     * @Feature({"Main"})
+     * crbug.com/224458
+     */
+    @FlakyTest
     public void testScroll() throws Throwable {
         // Vertical scroll to lower-left.
         scrollTo(0, 2500);
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/DeviceMotionAndOrientationTest.java b/content/public/android/javatests/src/org/chromium/content/browser/DeviceMotionAndOrientationTest.java
new file mode 100644
index 0000000..518b525
--- /dev/null
+++ b/content/public/android/javatests/src/org/chromium/content/browser/DeviceMotionAndOrientationTest.java
@@ -0,0 +1,299 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.content.browser;
+
+import org.chromium.base.ActivityStatus;
+import org.chromium.base.test.util.Feature;
+import org.chromium.content.app.LibraryLoader;
+import org.chromium.content.common.CommandLine;
+import org.chromium.content.common.ProcessInitException;
+import org.chromium.content_shell_apk.ContentShellApplication;
+
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.test.UiThreadTest;
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
+import android.hardware.SensorManager;
+import android.os.Handler;
+
+import com.google.common.collect.Sets;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+
+/**
+ * Test suite for DeviceMotionAndOrientation.
+ */
+public class DeviceMotionAndOrientationTest extends AndroidTestCase {
+
+    private DeviceMotionAndOrientationForTests mDeviceMotionAndOrientation;
+    private MockSensorManager mMockSensorManager;
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        mMockSensorManager = new MockSensorManager();
+        mDeviceMotionAndOrientation = DeviceMotionAndOrientationForTests.getInstance();
+        mDeviceMotionAndOrientation.setSensorManagerProxy(mMockSensorManager);
+    }
+
+    @SmallTest
+    public void testRegisterSensorsDeviceMotion() {
+        boolean start = mDeviceMotionAndOrientation.start(0,
+                DeviceMotionAndOrientation.DEVICE_MOTION, 100);
+
+        assertTrue(start);
+        assertTrue("should contain all motion sensors",
+                mDeviceMotionAndOrientation.mActiveSensors.containsAll(
+                        DeviceMotionAndOrientation.DEVICE_MOTION_SENSORS));
+        assertTrue(mDeviceMotionAndOrientation.mDeviceMotionIsActive);
+        assertFalse(mDeviceMotionAndOrientation.mDeviceOrientationIsActive);
+
+        assertEquals(DeviceMotionAndOrientation.DEVICE_MOTION_SENSORS.size(),
+                mMockSensorManager.numRegistered);
+        assertEquals(0, mMockSensorManager.numUnRegistered);
+    }
+
+    @SmallTest
+    public void testRegisterSensorsDeviceOrientation() {
+        boolean start = mDeviceMotionAndOrientation.start(0,
+                DeviceMotionAndOrientation.DEVICE_ORIENTATION, 100);
+
+        assertTrue(start);
+        assertTrue("should contain all orientation sensors",
+                mDeviceMotionAndOrientation.mActiveSensors.containsAll(
+                        DeviceMotionAndOrientation.DEVICE_ORIENTATION_SENSORS));
+        assertFalse(mDeviceMotionAndOrientation.mDeviceMotionIsActive);
+        assertTrue(mDeviceMotionAndOrientation.mDeviceOrientationIsActive);
+
+        assertEquals(DeviceMotionAndOrientation.DEVICE_ORIENTATION_SENSORS.size(),
+                mMockSensorManager.numRegistered);
+        assertEquals(0, mMockSensorManager.numUnRegistered);
+    }
+
+    @SmallTest
+    public void testRegisterSensorsDeviceMotionAndOrientation() {
+        boolean startOrientation = mDeviceMotionAndOrientation.start(0,
+                DeviceMotionAndOrientation.DEVICE_ORIENTATION, 100);
+        boolean startMotion = mDeviceMotionAndOrientation.start(0,
+                DeviceMotionAndOrientation.DEVICE_MOTION, 100);
+
+        assertTrue(startOrientation);
+        assertTrue(startMotion);
+        assertTrue("should contain all motion sensors",
+                mDeviceMotionAndOrientation.mActiveSensors.containsAll(
+                        DeviceMotionAndOrientation.DEVICE_MOTION_SENSORS));
+        assertTrue("should contain all orientation sensors",
+                mDeviceMotionAndOrientation.mActiveSensors.containsAll(
+                        DeviceMotionAndOrientation.DEVICE_ORIENTATION_SENSORS));
+
+        Set<Integer> union = Sets.newHashSet(DeviceMotionAndOrientation.DEVICE_ORIENTATION_SENSORS);
+        union.addAll(DeviceMotionAndOrientation.DEVICE_MOTION_SENSORS);
+
+        assertEquals(union.size(), mDeviceMotionAndOrientation.mActiveSensors.size());
+        assertTrue(mDeviceMotionAndOrientation.mDeviceMotionIsActive);
+        assertTrue(mDeviceMotionAndOrientation.mDeviceOrientationIsActive);
+        assertEquals(union.size(), mMockSensorManager.numRegistered);
+        assertEquals(0, mMockSensorManager.numUnRegistered);
+    }
+
+    @SmallTest
+    public void testUnregisterSensorsDeviceMotion() {
+        mDeviceMotionAndOrientation.start(0, DeviceMotionAndOrientation.DEVICE_MOTION, 100);
+        mDeviceMotionAndOrientation.stop(DeviceMotionAndOrientation.DEVICE_MOTION);
+
+        assertTrue("should contain no sensors",
+                mDeviceMotionAndOrientation.mActiveSensors.isEmpty());
+        assertFalse(mDeviceMotionAndOrientation.mDeviceMotionIsActive);
+        assertFalse(mDeviceMotionAndOrientation.mDeviceOrientationIsActive);
+        assertEquals(DeviceMotionAndOrientation.DEVICE_MOTION_SENSORS.size(),
+                mMockSensorManager.numUnRegistered);
+    }
+
+    @SmallTest
+    public void testUnregisterSensorsDeviceOrientation() {
+        mDeviceMotionAndOrientation.start(0, DeviceMotionAndOrientation.DEVICE_ORIENTATION, 100);
+        mDeviceMotionAndOrientation.stop(DeviceMotionAndOrientation.DEVICE_ORIENTATION);
+
+        assertTrue("should contain no sensors",
+                mDeviceMotionAndOrientation.mActiveSensors.isEmpty());
+        assertFalse(mDeviceMotionAndOrientation.mDeviceMotionIsActive);
+        assertFalse(mDeviceMotionAndOrientation.mDeviceOrientationIsActive);
+        assertEquals(DeviceMotionAndOrientation.DEVICE_ORIENTATION_SENSORS.size(),
+                mMockSensorManager.numUnRegistered);
+    }
+
+    @SmallTest
+    public void testUnRegisterSensorsDeviceMotionAndOrientation() {
+        mDeviceMotionAndOrientation.start(0, DeviceMotionAndOrientation.DEVICE_ORIENTATION, 100);
+        mDeviceMotionAndOrientation.start(0, DeviceMotionAndOrientation.DEVICE_MOTION, 100);
+        mDeviceMotionAndOrientation.stop(DeviceMotionAndOrientation.DEVICE_MOTION);
+
+        assertTrue("should contain all orientation sensors",
+                mDeviceMotionAndOrientation.mActiveSensors.containsAll(
+                        DeviceMotionAndOrientation.DEVICE_ORIENTATION_SENSORS));
+
+        Set<Integer> diff = Sets.newHashSet(DeviceMotionAndOrientation.DEVICE_MOTION_SENSORS);
+        diff.removeAll(DeviceMotionAndOrientation.DEVICE_ORIENTATION_SENSORS);
+
+        assertEquals(diff.size(), mMockSensorManager.numUnRegistered);
+
+        mDeviceMotionAndOrientation.stop(DeviceMotionAndOrientation.DEVICE_ORIENTATION);
+
+        assertTrue("should contain no sensors",
+                mDeviceMotionAndOrientation.mActiveSensors.isEmpty());
+        assertEquals(diff.size() + DeviceMotionAndOrientation.DEVICE_ORIENTATION_SENSORS.size(),
+                mMockSensorManager.numUnRegistered);
+    }
+
+    @SmallTest
+    public void testSensorChangedgotAccelerationAndOrientation() {
+        boolean startOrientation = mDeviceMotionAndOrientation.start(0,
+                DeviceMotionAndOrientation.DEVICE_ORIENTATION, 100);
+        boolean startMotion = mDeviceMotionAndOrientation.start(0,
+                DeviceMotionAndOrientation.DEVICE_MOTION, 100);
+
+        assertTrue(startOrientation);
+        assertTrue(startMotion);
+        assertTrue(mDeviceMotionAndOrientation.mDeviceMotionIsActive);
+        assertTrue(mDeviceMotionAndOrientation.mDeviceOrientationIsActive);
+
+        float[] values = {0.0f, 0.0f, 9.0f};
+        float[] values2 = {10.0f, 10.0f, 10.0f};
+        mDeviceMotionAndOrientation.sensorChanged(Sensor.TYPE_ACCELEROMETER, values);
+        mDeviceMotionAndOrientation.sensorChanged(Sensor.TYPE_MAGNETIC_FIELD, values2);
+        mDeviceMotionAndOrientation.verifyCalls("gotAccelerationIncludingGravity" +
+                "gotOrientation");
+        mDeviceMotionAndOrientation.verifyValuesEpsilon(45, 0, 0);
+    }
+
+    @SmallTest
+    public void testSensorChangedgotAccelerationIncludingGravity() {
+        mDeviceMotionAndOrientation.start(0, DeviceMotionAndOrientation.DEVICE_MOTION, 100);
+
+        float[] values = {1, 2, 3};
+        mDeviceMotionAndOrientation.sensorChanged(Sensor.TYPE_ACCELEROMETER, values);
+        mDeviceMotionAndOrientation.verifyCalls("gotAccelerationIncludingGravity");
+        mDeviceMotionAndOrientation.verifyValues(1, 2, 3);
+    }
+
+    @SmallTest
+    public void testSensorChangedgotAcceleration() {
+        mDeviceMotionAndOrientation.start(0, DeviceMotionAndOrientation.DEVICE_MOTION, 100);
+
+        float[] values = {1, 2, 3};
+        mDeviceMotionAndOrientation.sensorChanged(Sensor.TYPE_LINEAR_ACCELERATION, values);
+        mDeviceMotionAndOrientation.verifyCalls("gotAcceleration");
+        mDeviceMotionAndOrientation.verifyValues(1, 2, 3);
+    }
+
+    @SmallTest
+    public void testSensorChangedgotRotationRate() {
+        mDeviceMotionAndOrientation.start(0, DeviceMotionAndOrientation.DEVICE_MOTION, 100);
+
+        float[] values = {1, 2, 3};
+        mDeviceMotionAndOrientation.sensorChanged(Sensor.TYPE_GYROSCOPE, values);
+        mDeviceMotionAndOrientation.verifyCalls("gotRotationRate");
+        mDeviceMotionAndOrientation.verifyValues(1, 2, 3);
+    }
+
+    @SmallTest
+    public void testSensorChangedmagneticField() {
+        mDeviceMotionAndOrientation.start(0, DeviceMotionAndOrientation.DEVICE_ORIENTATION, 100);
+
+        float[] values = {1, 2, 3};
+        mDeviceMotionAndOrientation.sensorChanged(Sensor.TYPE_MAGNETIC_FIELD, values);
+        mDeviceMotionAndOrientation.verifyCalls("");
+    }
+
+    private static class DeviceMotionAndOrientationForTests extends DeviceMotionAndOrientation {
+
+        private double value1 = 0;
+        private double value2 = 0;
+        private double value3 = 0;
+        private String mCalls = "";
+
+        private DeviceMotionAndOrientationForTests(){
+        }
+
+        static DeviceMotionAndOrientationForTests getInstance() {
+            return new DeviceMotionAndOrientationForTests();
+        }
+
+        private void verifyValues(double v1, double v2, double v3) {
+            assertEquals(v1, value1);
+            assertEquals(v2, value2);
+            assertEquals(v3, value3);
+        }
+
+        private void verifyValuesEpsilon(double v1, double v2, double v3) {
+            assertEquals(v1, value1, 0.1);
+            assertEquals(v2, value2, 0.1);
+            assertEquals(v3, value3, 0.1);
+        }
+
+        private void verifyCalls(String names) {
+            assertEquals(mCalls, names);
+        }
+
+        @Override
+        protected void gotOrientation(double alpha, double beta, double gamma) {
+            value1 = alpha;
+            value2 = beta;
+            value3 = gamma;
+            mCalls = mCalls.concat("gotOrientation");
+        }
+
+        @Override
+        protected void gotAcceleration(double x, double y, double z) {
+            value1 = x;
+            value2 = y;
+            value3 = z;
+            mCalls = mCalls.concat("gotAcceleration");
+        }
+
+        @Override
+        protected void gotAccelerationIncludingGravity(double x, double y, double z) {
+            value1 = x;
+            value2 = y;
+            value3 = z;
+            mCalls = mCalls.concat("gotAccelerationIncludingGravity");
+        }
+
+        @Override
+        protected void gotRotationRate(double alpha, double beta, double gamma) {
+            value1 = alpha;
+            value2 = beta;
+            value3 = gamma;
+            mCalls = mCalls.concat("gotRotationRate");
+        }
+    }
+
+    private static class MockSensorManager implements
+            DeviceMotionAndOrientation.SensorManagerProxy {
+
+        private int numRegistered = 0;
+        private int numUnRegistered = 0;
+
+        private MockSensorManager() {
+        }
+
+        @Override
+        public boolean registerListener(SensorEventListener listener, int sensorType, int rate,
+                Handler handler) {
+            numRegistered++;
+            return true;
+        }
+
+        @Override
+        public void unregisterListener(SensorEventListener listener, int sensorType) {
+            numUnRegistered++;
+        }
+    }
+}
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/EmailAddressDetectionTest.java b/content/public/android/javatests/src/org/chromium/content/browser/EmailAddressDetectionTest.java
index 2dd5d34..2bd8797 100644
--- a/content/public/android/javatests/src/org/chromium/content/browser/EmailAddressDetectionTest.java
+++ b/content/public/android/javatests/src/org/chromium/content/browser/EmailAddressDetectionTest.java
@@ -6,7 +6,6 @@
 
 import android.test.suitebuilder.annotation.MediumTest;
 
-import org.chromium.base.test.util.DisabledTest;
 import org.chromium.base.test.util.Feature;
 
 /**
@@ -22,14 +21,11 @@
         return intentUrl.equals(expectedUrl);
     }
 
-    /*
     @MediumTest
     @Feature({"ContentDetection", "TabContents"})
-    http://crbug.com/172786
-    */
-    @DisabledTest
     public void testValidEmailAddresses() throws Throwable {
         startActivityWithTestUrl("content/content_detection/email.html");
+        assertWaitForPageScaleFactorMatch(1.0f);
 
         // valid_1: i.want.a.pony@chromium.org.
         String intentUrl = scrollAndTapExpectingIntent("valid_1");
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/JavaBridgeArrayCoercionTest.java b/content/public/android/javatests/src/org/chromium/content/browser/JavaBridgeArrayCoercionTest.java
index 9c737f2..9bd2f8f 100644
--- a/content/public/android/javatests/src/org/chromium/content/browser/JavaBridgeArrayCoercionTest.java
+++ b/content/public/android/javatests/src/org/chromium/content/browser/JavaBridgeArrayCoercionTest.java
@@ -248,12 +248,8 @@
 
     // Test passing an array of JavaScript NaN values to a method which takes a
     // Java array.
-    /*
     @SmallTest
     @Feature({"AndroidWebView", "Android-JavaBridge"})
-      Bug: http://code.google.com/p/chromium/issues/detail?id=145881
-    */
-    @DisabledTest
     public void testPassNumberNaN() throws Throwable {
         executeJavaScript("testObject.setBooleanArray([Number.NaN]);");
         assertFalse(mTestObject.waitForBooleanArray()[0]);
@@ -294,12 +290,8 @@
 
     // Test passing an array of JavaScript infinity values to a method which
     // takes a Java array.
-    /*
     @SmallTest
     @Feature({"AndroidWebView", "Android-JavaBridge"})
-      Bug: http://code.google.com/p/chromium/issues/detail?id=145881
-    */
-    @DisabledTest
     public void testPassNumberInfinity() throws Throwable {
         executeJavaScript("testObject.setBooleanArray([Infinity]);");
         assertFalse(mTestObject.waitForBooleanArray()[0]);
@@ -317,9 +309,8 @@
         executeJavaScript("testObject.setIntArray([Infinity]);");
         assertEquals(Integer.MAX_VALUE, mTestObject.waitForIntArray()[0]);
 
-        // LIVECONNECT_COMPLIANCE: Should be Long.MAX_VALUE.
         executeJavaScript("testObject.setLongArray([Infinity]);");
-        assertEquals(-1L, mTestObject.waitForLongArray()[0]);
+        assertEquals(Long.MAX_VALUE, mTestObject.waitForLongArray()[0]);
 
         executeJavaScript("testObject.setFloatArray([Infinity]);");
         assertEquals(Float.POSITIVE_INFINITY, mTestObject.waitForFloatArray()[0]);
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/JavaBridgeCoercionTest.java b/content/public/android/javatests/src/org/chromium/content/browser/JavaBridgeCoercionTest.java
index 8cdc60a..dea76d1 100644
--- a/content/public/android/javatests/src/org/chromium/content/browser/JavaBridgeCoercionTest.java
+++ b/content/public/android/javatests/src/org/chromium/content/browser/JavaBridgeCoercionTest.java
@@ -7,7 +7,6 @@
 import android.test.suitebuilder.annotation.SmallTest;
 
 import org.chromium.base.test.util.Feature;
-import org.chromium.base.test.util.DisabledTest;
 
 /**
  * Part of the test suite for the Java Bridge. This class tests that
@@ -161,8 +160,10 @@
         setUpContentView(mTestObject, "testObject");
     }
 
-    // Test passing a JavaScript number in the int32 range to a method of an
-    // injected object.
+    // Test passing a 32-bit integer JavaScript number to a method of an
+    // injected object. Note that JavaScript may choose to represent these
+    // values as either 32-bit integers or doubles, though this should not
+    // affect the result.
     @SmallTest
     @Feature({"AndroidWebView", "Android-JavaBridge"})
     public void testPassNumberInt32() throws Throwable {
@@ -212,21 +213,21 @@
         assertNull(mTestObject.waitForCustomTypeValue());
     }
 
-    // Test passing a JavaScript number in the double range to a method of an
-    // injected object.
-    /*
+    // Test passing a floating-point JavaScript number to a method of an
+    // injected object. JavaScript represents these values as doubles.
     @SmallTest
     @Feature({"AndroidWebView", "Android-JavaBridge"})
-      Bug: http://code.google.com/p/chromium/issues/detail?id=145881
-    */
-    @DisabledTest
     public void testPassNumberDouble() throws Throwable {
         executeJavaScript("testObject.setByteValue(42.1);");
         assertEquals(42, mTestObject.waitForByteValue());
         executeJavaScript("testObject.setByteValue(" + Byte.MAX_VALUE + " + 42.1);");
         assertEquals(Byte.MIN_VALUE + 42 - 1, mTestObject.waitForByteValue());
+        executeJavaScript("testObject.setByteValue(" + Byte.MIN_VALUE + " - 42.1);");
+        assertEquals(Byte.MAX_VALUE - 42 + 1, mTestObject.waitForByteValue());
         executeJavaScript("testObject.setByteValue(" + Integer.MAX_VALUE + " + 42.1);");
         assertEquals(-1, mTestObject.waitForByteValue());
+        executeJavaScript("testObject.setByteValue(" + Integer.MIN_VALUE + " - 42.1);");
+        assertEquals(0, mTestObject.waitForByteValue());
 
         // LIVECONNECT_COMPLIANCE: Should convert to numeric char value.
         executeJavaScript("testObject.setCharValue(42.1);");
@@ -236,18 +237,25 @@
         assertEquals(42, mTestObject.waitForShortValue());
         executeJavaScript("testObject.setShortValue(" + Short.MAX_VALUE + " + 42.1);");
         assertEquals(Short.MIN_VALUE + 42 - 1, mTestObject.waitForShortValue());
+        executeJavaScript("testObject.setShortValue(" + Short.MIN_VALUE + " - 42.1);");
+        assertEquals(Short.MAX_VALUE - 42 + 1, mTestObject.waitForShortValue());
         executeJavaScript("testObject.setShortValue(" + Integer.MAX_VALUE + " + 42.1);");
         assertEquals(-1, mTestObject.waitForShortValue());
+        executeJavaScript("testObject.setShortValue(" + Integer.MIN_VALUE + " - 42.1);");
+        assertEquals(0, mTestObject.waitForShortValue());
 
         executeJavaScript("testObject.setIntValue(42.1);");
         assertEquals(42, mTestObject.waitForIntValue());
         executeJavaScript("testObject.setIntValue(" + Integer.MAX_VALUE + " + 42.1);");
         assertEquals(Integer.MAX_VALUE, mTestObject.waitForIntValue());
+        executeJavaScript("testObject.setIntValue(" + Integer.MIN_VALUE + " - 42.1);");
+        assertEquals(Integer.MIN_VALUE, mTestObject.waitForIntValue());
 
         executeJavaScript("testObject.setLongValue(42.1);");
         assertEquals(42L, mTestObject.waitForLongValue());
-        // LIVECONNECT_COMPLIANCE: Should be Long.MAX_VALUE.
         executeJavaScript("testObject.setLongValue(" + Long.MAX_VALUE + " + 42.1);");
+        assertEquals(Long.MAX_VALUE, mTestObject.waitForLongValue());
+        executeJavaScript("testObject.setLongValue(" + Long.MIN_VALUE + " - 42.1);");
         assertEquals(Long.MIN_VALUE, mTestObject.waitForLongValue());
 
         executeJavaScript("testObject.setFloatValue(42.1);");
@@ -275,12 +283,8 @@
     }
 
     // Test passing JavaScript NaN to a method of an injected object.
-    /*
     @SmallTest
     @Feature({"AndroidWebView", "Android-JavaBridge"})
-      Bug: http://code.google.com/p/chromium/issues/detail?id=145881
-    */
-    @DisabledTest
     public void testPassNumberNaN() throws Throwable {
         executeJavaScript("testObject.setByteValue(Number.NaN);");
         assertEquals(0, mTestObject.waitForByteValue());
@@ -319,12 +323,8 @@
     }
 
     // Test passing JavaScript infinity to a method of an injected object.
-    /*
     @SmallTest
     @Feature({"AndroidWebView", "Android-JavaBridge"})
-      Bug: http://code.google.com/p/chromium/issues/detail?id=145881
-    */
-    @DisabledTest
     public void testPassNumberInfinity() throws Throwable {
         executeJavaScript("testObject.setByteValue(Infinity);");
         assertEquals(-1, mTestObject.waitForByteValue());
@@ -339,9 +339,8 @@
         executeJavaScript("testObject.setIntValue(Infinity);");
         assertEquals(Integer.MAX_VALUE, mTestObject.waitForIntValue());
 
-        // LIVECONNECT_COMPLIANCE: Should be Long.MAX_VALUE.
         executeJavaScript("testObject.setLongValue(Infinity);");
-        assertEquals(-1L, mTestObject.waitForLongValue());
+        assertEquals(Long.MAX_VALUE, mTestObject.waitForLongValue());
 
         executeJavaScript("testObject.setFloatValue(Infinity);");
         assertEquals(Float.POSITIVE_INFINITY, mTestObject.waitForFloatValue());
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/PhoneNumberDetectionTest.java b/content/public/android/javatests/src/org/chromium/content/browser/PhoneNumberDetectionTest.java
index 34432d6..a0ad8d2 100644
--- a/content/public/android/javatests/src/org/chromium/content/browser/PhoneNumberDetectionTest.java
+++ b/content/public/android/javatests/src/org/chromium/content/browser/PhoneNumberDetectionTest.java
@@ -4,10 +4,10 @@
 
 package org.chromium.content.browser;
 
+import android.test.FlakyTest;
 import android.test.suitebuilder.annotation.LargeTest;
 import android.test.suitebuilder.annotation.MediumTest;
 
-import org.chromium.base.test.util.DisabledTest;
 import org.chromium.base.test.util.Feature;
 import org.chromium.content.common.CommandLine;
 
@@ -38,14 +38,12 @@
         startActivityWithTestUrlAndCommandLineArgs(testUrl, cmdlineArgs);
     }
 
-    /*
-    @LargeTest
+    /* @LargeTest */
+    @FlakyTest
     @Feature({"ContentDetection", "TabContents"})
-    http://crbug.com/172786
-    */
-    @DisabledTest
     public void testInternationalNumberIntents() throws Throwable {
         startActivityWithTestUrl("content/content_detection/phone_international.html");
+        assertWaitForPageScaleFactorMatch(1.0f);
 
         // US: +1 650-253-0000.
         String intentUrl = scrollAndTapExpectingIntent("US");
@@ -156,14 +154,12 @@
         assertTrue(isExpectedTelephoneIntent(intentUrl, "+97144509500"));
     }
 
-    /*
-    @MediumTest
+    /* @MediumTest */
+    @FlakyTest
     @Feature({"ContentDetection", "TabContents"})
-    http://crbug.com/172786
-    */
-    @DisabledTest
     public void testLocalUSNumbers() throws Throwable {
         startActivityWithTestUrlAndCountryIso("content/content_detection/phone_local.html", "US");
+        assertWaitForPageScaleFactorMatch(1.0f);
 
         // US_1: 1-888-433-5788.
         String intentUrl = scrollAndTapExpectingIntent("US_1");
@@ -182,14 +178,12 @@
         assertTrue(isExpectedTelephoneIntent(intentUrl, "+31205045100"));
     }
 
-    /*
-    @MediumTest
+    /* @MediumTest */
+    @FlakyTest
     @Feature({"ContentDetection", "TabContents"})
-    http://crbug.com/172786
-    */
-    @DisabledTest
     public void testLocalUKNumbers() throws Throwable {
         startActivityWithTestUrlAndCountryIso("content/content_detection/phone_local.html", "GB");
+        assertWaitForPageScaleFactorMatch(1.0f);
 
         // GB_1: (0) 20 7323 8299.
         String intentUrl = scrollAndTapExpectingIntent("GB_1");
@@ -208,14 +202,12 @@
         assertTrue(isExpectedTelephoneIntent(intentUrl, "+31205045100"));
     }
 
-    /*
-    @MediumTest
+    /* @MediumTest */
+    @FlakyTest
     @Feature({"ContentDetection", "TabContents"})
-    http://crbug.com/172786
-    */
-    @DisabledTest
     public void testLocalFRNumbers() throws Throwable {
         startActivityWithTestUrlAndCountryIso("content/content_detection/phone_local.html", "FR");
+        assertWaitForPageScaleFactorMatch(1.0f);
 
         // FR_1: 01 40 20 50 50.
         String intentUrl = scrollAndTapExpectingIntent("FR_1");
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/ImeTest.java b/content/public/android/javatests/src/org/chromium/content/browser/input/ImeTest.java
similarity index 60%
rename from content/public/android/javatests/src/org/chromium/content/browser/ImeTest.java
rename to content/public/android/javatests/src/org/chromium/content/browser/input/ImeTest.java
index c3e03b6..51bc7b5 100644
--- a/content/public/android/javatests/src/org/chromium/content/browser/ImeTest.java
+++ b/content/public/android/javatests/src/org/chromium/content/browser/input/ImeTest.java
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-package org.chromium.content.browser;
+package org.chromium.content.browser.input;
 
 import android.app.Activity;
 import android.content.ClipData;
@@ -20,19 +20,19 @@
 import org.chromium.base.ThreadUtils;
 import org.chromium.base.test.util.Feature;
 import org.chromium.base.test.util.UrlUtils;
-import org.chromium.content.browser.ImeAdapter.AdapterInputConnection;
+import org.chromium.content.browser.ContentView;
+import org.chromium.content.browser.ContentViewCore;
 import org.chromium.content.browser.test.util.Criteria;
 import org.chromium.content.browser.test.util.CriteriaHelper;
 import org.chromium.content.browser.test.util.DOMUtils;
 import org.chromium.content.browser.test.util.TestCallbackHelperContainer;
 import org.chromium.content_shell_apk.ContentShellTestBase;
 
+import java.util.ArrayList;
 import java.util.concurrent.Callable;
 
 public class ImeTest extends ContentShellTestBase {
 
-    private static final int INVALID_SELECTION = -2;
-    private static final int INVALID_COMPOSITION = -2;
     private static final String DATA_URL = UrlUtils.encodeHtmlDataUri(
             "<html><head><meta name=\"viewport\"" +
             "content=\"width=device-width, initial-scale=1.0, maximum-scale=1.0\" /></head>" +
@@ -70,91 +70,52 @@
         mConnection = (TestAdapterInputConnection) getAdapterInputConnection();
         mImeAdapter = getImeAdapter();
 
-        assertWaitForSetEditableCallback(1, mConnection);
-        assertEquals("", mConnection.mText);
-        assertEquals(0, mConnection.mSelectionStart);
-        assertEquals(0, mConnection.mSelectionEnd);
-        assertEquals(-1, mConnection.mCompositionStart);
-        assertEquals(-1, mConnection.mCompositionEnd);
+        waitAndVerifyEditableCallback(mConnection.mImeUpdateQueue, 0, "", 0, 0, -1, -1);
         assertEquals(1, mInputMethodManagerWrapper.mShowSoftInputCounter);
+        assertEquals(0, mInputMethodManagerWrapper.mEditorInfo.initialSelStart);
+        assertEquals(0, mInputMethodManagerWrapper.mEditorInfo.initialSelEnd);
     }
 
     @MediumTest
     @Feature({"TextInput", "Main"})
     public void testKeyboardDismissedAfterClickingGo() throws Throwable {
-        mImeAdapter.checkCompositionQueueAndCallNative("hello", 1, false);
-        assertWaitForSetEditableCallback(2, mConnection);
-        assertEquals("hello", mConnection.mText);
-        assertEquals(5, mConnection.mSelectionStart);
-        assertEquals(5, mConnection.mSelectionEnd);
-        assertEquals(0, mConnection.mCompositionStart);
-        assertEquals(5, mConnection.mCompositionEnd);
+        mConnection.setComposingText("hello", 1);
+        waitAndVerifyEditableCallback(mConnection.mImeUpdateQueue, 1, "hello", 5, 5, 0, 5);
 
         performGo(getAdapterInputConnection(), mCallbackContainer);
 
-        assertWaitForSetEditableCallback(3, mConnection);
-        assertEquals("", mConnection.mText);
-        assertEquals(0, mConnection.mSelectionStart);
-        assertEquals(0, mConnection.mSelectionEnd);
-        assertEquals(-1, mConnection.mCompositionStart);
-        assertEquals(-1, mConnection.mCompositionEnd);
+        waitAndVerifyEditableCallback(mConnection.mImeUpdateQueue, 2, "", 0, 0, -1, -1);
         assertWaitForKeyboardStatus(false);
     }
 
     @SmallTest
     @Feature({"TextInput", "Main"})
     public void testGetTextUpdatesAfterEnteringText() throws Throwable {
-        mImeAdapter.checkCompositionQueueAndCallNative("h", 1, false);
-        assertWaitForSetEditableCallback(2, mConnection);
-        assertEquals("h", mConnection.mText);
-        assertEquals(1, mConnection.mSelectionStart);
-        assertEquals(1, mConnection.mSelectionEnd);
-        assertEquals(0, mConnection.mCompositionStart);
-        assertEquals(1, mConnection.mCompositionEnd);
+        mConnection.setComposingText("h", 1);
+        waitAndVerifyEditableCallback(mConnection.mImeUpdateQueue, 1, "h", 1, 1, 0, 1);
         assertEquals(1, mInputMethodManagerWrapper.mShowSoftInputCounter);
 
-        mImeAdapter.checkCompositionQueueAndCallNative("he", 1, false);
-        assertWaitForSetEditableCallback(3, mConnection);
-        assertEquals("he", mConnection.mText);
-        assertEquals(2, mConnection.mSelectionStart);
-        assertEquals(2, mConnection.mSelectionEnd);
-        assertEquals(0, mConnection.mCompositionStart);
-        assertEquals(2, mConnection.mCompositionEnd);
+        mConnection.setComposingText("he", 1);
+        waitAndVerifyEditableCallback(mConnection.mImeUpdateQueue, 2, "he", 2, 2, 0, 2);
         assertEquals(1, mInputMethodManagerWrapper.mShowSoftInputCounter);
 
-        mImeAdapter.checkCompositionQueueAndCallNative("hel", 1, false);
-        assertWaitForSetEditableCallback(4, mConnection);
-        assertEquals("hel", mConnection.mText);
-        assertEquals(3, mConnection.mSelectionStart);
-        assertEquals(3, mConnection.mSelectionEnd);
-        assertEquals(0, mConnection.mCompositionStart);
-        assertEquals(3, mConnection.mCompositionEnd);
+        mConnection.setComposingText("hel", 1);
+        waitAndVerifyEditableCallback(mConnection.mImeUpdateQueue, 3, "hel", 3, 3, 0, 3);
         assertEquals(1, mInputMethodManagerWrapper.mShowSoftInputCounter);
 
-        mImeAdapter.checkCompositionQueueAndCallNative("hel", 1, true);
-        assertWaitForSetEditableCallback(5, mConnection);
-        assertEquals("hel", mConnection.mText);
-        assertEquals(3, mConnection.mSelectionStart);
-        assertEquals(3, mConnection.mSelectionEnd);
-        assertEquals(-1, mConnection.mCompositionStart);
-        assertEquals(-1, mConnection.mCompositionEnd);
+        mConnection.commitText("hel", 1);
+        waitAndVerifyEditableCallback(mConnection.mImeUpdateQueue, 4, "hel", 3, 3, -1, -1);
         assertEquals(1, mInputMethodManagerWrapper.mShowSoftInputCounter);
     }
 
     @SmallTest
     @Feature({"TextInput"})
     public void testImeCopy() throws Exception {
-        mImeAdapter.checkCompositionQueueAndCallNative("hello", 1, true);
-        assertWaitForSetEditableCallback(2, mConnection);
-        assertEquals("hello", mConnection.mText);
-        assertEquals(5, mConnection.mSelectionStart);
-        assertEquals(5, mConnection.mSelectionEnd);
+        mConnection.commitText("hello", 1);
+        waitAndVerifyEditableCallback(mConnection.mImeUpdateQueue, 1, "hello", 5, 5, -1, -1);
 
-        mImeAdapter.setEditableSelectionOffsets(2, 5);
-        assertWaitForSetEditableCallback(3, mConnection);
-        assertEquals("hello", mConnection.mText);
-        assertEquals(2, mConnection.mSelectionStart);
-        assertEquals(5, mConnection.mSelectionEnd);
+        mConnection.setSelection(2, 5);
+        waitAndVerifyEditableCallback(mConnection.mImeUpdateQueue, 2, "hello", 2, 5, -1, -1);
 
         mImeAdapter.copy();
         assertClipboardContents(getActivity(), "llo");
@@ -162,24 +123,30 @@
 
     @SmallTest
     @Feature({"TextInput"})
-    public void testImeCut() throws Exception {
-        mImeAdapter.checkCompositionQueueAndCallNative("snarful", 1, true);
-        assertWaitForSetEditableCallback(2, mConnection);
-        assertEquals("snarful", mConnection.mText);
-        assertEquals(7, mConnection.mSelectionStart);
-        assertEquals(7, mConnection.mSelectionEnd);
+    public void testEnterTextAndRefocus() throws Exception {
+        mConnection.commitText("hello", 1);
+        waitAndVerifyEditableCallback(mConnection.mImeUpdateQueue, 1, "hello", 5, 5, -1, -1);
 
-        mImeAdapter.setEditableSelectionOffsets(1, 5);
-        assertWaitForSetEditableCallback(3, mConnection);
-        assertEquals("snarful", mConnection.mText);
-        assertEquals(1, mConnection.mSelectionStart);
-        assertEquals(5, mConnection.mSelectionEnd);
+        DOMUtils.clickNode(this, mContentView, mCallbackContainer, "input_radio");
+        assertWaitForKeyboardStatus(false);
+
+        DOMUtils.clickNode(this, mContentView, mCallbackContainer, "input_text");
+        assertWaitForKeyboardStatus(true);
+        assertEquals(5, mInputMethodManagerWrapper.mEditorInfo.initialSelStart);
+        assertEquals(5, mInputMethodManagerWrapper.mEditorInfo.initialSelEnd);
+    }
+
+    @SmallTest
+    @Feature({"TextInput"})
+    public void testImeCut() throws Exception {
+        mConnection.commitText("snarful", 1);
+        waitAndVerifyEditableCallback(mConnection.mImeUpdateQueue, 1, "snarful", 7, 7, -1, -1);
+
+        mConnection.setSelection(1, 5);
+        waitAndVerifyEditableCallback(mConnection.mImeUpdateQueue, 2, "snarful", 1, 5, -1, -1);
 
         mImeAdapter.cut();
-        assertWaitForSetEditableCallback(4, mConnection);
-        assertEquals("sul", mConnection.mText);
-        assertEquals(1, mConnection.mSelectionStart);
-        assertEquals(1, mConnection.mSelectionEnd);
+        waitAndVerifyEditableCallback(mConnection.mImeUpdateQueue, 3, "sul", 1, 1, -1, -1);
 
         assertClipboardContents(getActivity(), "narf");
     }
@@ -198,50 +165,32 @@
         });
 
         mImeAdapter.paste();
-        assertWaitForSetEditableCallback(2, mConnection);
-        assertEquals("blarg", mConnection.mText);
-        assertEquals(5, mConnection.mSelectionStart);
-        assertEquals(5, mConnection.mSelectionEnd);
+        waitAndVerifyEditableCallback(mConnection.mImeUpdateQueue, 1, "blarg", 5, 5, -1, -1);
 
-        mImeAdapter.setEditableSelectionOffsets(3, 5);
-        assertWaitForSetEditableCallback(3, mConnection);
-        assertEquals("blarg", mConnection.mText);
-        assertEquals(3, mConnection.mSelectionStart);
-        assertEquals(5, mConnection.mSelectionEnd);
+        mConnection.setSelection(3, 5);
+        waitAndVerifyEditableCallback(mConnection.mImeUpdateQueue, 2, "blarg", 3, 5, -1, -1);
 
         mImeAdapter.paste();
-        assertWaitForSetEditableCallback(5, mConnection);
-        assertEquals("blablarg", mConnection.mText);
-        assertEquals(8, mConnection.mSelectionStart);
-        assertEquals(8, mConnection.mSelectionEnd);
+        // Paste is a two step process when there is a non-zero selection.
+        waitAndVerifyEditableCallback(mConnection.mImeUpdateQueue, 3, "bla", 3, 3, -1, -1);
+        waitAndVerifyEditableCallback(mConnection.mImeUpdateQueue, 4, "blablarg", 8, 8, -1, -1);
 
         mImeAdapter.paste();
-        assertWaitForSetEditableCallback(6, mConnection);
-        assertEquals("blablargblarg", mConnection.mText);
-        assertEquals(13, mConnection.mSelectionStart);
-        assertEquals(13, mConnection.mSelectionEnd);
+        waitAndVerifyEditableCallback(
+                mConnection.mImeUpdateQueue, 5, "blablargblarg", 13, 13, -1, -1);
     }
 
     @SmallTest
     @Feature({"TextInput"})
     public void testImeSelectAndUnSelectAll() throws Exception {
-        mImeAdapter.checkCompositionQueueAndCallNative("hello", 1, true);
-        assertWaitForSetEditableCallback(2, mConnection);
-        assertEquals("hello", mConnection.mText);
-        assertEquals(5, mConnection.mSelectionStart);
-        assertEquals(5, mConnection.mSelectionEnd);
+        mConnection.commitText("hello", 1);
+        waitAndVerifyEditableCallback(mConnection.mImeUpdateQueue, 1, "hello", 5, 5, -1, -1);
 
         mImeAdapter.selectAll();
-        assertWaitForSetEditableCallback(3, mConnection);
-        assertEquals("hello", mConnection.mText);
-        assertEquals(0, mConnection.mSelectionStart);
-        assertEquals(5, mConnection.mSelectionEnd);
+        waitAndVerifyEditableCallback(mConnection.mImeUpdateQueue, 2, "hello", 0, 5, -1, -1);
 
         mImeAdapter.unselect();
-        assertWaitForSetEditableCallback(4, mConnection);
-        assertEquals("", mConnection.mText);
-        assertEquals(0, mConnection.mSelectionStart);
-        assertEquals(0, mConnection.mSelectionEnd);
+        waitAndVerifyEditableCallback(mConnection.mImeUpdateQueue, 3, "", 0, 0, -1, -1);
 
         assertWaitForKeyboardStatus(false);
     }
@@ -252,31 +201,16 @@
         mConnection.beginBatchEdit();
         assertWaitForSetIgnoreUpdates(true, mConnection);
 
-        mImeAdapter.checkCompositionQueueAndCallNative("h", 1, false);
-        assertWaitForSetEditableCallback(2, mConnection);
-        assertEquals("h", mConnection.mText);
-        assertEquals(1, mConnection.mSelectionStart);
-        assertEquals(1, mConnection.mSelectionEnd);
-        assertEquals(0, mConnection.mCompositionStart);
-        assertEquals(1, mConnection.mCompositionEnd);
+        mConnection.setComposingText("h", 1);
+        waitAndVerifyEditableCallback(mConnection.mImeUpdateQueue, 1, "h", 1, 1, 0, 1);
         assertTrue(mConnection.isIgnoringTextInputStateUpdates());
 
-        mImeAdapter.checkCompositionQueueAndCallNative("he", 1, false);
-        assertWaitForSetEditableCallback(3, mConnection);
-        assertEquals("he", mConnection.mText);
-        assertEquals(2, mConnection.mSelectionStart);
-        assertEquals(2, mConnection.mSelectionEnd);
-        assertEquals(0, mConnection.mCompositionStart);
-        assertEquals(2, mConnection.mCompositionEnd);
+        mConnection.setComposingText("he", 1);
+        waitAndVerifyEditableCallback(mConnection.mImeUpdateQueue, 2, "he", 2, 2, 0, 2);
         assertTrue(mConnection.isIgnoringTextInputStateUpdates());
 
-        mImeAdapter.checkCompositionQueueAndCallNative("hel", 1, false);
-        assertWaitForSetEditableCallback(4, mConnection);
-        assertEquals("hel", mConnection.mText);
-        assertEquals(3, mConnection.mSelectionStart);
-        assertEquals(3, mConnection.mSelectionEnd);
-        assertEquals(0, mConnection.mCompositionStart);
-        assertEquals(3, mConnection.mCompositionEnd);
+        mConnection.setComposingText("hel", 1);
+        waitAndVerifyEditableCallback(mConnection.mImeUpdateQueue, 3, "hel", 3, 3, 0, 3);
 
         assertEquals(0, mConnection.mUpdateSelectionCounter);
         assertTrue(mConnection.isIgnoringTextInputStateUpdates());
@@ -300,6 +234,27 @@
         assertWaitForKeyboardStatus(true);
     }
 
+    @SmallTest
+    @Feature({"TextInput", "Main"})
+    public void testFinishComposingText() throws Throwable {
+        mConnection.commitText("hllo", 1);
+        waitAndVerifyEditableCallback(mConnection.mImeUpdateQueue, 1, "hllo", 4, 4, -1, -1);
+
+        mConnection.commitText(" ", 1);
+        waitAndVerifyEditableCallback(mConnection.mImeUpdateQueue, 2, "hllo ", 5, 5, -1, -1);
+
+        mConnection.setSelection(1, 1);
+        waitAndVerifyEditableCallback(mConnection.mImeUpdateQueue, 3, "hllo ", 1, 1, -1, -1);
+
+        mConnection.setComposingRegion(0, 4);
+        waitAndVerifyEditableCallback(mConnection.mImeUpdateQueue, 4, "hllo ", 1, 1, 0, 4);
+
+        mConnection.finishComposingText();
+        // finishComposingText() is a two step IME event.
+        waitAndVerifyEditableCallback(mConnection.mImeUpdateQueue, 5, "hllo ", 4, 4, -1, -1);
+        waitAndVerifyEditableCallback(mConnection.mImeUpdateQueue, 6, "hllo ", 1, 1, -1, -1);
+    }
+
     private void performShowImeIfNeeded() {
         ThreadUtils.runOnUiThreadBlocking(new Runnable() {
             @Override
@@ -342,14 +297,17 @@
         }));
     }
 
-    private void assertWaitForSetEditableCallback(final int callbackNumber,
-            final TestAdapterInputConnection connection) throws InterruptedException {
+    private void waitAndVerifyEditableCallback(final ArrayList<TestImeState> states,
+            final int index, String text, int selectionStart, int selectionEnd,
+            int compositionStart, int compositionEnd) throws InterruptedException {
         assertTrue(CriteriaHelper.pollForCriteria(new Criteria() {
             @Override
             public boolean isSatisfied() {
-                return callbackNumber == connection.mSetEditableTextCallCounter;
+                return states.size() > index;
             }
         }));
+        states.get(index).assertEqualState(
+                text, selectionStart, selectionEnd, compositionStart, compositionEnd);
     }
 
     private void assertClipboardContents(final Activity activity, final String expectedContents)
@@ -386,7 +344,7 @@
         return getContentViewCore().getImeAdapterForTest();
     }
 
-    private ImeAdapter.AdapterInputConnection getAdapterInputConnection() {
+    private AdapterInputConnection getAdapterInputConnection() {
         return getContentViewCore().getInputConnectionForTest();
     }
 
@@ -399,14 +357,9 @@
         }
     }
 
-    private static class TestAdapterInputConnection extends ImeAdapter.AdapterInputConnection {
-        private int mSetEditableTextCallCounter = 0;
+    private static class TestAdapterInputConnection extends AdapterInputConnection {
         private int mUpdateSelectionCounter = 0;
-        private String mText;
-        private int mSelectionStart = INVALID_SELECTION;
-        private int mSelectionEnd = INVALID_SELECTION;
-        private int mCompositionStart = INVALID_COMPOSITION;
-        private int mCompositionEnd = INVALID_COMPOSITION;
+        private ArrayList<TestImeState> mImeUpdateQueue = new ArrayList<ImeTest.TestImeState>();
 
         public TestAdapterInputConnection(View view, ImeAdapter imeAdapter, EditorInfo outAttrs) {
             super(view, imeAdapter, outAttrs);
@@ -415,12 +368,8 @@
         @Override
         public void setEditableText(String text, int selectionStart, int selectionEnd,
                 int compositionStart, int compositionEnd) {
-            mText = text;
-            mSelectionStart = selectionStart;
-            mSelectionEnd = selectionEnd;
-            mCompositionStart = compositionStart;
-            mCompositionEnd = compositionEnd;
-            mSetEditableTextCallCounter++;
+            mImeUpdateQueue.add(new TestImeState(text, selectionStart, selectionEnd,
+                    compositionStart, compositionEnd));
             super.setEditableText(
                     text, selectionStart, selectionEnd, compositionStart, compositionEnd);
         }
@@ -437,6 +386,7 @@
         private ContentViewCore mContentViewCore;
         private InputConnection mInputConnection;
         private int mShowSoftInputCounter = 0;
+        private EditorInfo mEditorInfo;
 
         public TestInputMethodManagerWrapper(ContentViewCore contentViewCore) {
             super(null);
@@ -445,14 +395,16 @@
 
         @Override
         public void restartInput(View view) {
-            mInputConnection = mContentViewCore.onCreateInputConnection(new EditorInfo());
+            mEditorInfo = new EditorInfo();
+            mInputConnection = mContentViewCore.onCreateInputConnection(mEditorInfo);
         }
 
         @Override
         public void showSoftInput(View view, int flags, ResultReceiver resultReceiver) {
             mShowSoftInputCounter++;
             if (mInputConnection != null) return;
-            mInputConnection = mContentViewCore.onCreateInputConnection(new EditorInfo());
+            mEditorInfo = new EditorInfo();
+            mInputConnection = mContentViewCore.onCreateInputConnection(mEditorInfo);
         }
 
         @Override
@@ -474,4 +426,30 @@
                 int candidatesStart, int candidatesEnd) {
         }
     }
+
+    private static class TestImeState {
+        private final String mText;
+        private final int mSelectionStart;
+        private final int mSelectionEnd;
+        private final int mCompositionStart;
+        private final int mCompositionEnd;
+
+        public TestImeState(String text, int selectionStart, int selectionEnd,
+                int compositionStart, int compositionEnd) {
+            mText = text;
+            mSelectionStart = selectionStart;
+            mSelectionEnd = selectionEnd;
+            mCompositionStart = compositionStart;
+            mCompositionEnd = compositionEnd;
+        }
+
+        public void assertEqualState(String text, int selectionStart, int selectionEnd,
+                int compositionStart, int compositionEnd) {
+            assertEquals("Text did not match", mText, text);
+            assertEquals("Selection start did not match", mSelectionStart, selectionStart);
+            assertEquals("Selection end did not match", mSelectionEnd, selectionEnd);
+            assertEquals("Composition start did not match", mCompositionStart, compositionStart);
+            assertEquals("Composition end did not match", mCompositionEnd, compositionEnd);
+        }
+    }
 }
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/InsertionHandleTest.java b/content/public/android/javatests/src/org/chromium/content/browser/input/InsertionHandleTest.java
similarity index 96%
rename from content/public/android/javatests/src/org/chromium/content/browser/InsertionHandleTest.java
rename to content/public/android/javatests/src/org/chromium/content/browser/input/InsertionHandleTest.java
index 845e64a..42ee232 100644
--- a/content/public/android/javatests/src/org/chromium/content/browser/InsertionHandleTest.java
+++ b/content/public/android/javatests/src/org/chromium/content/browser/input/InsertionHandleTest.java
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-package org.chromium.content.browser;
+package org.chromium.content.browser.input;
 
 import android.content.ClipData;
 import android.content.ClipboardManager;
@@ -14,6 +14,8 @@
 
 import org.chromium.base.test.util.DisabledTest;
 import org.chromium.base.test.util.Feature;
+import org.chromium.content.browser.ContentView;
+import org.chromium.content.browser.RenderCoordinates;
 import org.chromium.content.browser.test.util.Criteria;
 import org.chromium.content.browser.test.util.CriteriaHelper;
 import org.chromium.content.browser.test.util.DOMUtils;
@@ -190,10 +192,12 @@
                 new TestCallbackHelperContainer(getContentView()), nodeId);
 
         RenderCoordinates renderCoordinates = getContentView().getRenderCoordinates();
-        float left = renderCoordinates.fromLocalCssToPix(nodeBounds.left);
-        float right = renderCoordinates.fromLocalCssToPix(nodeBounds.right);
-        float top = renderCoordinates.fromLocalCssToPix(nodeBounds.top);
-        float bottom = renderCoordinates.fromLocalCssToPix(nodeBounds.bottom);
+        int offsetX = getContentView().getContentViewCore().getViewportSizeOffsetWidthPix();
+        int offsetY = getContentView().getContentViewCore().getViewportSizeOffsetHeightPix();
+        float left = renderCoordinates.fromLocalCssToPix(nodeBounds.left) + offsetX;
+        float right = renderCoordinates.fromLocalCssToPix(nodeBounds.right) + offsetX;
+        float top = renderCoordinates.fromLocalCssToPix(nodeBounds.top) + offsetY;
+        float bottom = renderCoordinates.fromLocalCssToPix(nodeBounds.bottom) + offsetY;
 
         TouchCommon touchCommon = new TouchCommon(this);
         touchCommon.singleClickView(getContentView(),
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/SelectPopupTest.java b/content/public/android/javatests/src/org/chromium/content/browser/input/SelectPopupTest.java
similarity index 97%
rename from content/public/android/javatests/src/org/chromium/content/browser/SelectPopupTest.java
rename to content/public/android/javatests/src/org/chromium/content/browser/input/SelectPopupTest.java
index 81e03c1..7e65a25 100644
--- a/content/public/android/javatests/src/org/chromium/content/browser/SelectPopupTest.java
+++ b/content/public/android/javatests/src/org/chromium/content/browser/input/SelectPopupTest.java
@@ -2,13 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-package org.chromium.content.browser;
+package org.chromium.content.browser.input;
 
 import android.test.suitebuilder.annotation.LargeTest;
 
 import org.chromium.base.test.util.DisabledTest;
 import org.chromium.base.test.util.Feature;
 import org.chromium.base.test.util.UrlUtils;
+import org.chromium.content.browser.ContentView;
 import org.chromium.content.browser.test.util.Criteria;
 import org.chromium.content.browser.test.util.CriteriaHelper;
 import org.chromium.content.browser.test.util.DOMUtils;
diff --git a/content/public/browser/OWNERS b/content/public/browser/OWNERS
deleted file mode 100644
index 39e58a2..0000000
--- a/content/public/browser/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-# rdsmith@chromium.org only for download* files.  All other reviews
-# must use OWNERS from parent directories.  
-rdsmith@chromium.org
diff --git a/content/public/browser/android/compositor.h b/content/public/browser/android/compositor.h
index 4554074..b6a5352 100644
--- a/content/public/browser/android/compositor.h
+++ b/content/public/browser/android/compositor.h
@@ -33,6 +33,9 @@
 
     // The compositor has completed swapping a frame.
     virtual void OnSwapBuffersCompleted() {}
+
+    // The compositor will eventually swap a frame.
+    virtual void OnSwapBuffersPosted() {}
   };
 
   virtual ~Compositor() {}
@@ -86,6 +89,9 @@
   // The buffer is not modified if false is returned.
   virtual bool CompositeAndReadback(void *pixels, const gfx::Rect& rect) = 0;
 
+  // Invalidate the whole viewport.
+  virtual void SetNeedsRedraw() = 0;
+
   // Composite immediately. Used in single-threaded mode.
   virtual void Composite() = 0;
 
diff --git a/content/public/browser/android/content_view_core.h b/content/public/browser/android/content_view_core.h
index b0417de..6ba7e4b 100644
--- a/content/public/browser/android/content_view_core.h
+++ b/content/public/browser/android/content_view_core.h
@@ -17,12 +17,14 @@
 }
 
 namespace gfx {
+class Rect;
 class Size;
 class SizeF;
 class Vector2dF;
 }
 
 namespace ui {
+class ViewAndroid;
 class WindowAndroid;
 }
 
@@ -44,12 +46,10 @@
 
   virtual WebContents* GetWebContents() const = 0;
   virtual base::android::ScopedJavaLocalRef<jobject> GetJavaObject() = 0;
-  virtual base::android::ScopedJavaLocalRef<jobject> GetContainerViewDelegate()
-      = 0;
+  virtual ui::ViewAndroid* GetViewAndroid() const = 0;
   virtual ui::WindowAndroid* GetWindowAndroid() const = 0;
   virtual scoped_refptr<cc::Layer> GetLayer() const = 0;
   virtual void LoadUrl(NavigationController::LoadURLParams& params) = 0;
-  virtual void OnWebPreferencesUpdated() = 0;
   virtual jint GetCurrentRenderProcessId(JNIEnv* env, jobject obj) = 0;
   virtual void ShowPastePopup(int x, int y) = 0;
   virtual unsigned int GetScaledContentTexture(
@@ -58,6 +58,8 @@
   virtual float GetDpiScale() const = 0;
   virtual void SetInputHandler(
       WebKit::WebCompositorInputHandler* input_handler) = 0;
+  virtual void RequestContentClipping(const gfx::Rect& clipping,
+                                      const gfx::Size& content_size) = 0;
 
   // Observer callback for frame metadata updates.
   typedef base::Callback<void(
diff --git a/content/public/browser/android/download_controller_android.h b/content/public/browser/android/download_controller_android.h
index df0470e..65da4b8 100644
--- a/content/public/browser/android/download_controller_android.h
+++ b/content/public/browser/android/download_controller_android.h
@@ -6,10 +6,10 @@
 #define CONTENT_PUBLIC_BROWSER_ANDROID_DOWNLOAD_CONTROLLER_ANDROID_H_
 
 #include "content/common/content_export.h"
+#include "content/public/common/context_menu_params.h"
 
 namespace content {
 class DownloadItem;
-class RenderViewHost;
 class WebContents;
 
 // Interface to request GET downloads and send notifications for POST
@@ -21,11 +21,23 @@
 
   // Starts a new download request with Android. Should be called on the
   // UI thread.
-  virtual void CreateGETDownload(RenderViewHost* source, int request_id) = 0;
+  virtual void CreateGETDownload(int render_process_id, int render_view_id,
+                                 int request_id) = 0;
 
-  // Should be called when a POST download is started. Notifies the embedding
+  // Should be called when a download is started. It can be either a GET
+  // request with authentication or a POST request. Notifies the embedding
   // app about the download. Should be called on the UI thread.
-  virtual void OnPostDownloadStarted(DownloadItem* download_item) = 0;
+  virtual void OnDownloadStarted(DownloadItem* download_item) = 0;
+
+  // Called when a download is initiated by context menu.
+  virtual void StartContextMenuDownload(
+      const ContextMenuParams& params, WebContents* web_contents,
+      bool is_link) = 0;
+
+  // Called when a dangerous download item is verified or rejected.
+  virtual void DangerousDownloadValidated(
+      WebContents* web_contents, int download_id, bool accept) = 0;
+
  protected:
   virtual ~DownloadControllerAndroid() {};
 };
diff --git a/content/public/browser/browser_accessibility_state.h b/content/public/browser/browser_accessibility_state.h
index 16cf706..6f8d6d2 100644
--- a/content/public/browser/browser_accessibility_state.h
+++ b/content/public/browser/browser_accessibility_state.h
@@ -6,6 +6,7 @@
 #define CONTENT_PUBLIC_BROWSER_BROWSER_ACCESSIBILITY_STATE_H_
 
 #include "base/callback_forward.h"
+
 #include "content/common/content_export.h"
 
 namespace content {
@@ -20,8 +21,11 @@
   // Returns the singleton instance.
   static BrowserAccessibilityState* GetInstance();
 
-  // Called when accessibility is enabled manually (via command-line flag).
-  virtual void OnAccessibilityEnabledManually() = 0;
+  // Enables accessibility for all running tabs.
+  virtual void EnableAccessibility() = 0;
+
+  // Disables accessibility for all running tabs.
+  virtual void DisableAccessibility() = 0;
 
   // Called when screen reader client is detected.
   virtual void OnScreenReaderDetected() = 0;
diff --git a/content/public/browser/browser_context.h b/content/public/browser/browser_context.h
index a565cac..c7c664d 100644
--- a/content/public/browser/browser_context.h
+++ b/content/public/browser/browser_context.h
@@ -10,7 +10,7 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/supports_user_data.h"
 #include "content/common/content_export.h"
-#include "ui/base/clipboard/clipboard.h"
+#include "ui/base/clipboard/clipboard_sourcetag.h"
 
 class GURL;
 
@@ -98,8 +98,7 @@
   // Returns a Clipboard::SourceTag (pointer) if |context| is OffTheRecord
   // context. Otherwise, NULL. If the clipboard contains that SourceTag at the
   // time of |context| destruction it will be flushed.
-  static ui::Clipboard::SourceTag GetMarkerForOffTheRecordContext(
-      BrowserContext* context);
+  static ui::SourceTag GetMarkerForOffTheRecordContext(BrowserContext* context);
 
   virtual ~BrowserContext();
 
@@ -107,7 +106,6 @@
   virtual base::FilePath GetPath() = 0;
 
   // Return whether this context is incognito. Default is false.
-  // This doesn't belong here; http://crbug.com/89628
   virtual bool IsOffTheRecord() const = 0;
 
   // Returns the request context information associated with this context.  Call
@@ -118,8 +116,8 @@
 
   // Returns the request context appropriate for the given renderer. If the
   // renderer process doesn't have an associated installed app, or if the
-  // installed app's is_storage_isolated() returns false, this is equivalent to
-  // calling GetRequestContext().
+  // installed app doesn't have isolated storage, this is equivalent to calling
+  // GetRequestContext().
   virtual net::URLRequestContextGetter* GetRequestContextForRenderProcess(
       int renderer_child_id) = 0;
 
diff --git a/content/public/browser/browser_message_filter.cc b/content/public/browser/browser_message_filter.cc
index 4d3c2b2..6a602a9 100644
--- a/content/public/browser/browser_message_filter.cc
+++ b/content/public/browser/browser_message_filter.cc
@@ -31,7 +31,7 @@
 }
 
 void BrowserMessageFilter::OnChannelConnected(int32 peer_pid) {
-  if (!base::OpenProcessHandle(peer_pid, &peer_handle_)) {
+  if (!base::OpenPrivilegedProcessHandle(peer_pid, &peer_handle_)) {
     NOTREACHED();
   }
 }
diff --git a/content/public/browser/browser_ppapi_host.h b/content/public/browser/browser_ppapi_host.h
index d23908e..b831e09 100644
--- a/content/public/browser/browser_ppapi_host.h
+++ b/content/public/browser/browser_ppapi_host.h
@@ -47,7 +47,8 @@
       IPC::ChannelProxy* channel,
       net::HostResolver* host_resolver,
       int render_process_id,
-      int render_view_id);
+      int render_view_id,
+      const base::FilePath& profile_directory);
 
   virtual ~BrowserPpapiHost() {}
 
diff --git a/content/public/browser/browser_thread.h b/content/public/browser/browser_thread.h
index 9ab2052..6e2fc67 100644
--- a/content/public/browser/browser_thread.h
+++ b/content/public/browser/browser_thread.h
@@ -19,9 +19,8 @@
 #include "base/logging.h"
 #endif  // UNIT_TEST
 
-class MessageLoop;
-
 namespace base {
+class MessageLoop;
 class SequencedWorkerPool;
 class Thread;
 }
@@ -216,7 +215,7 @@
   //
   // Ownership remains with the BrowserThread implementation, so you
   // must not delete the pointer.
-  static MessageLoop* UnsafeGetMessageLoopForThread(ID identifier);
+  static base::MessageLoop* UnsafeGetMessageLoopForThread(ID identifier);
 
   // Sets the delegate for the specified BrowserThread.
   //
@@ -268,7 +267,6 @@
   struct DeleteOnIOThread : public DeleteOnThread<IO> { };
   struct DeleteOnFileThread : public DeleteOnThread<FILE> { };
   struct DeleteOnDBThread : public DeleteOnThread<DB> { };
-  struct DeleteOnWebKitThread : public DeleteOnThread<WEBKIT_DEPRECATED> { };
 
  private:
   friend class BrowserThreadImpl;
diff --git a/content/public/browser/content_browser_client.cc b/content/public/browser/content_browser_client.cc
index 27ebe56..05b7da9 100644
--- a/content/public/browser/content_browser_client.cc
+++ b/content/public/browser/content_browser_client.cc
@@ -26,6 +26,14 @@
   return NULL;
 }
 
+GURL ContentBrowserClient::GetPossiblyPrivilegedURL(
+    content::BrowserContext* browser_context,
+    const GURL& url,
+    bool is_renderer_initiated,
+    SiteInstance* current_instance) {
+  return url;
+}
+
 GURL ContentBrowserClient::GetEffectiveURL(BrowserContext* browser_context,
                                            const GURL& url) {
   return url;
@@ -36,10 +44,6 @@
   return false;
 }
 
-std::vector<std::string> ContentBrowserClient::GetAdditionalWebUISchemes() {
-  return std::vector<std::string>();
-}
-
 net::URLRequestContextGetter* ContentBrowserClient::CreateRequestContext(
     BrowserContext* browser_context,
     ProtocolHandlerMap* protocol_handlers) {
diff --git a/content/public/browser/content_browser_client.h b/content/public/browser/content_browser_client.h
index b89fffa..c7fe000 100644
--- a/content/public/browser/content_browser_client.h
+++ b/content/public/browser/content_browser_client.h
@@ -13,9 +13,10 @@
 #include "base/callback_forward.h"
 #include "base/memory/linked_ptr.h"
 #include "base/memory/scoped_ptr.h"
+#include "base/memory/scoped_vector.h"
 #include "content/public/browser/file_descriptor_info.h"
-#include "content/public/common/socket_permission_request.h"
 #include "content/public/common/content_client.h"
+#include "content/public/common/socket_permission_request.h"
 #include "content/public/common/window_container_type.h"
 #include "net/base/mime_util.h"
 #include "net/cookies/canonical_cookie.h"
@@ -29,6 +30,7 @@
 
 class CommandLine;
 class GURL;
+struct WebPreferences;
 
 namespace base {
 class FilePath;
@@ -61,8 +63,8 @@
 class SelectFilePolicy;
 }
 
-namespace webkit_glue {
-struct WebPreferences;
+namespace fileapi {
+class FileSystemMountPointProvider;
 }
 
 namespace content {
@@ -125,9 +127,6 @@
   virtual WebContentsViewDelegate* GetWebContentsViewDelegate(
       WebContents* web_contents);
 
-  // Notifies that a new RenderHostView has been created.
-  virtual void RenderViewHostCreated(RenderViewHost* render_view_host) {}
-
   // Notifies that a <webview> guest WebContents has been created.
   virtual void GuestWebContentsCreated(WebContents* guest_web_contents,
                                        WebContents* embedder_web_contents) {}
@@ -140,6 +139,22 @@
   // Notifies that a BrowserChildProcessHost has been created.
   virtual void BrowserChildProcessHostCreated(BrowserChildProcessHost* host) {}
 
+  // Determines whether a navigation from |current_instance| to |url| would be a
+  // valid entry point to a "privileged site," based on whether it
+  // |is_renderer_initiated|. A privileged site requires careful process
+  // isolation to ensure its privileges do not leak, and it can only be entered
+  // via known navigation paths.
+  //
+  // If this is a valid entry to a privileged site, this function should rewrite
+  // the origin of |url| with a non-http(s) origin that represents the
+  // privileged site. This will distinguish the resulting SiteInstance from
+  // other SiteInstances in the process model.
+  virtual GURL GetPossiblyPrivilegedURL(
+      content::BrowserContext* browser_context,
+      const GURL& url,
+      bool is_renderer_initiated,
+      SiteInstance* current_instance);
+
   // Get the effective URL for the given actual URL, to allow an embedder to
   // group different url schemes in the same SiteInstance.
   virtual GURL GetEffectiveURL(BrowserContext* browser_context,
@@ -154,7 +169,8 @@
   // act as aliases to the chrome: scheme.  The additional schemes may or may
   // not serve specific WebUI pages depending on the particular URLDataSource
   // and its override of URLDataSource::ShouldServiceRequest.
-  virtual std::vector<std::string> GetAdditionalWebUISchemes();
+  virtual void GetAdditionalWebUISchemes(
+      std::vector<std::string>* additional_schemes) {}
 
   // Creates the main net::URLRequestContextGetter. Should only be called once
   // per ContentBrowserClient object.
@@ -441,16 +457,13 @@
   // to the embedder to update it if it wants.
   virtual void OverrideWebkitPrefs(RenderViewHost* render_view_host,
                                    const GURL& url,
-                                   webkit_glue::WebPreferences* prefs) {}
+                                   WebPreferences* prefs) {}
 
   // Inspector setting was changed and should be persisted.
   virtual void UpdateInspectorSetting(RenderViewHost* rvh,
                                       const std::string& key,
                                       const std::string& value) {}
 
-  // Clear the Inspector settings.
-  virtual void ClearInspectorSettings(RenderViewHost* rvh) {}
-
   // Notifies that BrowserURLHandler has been created, so that the embedder can
   // optionally add their own handlers.
   virtual void BrowserURLHandlerCreated(BrowserURLHandler* handler) {}
@@ -496,6 +509,17 @@
   virtual ui::SelectFilePolicy* CreateSelectFilePolicy(
       WebContents* web_contents);
 
+  // Returns additional allowed scheme set which can access files in
+  // FileSystem API.
+  virtual void GetAdditionalAllowedSchemesForFileSystem(
+      std::vector<std::string>* additional_schemes) {}
+
+  // Returns additional MountPointProviders for FileSystem API.
+  virtual void GetAdditionalFileSystemMountPointProviders(
+      const base::FilePath& storage_partition_path,
+      ScopedVector<fileapi::FileSystemMountPointProvider>*
+          additional_providers) {}
+
 #if defined(OS_POSIX) && !defined(OS_MACOSX)
   // Populates |mappings| with all files that need to be mapped before launching
   // a child process.
diff --git a/content/public/browser/cookie_store_factory.h b/content/public/browser/cookie_store_factory.h
new file mode 100644
index 0000000..c7a9c6e
--- /dev/null
+++ b/content/public/browser/cookie_store_factory.h
@@ -0,0 +1,29 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_PUBLIC_BROWSER_COOKIE_STORE_FACTORY_H_
+#define CONTENT_PUBLIC_BROWSER_COOKIE_STORE_FACTORY_H_
+
+#include "content/common/content_export.h"
+#include "net/cookies/cookie_monster.h"
+
+namespace base {
+class FilePath;
+}
+
+namespace quota {
+class SpecialStoragePolicy;
+}
+
+namespace content {
+
+CONTENT_EXPORT net::CookieStore* CreatePersistentCookieStore(
+    const base::FilePath& path,
+    bool restore_old_session_cookies,
+    quota::SpecialStoragePolicy* storage_policy,
+    net::CookieMonster::Delegate* cookie_monster_delegate);
+
+}  // namespace content
+
+#endif  // CONTENT_PUBLIC_BROWSER_COOKIE_STORE_FACTORY_H_
diff --git a/content/public/browser/devtools_agent_host.h b/content/public/browser/devtools_agent_host.h
index 9b9a0cc..80182fe 100644
--- a/content/public/browser/devtools_agent_host.h
+++ b/content/public/browser/devtools_agent_host.h
@@ -52,6 +52,9 @@
   // Returns a list of all existing RenderViewHost's that can be debugged.
   static std::vector<RenderViewHost*> GetValidRenderViewHosts();
 
+  // Returns true if there is a client attached.
+  virtual bool IsAttached() = 0;
+
   // Starts inspecting element at position (|x|, |y|) in the specified page.
   virtual void InspectElement(int x, int y) = 0;
 
diff --git a/content/public/browser/devtools_external_agent_proxy.h b/content/public/browser/devtools_external_agent_proxy.h
new file mode 100644
index 0000000..25d7016
--- /dev/null
+++ b/content/public/browser/devtools_external_agent_proxy.h
@@ -0,0 +1,40 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_PUBLIC_BROWSER_DEVTOOLS_EXTERNAL_AGENT_PROXY_H_
+#define CONTENT_PUBLIC_BROWSER_DEVTOOLS_EXTERNAL_AGENT_PROXY_H_
+
+#include <string>
+
+#include "content/common/content_export.h"
+
+namespace content {
+
+class DevToolsAgentHost;
+class DevToolsExternalAgentProxyDelegate;
+
+// Describes interface for communication with an external DevTools agent.
+class DevToolsExternalAgentProxy {
+ public:
+  // Creates DevToolsExternalAgentProxy to communicate with an agent
+  // via the provided |delegate|.
+  // Caller get the proxy ownership and keeps the |delegate| ownership.
+  static CONTENT_EXPORT DevToolsExternalAgentProxy* Create(
+      DevToolsExternalAgentProxyDelegate* delegate);
+
+  // Returns the local DevToolsAgentHost for the external agent.
+  virtual scoped_refptr<DevToolsAgentHost> GetAgentHost() = 0;
+
+  // Sends the message to the client host.
+  virtual void DispatchOnClientHost(const std::string& message) = 0;
+
+  // Informs the client that the connection has closed.
+  virtual void ConnectionClosed() = 0;
+
+  virtual ~DevToolsExternalAgentProxy() {}
+};
+
+}  // namespace content
+
+#endif  // CONTENT_PUBLIC_BROWSER_DEVTOOLS_EXTERNAL_AGENT_PROXY_H_
diff --git a/content/public/browser/devtools_external_agent_proxy_delegate.h b/content/public/browser/devtools_external_agent_proxy_delegate.h
new file mode 100644
index 0000000..d68854f
--- /dev/null
+++ b/content/public/browser/devtools_external_agent_proxy_delegate.h
@@ -0,0 +1,32 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_PUBLIC_BROWSER_DEVTOOLS_EXTERNAL_AGENT_PROXY_DELEGATE_H_
+#define CONTENT_PUBLIC_BROWSER_DEVTOOLS_EXTERNAL_AGENT_PROXY_DELEGATE_H_
+
+#include <string>
+
+#include "content/common/content_export.h"
+
+namespace content {
+
+// Describes the interface for sending messages to an external DevTools agent.
+class DevToolsExternalAgentProxyDelegate {
+ public:
+   // Informs the agent that a client host has attached.
+   virtual void Attach() = 0;
+
+   // Informs the agent that a client host has detached.
+   virtual void Detach() = 0;
+
+   // Sends a message to the agent.
+   virtual void SendMessageToBackend(const std::string& message) = 0;
+
+ protected:
+  virtual ~DevToolsExternalAgentProxyDelegate() {}
+};
+
+}  // namespace content
+
+#endif  // CONTENT_PUBLIC_BROWSER_DEVTOOLS_EXTERNAL_AGENT_PROXY_DELEGATE_H_
diff --git a/content/public/browser/devtools_http_handler_delegate.h b/content/public/browser/devtools_http_handler_delegate.h
index e9b37d4..4476a17 100644
--- a/content/public/browser/devtools_http_handler_delegate.h
+++ b/content/public/browser/devtools_http_handler_delegate.h
@@ -9,6 +9,8 @@
 #include <vector>
 
 #include "base/files/file_path.h"
+#include "base/memory/ref_counted.h"
+#include "net/socket/stream_listen_socket.h"
 
 class GURL;
 
@@ -47,6 +49,12 @@
 
   // Provides the delegate with an ability to supply a description for views.
   virtual std::string GetViewDescription(content::RenderViewHost*) = 0;
+
+  // Creates named socket for reversed tethering implementation (used with
+  // remote debugging, primarily for mobile).
+  virtual scoped_refptr<net::StreamListenSocket> CreateSocketForTethering(
+      net::StreamListenSocket::Delegate* delegate,
+      std::string* name) = 0;
 };
 
 }  // namespace content
diff --git a/content/public/browser/devtools_manager.h b/content/public/browser/devtools_manager.h
index ae5df5a..32082ea 100644
--- a/content/public/browser/devtools_manager.h
+++ b/content/public/browser/devtools_manager.h
@@ -7,6 +7,7 @@
 
 #include <string>
 
+#include "base/callback.h"
 #include "content/common/content_export.h"
 
 namespace IPC {
@@ -34,31 +35,29 @@
   virtual bool DispatchOnInspectorBackend(DevToolsClientHost* from,
                                           const std::string& message) = 0;
 
-  // Closes all open developer tools windows.
+  // Disconnects all client hostst.
   virtual void CloseAllClientHosts() = 0;
 
-  // Returns client attached to the |agent_host| if there is one.
-  virtual DevToolsClientHost* GetDevToolsClientHostFor(
-      DevToolsAgentHost* agent_host) = 0;
-
-  // Returns agent that has |client_host| attachd to it if there is one.
+  // Returns agent that has |client_host| attached to it if there is one.
   virtual DevToolsAgentHost* GetDevToolsAgentHostFor(
       DevToolsClientHost* client_host) = 0;
 
-  // Registers new DevToolsClientHost for inspected |agent_host|. There must be
-  // no other DevToolsClientHosts registered for the |agent_host| at the moment.
+  // Registers new DevToolsClientHost for inspected |agent_host|. If there is
+  // another DevToolsClientHost registered for the |agent_host| at the moment
+  // it is disconnected.
   virtual void RegisterDevToolsClientHostFor(
       DevToolsAgentHost* agent_host,
       DevToolsClientHost* client_host) = 0;
-  // Unregisters given |agent_host|. DevToolsManager will notify corresponding
-  // client if one is attached.
-  virtual void UnregisterDevToolsClientHostFor(
-      DevToolsAgentHost* agent_host) = 0;
 
   // This method will remove all references from the manager to the
   // DevToolsClientHost and unregister all listeners related to the
   // DevToolsClientHost. Called by closing client.
   virtual void ClientHostClosing(DevToolsClientHost* client_host) = 0;
+
+  typedef base::Callback<void(DevToolsAgentHost*, bool attached)> Callback;
+
+  virtual void AddAgentStateCallback(const Callback& callback) = 0;
+  virtual void RemoveAgentStateCallback(const Callback& callback) = 0;
 };
 
 }  // namespace content
diff --git a/content/public/browser/download_manager.h b/content/public/browser/download_manager.h
index 330aa57..e34f080 100644
--- a/content/public/browser/download_manager.h
+++ b/content/public/browser/download_manager.h
@@ -102,9 +102,6 @@
   // clearing |downloads| first.
   virtual void GetAllDownloads(DownloadVector* downloads) = 0;
 
-  // Returns true if initialized properly.
-  virtual bool Init(BrowserContext* browser_context) = 0;
-
   // Called by a download source (Currently DownloadResourceHandler)
   // to initiate the non-source portions of a download.
   // Returns the id assigned to the download.  If the DownloadCreateInfo
diff --git a/content/public/browser/favicon_status.h b/content/public/browser/favicon_status.h
index 3d1af9a..cfa4773 100644
--- a/content/public/browser/favicon_status.h
+++ b/content/public/browser/favicon_status.h
@@ -8,7 +8,6 @@
 #include "content/common/content_export.h"
 #include "googleurl/src/gurl.h"
 #include "ui/gfx/image/image.h"
-#include "third_party/skia/include/core/SkBitmap.h"
 
 namespace content {
 
diff --git a/content/public/browser/gpu_data_manager.h b/content/public/browser/gpu_data_manager.h
index 8acdda3..f76907a 100644
--- a/content/public/browser/gpu_data_manager.h
+++ b/content/public/browser/gpu_data_manager.h
@@ -11,8 +11,6 @@
 #include "base/callback_forward.h"
 #include "base/process.h"
 #include "content/common/content_export.h"
-#include "content/public/common/gpu_feature_type.h"
-#include "content/public/common/gpu_switching_option.h"
 
 class GURL;
 
@@ -38,7 +36,7 @@
   virtual void InitializeForTesting(const std::string& gpu_blacklist_json,
                                     const content::GPUInfo& gpu_info) = 0;
 
-  virtual GpuFeatureType GetBlacklistedFeatures() const = 0;
+  virtual bool IsFeatureBlacklisted(int feature) const = 0;
 
   virtual GPUInfo GetGPUInfo() const = 0;
 
@@ -52,7 +50,9 @@
   // process, establish GPU channel, and GPU info collection, should be
   // blocked.
   // Can be called on any thread.
-  virtual bool GpuAccessAllowed() const = 0;
+  // If |reason| is not NULL and GPU access is blocked, upon return, |reason|
+  // contains a description of the reason why GPU access is blocked.
+  virtual bool GpuAccessAllowed(std::string* reason) const = 0;
 
   // Requests complete GPUinfo if it has not already been requested
   virtual void RequestCompleteGpuInfoIfNeeded() = 0;
@@ -63,10 +63,10 @@
   // which can be retrieved via the GPU data manager's on-update function.
   virtual void RequestVideoMemoryUsageStatsUpdate() const = 0;
 
-  // Returns true if the software rendering should currently be used.
-  virtual bool ShouldUseSoftwareRendering() const = 0;
+  // Returns true if SwiftShader should be used.
+  virtual bool ShouldUseSwiftShader() const = 0;
 
-  // Register a path to the SwiftShader software renderer.
+  // Register a path to SwiftShader.
   virtual void RegisterSwiftShaderPath(const base::FilePath& path) = 0;
 
   // Registers/unregister |observer|.
diff --git a/content/public/browser/histogram_fetcher.h b/content/public/browser/histogram_fetcher.h
index 73dabde..5e6e090 100644
--- a/content/public/browser/histogram_fetcher.h
+++ b/content/public/browser/histogram_fetcher.h
@@ -10,7 +10,9 @@
 #include "base/time.h"
 #include "content/common/content_export.h"
 
+namespace base {
 class MessageLoop;
+}
 
 namespace content {
 
@@ -21,9 +23,11 @@
 // been acquired, or when the wait time expires (whichever is sooner), post the
 // callback to the specified message loop. Note the callback is posted exactly
 // once.
-CONTENT_EXPORT void FetchHistogramsAsynchronously(MessageLoop* callback_thread,
-                                                  const base::Closure& callback,
-                                                  base::TimeDelta wait_time);
+CONTENT_EXPORT void FetchHistogramsAsynchronously(
+    base::MessageLoop* callback_thread,
+    const base::Closure& callback,
+    base::TimeDelta wait_time);
+
 }  // namespace content
 
 #endif  // CONTENT_PUBLIC_BROWSER_HISTOGRAM_FETCHER_H_
diff --git a/content/public/browser/indexed_db_context.h b/content/public/browser/indexed_db_context.h
index 9d87444..ce3c2c6 100644
--- a/content/public/browser/indexed_db_context.h
+++ b/content/public/browser/indexed_db_context.h
@@ -8,14 +8,10 @@
 #include <vector>
 
 #include "base/basictypes.h"
+#include "base/files/file_path.h"
 #include "base/memory/ref_counted.h"
 #include "content/common/content_export.h"
-
-class GURL;
-
-namespace base {
-class Time;
-}
+#include "content/public/browser/indexed_db_info.h"
 
 namespace content {
 
@@ -25,6 +21,7 @@
  public:
   // Methods used in response to QuotaManager requests.
   virtual std::vector<GURL> GetAllOrigins() = 0;
+  virtual std::vector<IndexedDBInfo> GetAllOriginsInfo() = 0;
   virtual int64 GetOriginDiskUsage(const GURL& origin_url) = 0;
   virtual base::Time GetOriginLastModified(const GURL& origin_url) = 0;
 
diff --git a/content/public/browser/indexed_db_info.cc b/content/public/browser/indexed_db_info.cc
new file mode 100644
index 0000000..6f0116f
--- /dev/null
+++ b/content/public/browser/indexed_db_info.cc
@@ -0,0 +1,16 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/public/browser/indexed_db_info.h"
+
+namespace content {
+
+IndexedDBInfo::IndexedDBInfo(const GURL& origin,
+                             int64 size,
+                             const base::Time& last_modified,
+                             const base::FilePath& path)
+    : origin_(origin), size_(size), last_modified_(last_modified), path_(path) {
+}
+
+}  // namespace content
diff --git a/content/public/browser/indexed_db_info.h b/content/public/browser/indexed_db_info.h
new file mode 100644
index 0000000..951c968
--- /dev/null
+++ b/content/public/browser/indexed_db_info.h
@@ -0,0 +1,30 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_PUBLIC_BROWSER_INDEXED_DB_INFO_H_
+#define CONTENT_PUBLIC_BROWSER_INDEXED_DB_INFO_H_
+
+#include "base/files/file_path.h"
+#include "base/time.h"
+#include "content/common/content_export.h"
+#include "googleurl/src/gurl.h"
+
+namespace content {
+
+class CONTENT_EXPORT IndexedDBInfo {
+ public:
+  IndexedDBInfo(const GURL& origin,
+                int64 size,
+                const base::Time& last_modified,
+                const base::FilePath& path);
+
+  GURL origin_;
+  int64 size_;
+  base::Time last_modified_;
+  base::FilePath path_;
+};
+
+}  // namespace content
+
+#endif  // CONTENT_PUBLIC_BROWSER_INDEXED_DB_INFO_H_
diff --git a/content/public/browser/load_from_memory_cache_details.h b/content/public/browser/load_from_memory_cache_details.h
index 49de85b..1ebf491 100644
--- a/content/public/browser/load_from_memory_cache_details.h
+++ b/content/public/browser/load_from_memory_cache_details.h
@@ -8,7 +8,7 @@
 #include <string>
 #include "base/basictypes.h"
 #include "googleurl/src/gurl.h"
-#include "net/base/cert_status_flags.h"
+#include "net/cert/cert_status_flags.h"
 #include "webkit/glue/resource_type.h"
 
 namespace content {
diff --git a/content/public/browser/media_observer.h b/content/public/browser/media_observer.h
index 6b61528..65c9705 100644
--- a/content/public/browser/media_observer.h
+++ b/content/public/browser/media_observer.h
@@ -14,20 +14,6 @@
 // ContentBrowserClient to receive callbacks as media events occur.
 class MediaObserver {
  public:
-  // Called when capture devices are opened. The observer can call
-  // |close_callback| to stop the stream.
-  virtual void OnCaptureDevicesOpened(
-      int render_process_id,
-      int render_view_id,
-      const MediaStreamDevices& devices,
-      const base::Closure& close_callback) = 0;
-
-  // Called when the opened capture devices are closed.
-  virtual void OnCaptureDevicesClosed(
-      int render_process_id,
-      int render_view_id,
-      const MediaStreamDevices& devices) = 0;
-
   // Called when a audio capture device is plugged in or unplugged.
   virtual void OnAudioCaptureDevicesChanged(
       const MediaStreamDevices& devices) = 0;
@@ -43,12 +29,13 @@
       const MediaStreamDevice& device,
       MediaRequestState state) = 0;
 
-  // Called when an audio stream is played or paused.
+  // Called when an audio stream transitions into playing audible or silent
+  // sound, and when the stream is stopped.
   virtual void OnAudioStreamPlayingChanged(
       int render_process_id,
       int render_view_id,
       int stream_id,
-      bool playing) = 0;
+      bool is_playing_and_audible) = 0;
 
  protected:
   virtual ~MediaObserver() {}
diff --git a/content/public/browser/navigation_controller.cc b/content/public/browser/navigation_controller.cc
index 5fc56dc..fa1dc1b 100644
--- a/content/public/browser/navigation_controller.cc
+++ b/content/public/browser/navigation_controller.cc
@@ -16,7 +16,8 @@
       override_user_agent(UA_OVERRIDE_INHERIT),
       browser_initiated_post_data(NULL),
       can_load_local_resources(false),
-      is_cross_site_redirect(false) {
+      is_cross_site_redirect(false),
+      should_clear_history_list(false)  {
 }
 
 NavigationController::LoadURLParams::~LoadURLParams() {
@@ -35,7 +36,8 @@
       base_url_for_data_url(other.base_url_for_data_url),
       virtual_url_for_data_url(other.virtual_url_for_data_url),
       browser_initiated_post_data(other.browser_initiated_post_data),
-      is_cross_site_redirect(false) {
+      is_cross_site_redirect(false),
+      should_clear_history_list(false) {
 }
 
 NavigationController::LoadURLParams&
@@ -53,6 +55,7 @@
   virtual_url_for_data_url = other.virtual_url_for_data_url;
   browser_initiated_post_data = other.browser_initiated_post_data;
   is_cross_site_redirect = other.is_cross_site_redirect;
+  should_clear_history_list = other.should_clear_history_list;
 
   return *this;
 }
diff --git a/content/public/browser/navigation_controller.h b/content/public/browser/navigation_controller.h
index 1cb18ec..5109301 100644
--- a/content/public/browser/navigation_controller.h
+++ b/content/public/browser/navigation_controller.h
@@ -159,6 +159,14 @@
     // navigated. This is currently only used in tests.
     std::string frame_name;
 
+    // Indicates that during this navigation, the session history should be
+    // cleared such that the resulting page is the first and only entry of the
+    // session history.
+    //
+    // The clearing is done asynchronously, and completes when this navigation
+    // commits.
+    bool should_clear_history_list;
+
     explicit LoadURLParams(const GURL& url);
     ~LoadURLParams();
 
diff --git a/content/public/browser/notification_types.h b/content/public/browser/notification_types.h
index 2902b04..db8654c 100644
--- a/content/public/browser/notification_types.h
+++ b/content/public/browser/notification_types.h
@@ -102,16 +102,6 @@
   // issued.  Details in the form of a ResourceRedirectDetails are provided.
   NOTIFICATION_RESOURCE_RECEIVED_REDIRECT,
 
-  // Devtools ------------------------------------------------------------------
-
-  // Indicates that a devtools agent has attached to a client. The source is
-  // the BrowserContext* and the details is the inspected RenderViewHost*.
-  NOTIFICATION_DEVTOOLS_AGENT_ATTACHED,
-
-  // Indicates that a devtools agent has detached from a client. The source is
-  // the BrowserContext* and the details is the inspected RenderViewHost*.
-  NOTIFICATION_DEVTOOLS_AGENT_DETACHED,
-
   // WebContents ---------------------------------------------------------------
 
   // This notification is sent when a render view host has connected to a
@@ -206,10 +196,6 @@
   // Used only in testing.
   NOTIFICATION_RENDER_WIDGET_HOST_DID_RECEIVE_INPUT_EVENT_ACK,
 
-  // Sent from RenderViewHost constructor. The source is the RenderViewHost,
-  // the details unused.
-  NOTIFICATION_RENDER_VIEW_HOST_CREATED,
-
   // Sent from RenderViewHost::ClosePage.  The hosted RenderView has
   // processed the onbeforeunload handler and is about to be sent a
   // ViewMsg_ClosePage message to complete the tear-down process.  The source
diff --git a/content/public/browser/render_view_host.h b/content/public/browser/render_view_host.h
index 311debe..e59f5bc 100644
--- a/content/public/browser/render_view_host.h
+++ b/content/public/browser/render_view_host.h
@@ -14,6 +14,7 @@
 
 class GURL;
 struct WebDropData;
+struct WebPreferences;
 
 namespace gfx {
 class Point;
@@ -34,10 +35,6 @@
 struct WebPluginAction;
 }
 
-namespace webkit_glue {
-struct WebPreferences;
-}
-
 namespace content {
 
 class ChildProcessSecurityPolicy;
@@ -60,8 +57,6 @@
 // WebContents (see WebContents for an example) but also as views, etc.
 class CONTENT_EXPORT RenderViewHost : virtual public RenderWidgetHost {
  public:
-  typedef base::Callback<void(const base::Value*)> JavascriptResultCallback;
-
   // Returns the RenderViewHost given its ID and the ID of its render process.
   // Returns NULL if the IDs do not correspond to a live RenderViewHost.
   static RenderViewHost* FromID(int render_process_id, int render_view_id);
@@ -77,6 +72,11 @@
                         bool empty_allowed,
                         GURL* url);
 
+  // Adds/removes a callback called on creation of each new RenderViewHost.
+  typedef base::Callback<void(RenderViewHost*)> CreatedCallback;
+  static void AddCreatedCallback(const CreatedCallback& callback);
+  static void RemoveCreatedCallback(const CreatedCallback& callback);
+
   virtual ~RenderViewHost() {}
 
   // Tell the render view to enable a set of javascript bindings. The argument
@@ -178,6 +178,7 @@
 
   // Runs some javascript within the context of a frame in the page. The result
   // is sent back via the provided callback.
+  typedef base::Callback<void(const base::Value*)> JavascriptResultCallback;
   virtual void ExecuteJavascriptInWebFrameCallbackResult(
       const string16& frame_xpath,
       const string16& jscript,
@@ -269,11 +270,10 @@
   virtual void ToggleSpeechInput() = 0;
 
   // Returns the current WebKit preferences.
-  virtual webkit_glue::WebPreferences GetWebkitPreferences() = 0;
+  virtual WebPreferences GetWebkitPreferences() = 0;
 
   // Passes a list of Webkit preferences to the renderer.
-  virtual void UpdateWebkitPreferences(
-      const webkit_glue::WebPreferences& prefs) = 0;
+  virtual void UpdateWebkitPreferences(const WebPreferences& prefs) = 0;
 
   // Informs the renderer process of a change in timezone.
   virtual void NotifyTimezoneChange() = 0;
diff --git a/content/public/browser/render_widget_host_view.h b/content/public/browser/render_widget_host_view.h
index 461ab6d..b881748 100644
--- a/content/public/browser/render_widget_host_view.h
+++ b/content/public/browser/render_widget_host_view.h
@@ -165,9 +165,8 @@
 #endif
 
 #if defined(OS_WIN) && defined(USE_AURA)
-  // Set the parent native accessible view for this View.
-  virtual void SetParentNativeViewAccessible(
-      gfx::NativeViewAccessible accessible_parent) = 0;
+  virtual gfx::NativeViewAccessible AccessibleObjectFromChildId(long child_id)
+      = 0;
 #endif
 };
 
diff --git a/content/public/browser/render_widget_host_view_mac_delegate.h b/content/public/browser/render_widget_host_view_mac_delegate.h
index 4e79fcb..7d24ac92 100644
--- a/content/public/browser/render_widget_host_view_mac_delegate.h
+++ b/content/public/browser/render_widget_host_view_mac_delegate.h
@@ -41,6 +41,9 @@
 - (BOOL)validateUserInterfaceItem:(id<NSValidatedUserInterfaceItem>)item
                       isValidItem:(BOOL*)valid;
 
+// Notification that the compositing IO surface has been created.
+- (void)compositingIOSurfaceCreated;
+
 @end
 
 #endif  // CONTENT_PUBLIC_BROWSER_RENDER_WIDGET_HOST_VIEW_MAC_DELEGATE_H_
diff --git a/content/public/browser/resource_request_details.h b/content/public/browser/resource_request_details.h
index 9504b30..4e94418 100644
--- a/content/public/browser/resource_request_details.h
+++ b/content/public/browser/resource_request_details.h
@@ -8,7 +8,7 @@
 #include <string>
 
 #include "googleurl/src/gurl.h"
-#include "net/base/cert_status_flags.h"
+#include "net/cert/cert_status_flags.h"
 #include "net/base/host_port_pair.h"
 #include "net/url_request/url_request_status.h"
 #include "webkit/glue/resource_type.h"
diff --git a/content/public/browser/storage_partition.h b/content/public/browser/storage_partition.h
index b0348da..bd7f90c 100644
--- a/content/public/browser/storage_partition.h
+++ b/content/public/browser/storage_partition.h
@@ -69,6 +69,12 @@
     kLocalDomStorage = 1 << 3,
     kSessionDomStorage = 1 << 4,
 
+    // Local shader storage.
+    kShaderStorage = 1 << 5,
+
+    // Corresponds to quota::kStorageTypeSyncable.
+    kQuotaManagedSyncableStorage = 1 << 6,
+
     kAllStorage = -1,
   };
 
@@ -91,6 +97,15 @@
   // StoragePartition rather than just the data related to this origin.
   virtual void AsyncClearData(uint32 storage_mask) = 0;
 
+  // Similar to AsyncClearDataForOrigin(), but deletes all the data out of the
+  // StoragePartion from between the given |begin| and |end| dates rather
+  // then just the data related to this origin.
+  //
+  // Note: This currently only supports the shader cache.
+  virtual void AsyncClearDataBetween(uint32 storage_mask,
+                                     const base::Time& begin,
+                                     const base::Time& end,
+                                     const base::Closure& callback) = 0;
  protected:
   virtual ~StoragePartition() {}
 };
diff --git a/content/public/browser/trace_controller.h b/content/public/browser/trace_controller.h
index aac45acf..0049555 100644
--- a/content/public/browser/trace_controller.h
+++ b/content/public/browser/trace_controller.h
@@ -31,10 +31,11 @@
   //   or if another subscriber is tracing,
   //   BeginTracing will return false meaning it failed.
   //
-  // |categories| is a comma-delimited list of category wildcards.
-  // A category can have an optional '-' prefix to make it an excluded category.
+  // |category_patterns| is a comma-delimited list of category wildcards.
+  // A category pattern can have an optional '-' prefix to exclude category
+  // groups that contain a matching category.
   // All the same rules apply above, so for example, having both included and
-  // excluded categories in the same list would not be supported.
+  // excluded category patterns in the same list would not be supported.
   //
   // |mode| is the tracing mode being used.
   //
@@ -42,7 +43,7 @@
   // Example: BeginTracing("test_MyTest*,test_OtherStuff");
   // Example: BeginTracing("-excluded_category1,-excluded_category2");
   virtual bool BeginTracing(TraceSubscriber* subscriber,
-                            const std::string& categories,
+                            const std::string& category_patterns,
                             base::debug::TraceLog::Options options) = 0;
 
   // Called by browser process to stop tracing events on all processes.
@@ -88,10 +89,10 @@
   // Safe to call even if caller is not the current subscriber.
   virtual void CancelSubscriber(TraceSubscriber* subscriber) = 0;
 
-  // Get set of known categories. This can change as new code paths are reached.
-  // If true is returned, subscriber->OnKnownCategoriesCollected will be called
-  // once the categories are retrieved from child processes.
-  virtual bool GetKnownCategoriesAsync(TraceSubscriber* subscriber) = 0;
+  // Get set of known category groups. This can change as new code paths are
+  // reached. If true is returned, subscriber->OnKnownCategoriesCollected will
+  // be called once the categories are retrieved from child processes.
+  virtual bool GetKnownCategoryGroupsAsync(TraceSubscriber* subscriber) = 0;
 
  protected:
   virtual ~TraceController() {}
diff --git a/content/public/browser/trace_subscriber.h b/content/public/browser/trace_subscriber.h
index ec8d070..02e9f1c 100644
--- a/content/public/browser/trace_subscriber.h
+++ b/content/public/browser/trace_subscriber.h
@@ -26,7 +26,7 @@
   virtual void OnTraceDataCollected(
       const scoped_refptr<base::RefCountedString>& trace_fragment) = 0;
 
-  // Called once after TraceController::GetKnownCategoriesAsync.
+  // Called once after TraceController::GetKnownCategoryGroupsAsync.
   virtual void OnKnownCategoriesCollected(
       const std::set<std::string>& known_categories) {}
 
diff --git a/content/public/browser/url_data_source.cc b/content/public/browser/url_data_source.cc
index b3c62b3..669f5c8 100644
--- a/content/public/browser/url_data_source.cc
+++ b/content/public/browser/url_data_source.cc
@@ -16,7 +16,7 @@
   URLDataManager::AddDataSource(browser_context, source);
 }
 
-MessageLoop* URLDataSource::MessageLoopForRequestPath(
+base::MessageLoop* URLDataSource::MessageLoopForRequestPath(
     const std::string& path) const {
   return BrowserThread::UnsafeGetMessageLoopForThread(BrowserThread::UI);
 }
diff --git a/content/public/browser/url_data_source.h b/content/public/browser/url_data_source.h
index 49daf87..d6ff1e0 100644
--- a/content/public/browser/url_data_source.h
+++ b/content/public/browser/url_data_source.h
@@ -10,9 +10,8 @@
 #include "base/callback.h"
 #include "content/common/content_export.h"
 
-class MessageLoop;
-
 namespace base {
+class MessageLoop;
 class RefCountedMemory;
 }
 
@@ -38,7 +37,7 @@
   // 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.
-  virtual std::string GetSource() = 0;
+  virtual std::string GetSource() const = 0;
 
   // Used by StartDataRequest so that the child class can return the data when
   // it's available.
@@ -49,7 +48,8 @@
   // data is available or if the request could not be satisfied. This can be
   // called either in this callback or asynchronously with the response.
   virtual void StartDataRequest(const std::string& path,
-                                bool is_incognito,
+                                int render_process_id,
+                                int render_view_id,
                                 const GotDataCallback& callback) = 0;
 
   // Return the mimetype that should be sent with this response, or empty
@@ -66,7 +66,8 @@
   // on the IO thread.  This can improve performance by satisfying such requests
   // more rapidly when there is a large amount of UI thread contention. Or the
   // delegate can return a specific thread's Messageloop if they wish.
-  virtual MessageLoop* MessageLoopForRequestPath(const std::string& path) const;
+  virtual base::MessageLoop* MessageLoopForRequestPath(
+      const std::string& path) const;
 
   // Returns true if the URLDataSource should replace an existing URLDataSource
   // with the same name that has already been registered. The default is true.
@@ -106,6 +107,13 @@
   // ContentBrowserClient::GetAdditionalWebUISchemes() to permit additional
   // WebUI scheme support for an embedder.
   virtual bool ShouldServiceRequest(const net::URLRequest* request) const;
+
+  // Called to inform the source that StartDataRequest() will be called soon.
+  // Gives the source an opportunity to rewrite |path| to incorporate extra
+  // information from the URLRequest prior to serving.
+  virtual void WillServiceRequest(
+      const net::URLRequest* request,
+      std::string* path) const {}
 };
 
 }  // namespace content
diff --git a/content/public/browser/web_contents.h b/content/public/browser/web_contents.h
index 22f0fab..8a3d038 100644
--- a/content/public/browser/web_contents.h
+++ b/content/public/browser/web_contents.h
@@ -173,8 +173,6 @@
   virtual WebUI* CreateWebUI(const GURL& url) = 0;
 
   // Returns the committed WebUI if one exists, otherwise the pending one.
-  // Callers who want to use the pending WebUI for the pending navigation entry
-  // should use GetWebUIForCurrentState instead.
   virtual WebUI* GetWebUI() const = 0;
   virtual WebUI* GetCommittedWebUI() const = 0;
 
@@ -182,6 +180,11 @@
   virtual void SetUserAgentOverride(const std::string& override) = 0;
   virtual const std::string& GetUserAgentOverride() const = 0;
 
+#if defined(OS_WIN) && defined(USE_AURA)
+  virtual void SetParentNativeViewAccessible(
+      gfx::NativeViewAccessible accessible_parent) = 0;
+#endif
+
   // Tab navigation state ------------------------------------------------------
 
   // Returns the current navigation properties, which if a navigation is
@@ -384,10 +387,6 @@
   // Get the content restrictions (see content::ContentRestriction).
   virtual int GetContentRestrictions() const = 0;
 
-  // Returns the WebUI for the current state of the tab. This will either be
-  // the pending WebUI, the committed WebUI, or NULL.
-  virtual WebUI* GetWebUIForCurrentState()= 0;
-
   // Called when the reponse to a pending mouse lock request has arrived.
   // Returns true if |allowed| is true and the mouse has been successfully
   // locked.
@@ -412,19 +411,19 @@
                               const GURL&, /* image_url */
                               int,  /* requested_size */
                               const std::vector<SkBitmap>& /* bitmaps*/)>
-      FaviconDownloadCallback;
+      ImageDownloadCallback;
 
-  // Sends a request to download the given favicon |url| and returns the unique
+  // Sends a request to download the given image |url| and returns the unique
   // id of the download request. When the download is finished, |callback| will
-  // be called with the bitmaps received from the renderer. If [is_favicon|,
-  // the cookeis are not sent and not accepted during download. Note that
+  // be called with the bitmaps received from the renderer. If |is_favicon| is
+  // true, the cookies are not sent and not accepted during download. Note that
   // |image_size| is a hint for images with multiple sizes. The downloaded image
   // is not resized to the given image_size. If 0 is passed, the first frame of
   // the image is returned.
-  virtual int DownloadFavicon(const GURL& url,
-                              bool is_favicon,
-                              int image_size,
-                              const FaviconDownloadCallback& callback) = 0;
+  virtual int DownloadImage(const GURL& url,
+                            bool is_favicon,
+                            int image_size,
+                            const ImageDownloadCallback& callback) = 0;
 
  private:
   // This interface should only be implemented inside content.
diff --git a/content/public/browser/web_contents_delegate.cc b/content/public/browser/web_contents_delegate.cc
index 7a4409d..db56c7e 100644
--- a/content/public/browser/web_contents_delegate.cc
+++ b/content/public/browser/web_contents_delegate.cc
@@ -69,10 +69,12 @@
   return 0;
 }
 
-bool WebContentsDelegate::CanDownload(RenderViewHost* render_view_host,
-                                      int request_id,
-                                      const std::string& request_method) {
-  return true;
+void WebContentsDelegate::CanDownload(
+    RenderViewHost* render_view_host,
+    int request_id,
+    const std::string& request_method,
+    const base::Callback<void(bool)>& callback) {
+  callback.Run(true);
 }
 
 bool WebContentsDelegate::HandleContextMenu(
diff --git a/content/public/browser/web_contents_delegate.h b/content/public/browser/web_contents_delegate.h
index 6705514..60732ce 100644
--- a/content/public/browser/web_contents_delegate.h
+++ b/content/public/browser/web_contents_delegate.h
@@ -56,8 +56,6 @@
 
 struct OpenURLParams;
 
-typedef base::Callback< void(const MediaStreamDevices&) > MediaResponseCallback;
-
 // Objects implement this interface to get notified about changes in the
 // WebContents and to provide necessary functionality.
 class CONTENT_EXPORT WebContentsDelegate {
@@ -220,9 +218,11 @@
   virtual void WebContentsFocused(WebContents* contents) {}
 
   // Asks the delegate if the given tab can download.
-  virtual bool CanDownload(RenderViewHost* render_view_host,
+  // Invoking the |callback| synchronously is OK.
+  virtual void CanDownload(RenderViewHost* render_view_host,
                            int request_id,
-                           const std::string& request_method);
+                           const std::string& request_method,
+                           const base::Callback<void(bool)>& callback);
 
   // Return much extra vertical space should be allotted to the
   // render view widget during various animations (e.g. infobar closing).
diff --git a/content/public/browser/web_ui.h b/content/public/browser/web_ui.h
index 3e72a64..88632db 100644
--- a/content/public/browser/web_ui.h
+++ b/content/public/browser/web_ui.h
@@ -57,21 +57,6 @@
   // Javascript.
   virtual ui::ScaleFactor GetDeviceScaleFactor() const = 0;
 
-  // Returns true if the favicon should be hidden for the current tab.
-  virtual bool ShouldHideFavicon() const = 0;
-  virtual void HideFavicon() = 0;
-
-  // 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.
-  virtual bool ShouldFocusLocationBarByDefault() const = 0;
-  virtual void FocusLocationBarByDefault() = 0;
-
-  // Returns true if the page's URL should be hidden. Some Web UI pages
-  // like the new tab page will want to hide it.
-  virtual bool ShouldHideURL() const = 0;
-  virtual void HideURL() = 0;
-
   // 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.
diff --git a/content/public/common/child_process_sandbox_support_linux.h b/content/public/common/child_process_sandbox_support_linux.h
index 2094558..f653e35 100644
--- a/content/public/common/child_process_sandbox_support_linux.h
+++ b/content/public/common/child_process_sandbox_support_linux.h
@@ -31,14 +31,16 @@
 
 // GetFontTable loads a specified font table from an open SFNT file.
 //   fd: a file descriptor to the SFNT file. The position doesn't matter.
-//   table: the table in *big-endian* format, or 0 for the whole font file.
+//   table_tag: the table tag in *big-endian* format, or 0 for the entire font.
+//   offset: offset into the table or entire font where loading should start.
+//     The offset must be between 0 and 1 GB - 1.
 //   output: a buffer of size output_length that gets the data.  can be 0, in
 //     which case output_length will be set to the required size in bytes.
 //   output_length: size of output, if it's not 0.
 //
 //   returns: true on success.
-CONTENT_EXPORT bool GetFontTable(int fd, uint32_t table, uint8_t* output,
-                                 size_t* output_length);
+CONTENT_EXPORT bool GetFontTable(int fd, uint32_t table_tag, off_t offset,
+                                 uint8_t* output, size_t* output_length);
 
 };  // namespace content
 
diff --git a/content/public/common/common_param_traits_macros.h b/content/public/common/common_param_traits_macros.h
index 11322eb..306d8b7 100644
--- a/content/public/common/common_param_traits_macros.h
+++ b/content/public/common/common_param_traits_macros.h
@@ -31,7 +31,7 @@
 IPC_ENUM_TRAITS(content::SecurityStyle)
 IPC_ENUM_TRAITS(WebKit::WebReferrerPolicy)
 IPC_ENUM_TRAITS(WindowOpenDisposition)
-IPC_ENUM_TRAITS(webkit_glue::WebPreferences::EditingBehavior)
+IPC_ENUM_TRAITS(webkit_glue::EditingBehavior)
 IPC_ENUM_TRAITS(content::PasswordForm::Type)
 IPC_ENUM_TRAITS(net::RequestPriority)
 
@@ -54,6 +54,7 @@
 IPC_STRUCT_TRAITS_MEMBER(submit_element)
 IPC_STRUCT_TRAITS_MEMBER(username_element)
 IPC_STRUCT_TRAITS_MEMBER(username_value)
+IPC_STRUCT_TRAITS_MEMBER(possible_usernames)
 IPC_STRUCT_TRAITS_MEMBER(password_element)
 IPC_STRUCT_TRAITS_MEMBER(password_value)
 IPC_STRUCT_TRAITS_MEMBER(password_autocomplete_set)
@@ -92,7 +93,7 @@
   IPC_STRUCT_TRAITS_MEMBER(pepper_permissions)
 IPC_STRUCT_TRAITS_END()
 
-IPC_STRUCT_TRAITS_BEGIN(webkit_glue::WebPreferences)
+IPC_STRUCT_TRAITS_BEGIN(WebPreferences)
   IPC_STRUCT_TRAITS_MEMBER(standard_font_family_map)
   IPC_STRUCT_TRAITS_MEMBER(fixed_font_family_map)
   IPC_STRUCT_TRAITS_MEMBER(serif_font_family_map)
@@ -113,7 +114,6 @@
   IPC_STRUCT_TRAITS_MEMBER(images_enabled)
   IPC_STRUCT_TRAITS_MEMBER(plugins_enabled)
   IPC_STRUCT_TRAITS_MEMBER(dom_paste_enabled)
-  IPC_STRUCT_TRAITS_MEMBER(developer_extras_enabled)
   IPC_STRUCT_TRAITS_MEMBER(inspector_settings)
   IPC_STRUCT_TRAITS_MEMBER(site_specific_quirks_enabled)
   IPC_STRUCT_TRAITS_MEMBER(shrinks_standalone_images_to_fit)
@@ -121,8 +121,6 @@
   IPC_STRUCT_TRAITS_MEMBER(text_areas_are_resizable)
   IPC_STRUCT_TRAITS_MEMBER(java_enabled)
   IPC_STRUCT_TRAITS_MEMBER(allow_scripts_to_close_windows)
-  IPC_STRUCT_TRAITS_MEMBER(uses_page_cache)
-  IPC_STRUCT_TRAITS_MEMBER(page_cache_supports_plugins)
   IPC_STRUCT_TRAITS_MEMBER(remote_fonts_enabled)
   IPC_STRUCT_TRAITS_MEMBER(javascript_can_access_clipboard)
   IPC_STRUCT_TRAITS_MEMBER(xss_auditor_enabled)
@@ -136,7 +134,6 @@
   IPC_STRUCT_TRAITS_MEMBER(user_style_sheet_enabled)
   IPC_STRUCT_TRAITS_MEMBER(user_style_sheet_location)
   IPC_STRUCT_TRAITS_MEMBER(author_and_user_styles_enabled)
-  IPC_STRUCT_TRAITS_MEMBER(frame_flattening_enabled)
   IPC_STRUCT_TRAITS_MEMBER(allow_universal_access_from_file_urls)
   IPC_STRUCT_TRAITS_MEMBER(allow_file_access_from_file_urls)
   IPC_STRUCT_TRAITS_MEMBER(webaudio_enabled)
@@ -178,6 +175,7 @@
   IPC_STRUCT_TRAITS_MEMBER(css_shaders_enabled)
   IPC_STRUCT_TRAITS_MEMBER(css_variables_enabled)
   IPC_STRUCT_TRAITS_MEMBER(css_grid_layout_enabled)
+  IPC_STRUCT_TRAITS_MEMBER(lazy_layout_enabled)
   IPC_STRUCT_TRAITS_MEMBER(touch_enabled)
   IPC_STRUCT_TRAITS_MEMBER(device_supports_touch)
   IPC_STRUCT_TRAITS_MEMBER(device_supports_mouse)
@@ -195,6 +193,7 @@
   IPC_STRUCT_TRAITS_MEMBER(smart_insert_delete_enabled)
   IPC_STRUCT_TRAITS_MEMBER(cookie_enabled)
   IPC_STRUCT_TRAITS_MEMBER(apply_page_scale_factor_in_compositor)
+  IPC_STRUCT_TRAITS_MEMBER(spatial_navigation_enabled)
 #if defined(OS_ANDROID)
   IPC_STRUCT_TRAITS_MEMBER(text_autosizing_enabled)
   IPC_STRUCT_TRAITS_MEMBER(font_scale_factor)
@@ -202,6 +201,8 @@
   IPC_STRUCT_TRAITS_MEMBER(double_tap_to_zoom_enabled)
   IPC_STRUCT_TRAITS_MEMBER(user_gesture_required_for_media_playback)
   IPC_STRUCT_TRAITS_MEMBER(default_video_poster_url)
+  IPC_STRUCT_TRAITS_MEMBER(support_deprecated_target_density_dpi)
+  IPC_STRUCT_TRAITS_MEMBER(use_wide_viewport)
 #endif
 IPC_STRUCT_TRAITS_END()
 
diff --git a/content/public/common/content_client.cc b/content/public/common/content_client.cc
index 31bbb8a..96cf48c 100644
--- a/content/public/common/content_client.cc
+++ b/content/public/common/content_client.cc
@@ -5,7 +5,7 @@
 #include "content/public/common/content_client.h"
 
 #include "base/logging.h"
-#include "base/string_piece.h"
+#include "base/strings/string_piece.h"
 #include "ui/gfx/image/image.h"
 #include "webkit/user_agent/user_agent.h"
 
@@ -17,6 +17,21 @@
 
 static ContentClient* g_client;
 
+class InternalTestInitializer {
+ public:
+  static ContentBrowserClient* SetBrowser(ContentBrowserClient* b) {
+    ContentBrowserClient* rv = g_client->browser_;
+    g_client->browser_ = b;
+    return rv;
+  }
+
+  static ContentRendererClient* SetRenderer(ContentRendererClient* r) {
+    ContentRendererClient* rv = g_client->renderer_;
+    g_client->renderer_ = r;
+    return rv;
+  }
+};
+
 void SetContentClient(ContentClient* client) {
   g_client = client;
 
@@ -32,6 +47,14 @@
   return g_client;
 }
 
+ContentBrowserClient* SetBrowserClientForTesting(ContentBrowserClient* b) {
+  return InternalTestInitializer::SetBrowser(b);
+}
+
+ContentRendererClient* SetRendererClientForTesting(ContentRendererClient* r) {
+  return InternalTestInitializer::SetRenderer(r);
+}
+
 const std::string& GetUserAgent(const GURL& url) {
   DCHECK(g_client);
   return webkit_glue::GetUserAgent(url);
diff --git a/content/public/common/content_client.h b/content/public/common/content_client.h
index ab397b0..198ecad 100644
--- a/content/public/common/content_client.h
+++ b/content/public/common/content_client.h
@@ -10,7 +10,7 @@
 
 #include "base/basictypes.h"
 #include "base/string16.h"
-#include "base/string_piece.h"
+#include "base/strings/string_piece.h"
 #include "build/build_config.h"
 #include "content/common/content_export.h"
 #include "ui/base/layout.h"
@@ -57,7 +57,18 @@
 // Setter and getter for the client.  The client should be set early, before any
 // content code is called.
 CONTENT_EXPORT void SetContentClient(ContentClient* client);
-CONTENT_EXPORT ContentClient* GetContentClient();
+
+#if defined(CONTENT_IMPLEMENTATION)
+// Content's embedder API should only be used by content.
+ContentClient* GetContentClient();
+#endif
+
+// Used for tests to override the relevant embedder interfaces. Each method
+// returns the old value.
+CONTENT_EXPORT ContentBrowserClient* SetBrowserClientForTesting(
+    ContentBrowserClient* b);
+CONTENT_EXPORT ContentRendererClient* SetRendererClientForTesting(
+    ContentRendererClient* r);
 
 // Returns the user agent string being used by the browser. SetContentClient()
 // must be called prior to calling this, and this routine must be used
@@ -154,11 +165,9 @@
   virtual std::string GetCarbonInterposePath() const;
 #endif
 
-  void set_browser_for_testing(ContentBrowserClient* c) { browser_ = c; }
-  void set_renderer_for_testing(ContentRendererClient* r) { renderer_ = r; }
-
  private:
   friend class ContentClientInitializer;  // To set these pointers.
+  friend class InternalTestInitializer;
 
   // The embedder API for participating in browser logic.
   ContentBrowserClient* browser_;
diff --git a/content/public/common/content_switches.cc b/content/public/common/content_switches.cc
index 3281123..32b1237 100644
--- a/content/public/common/content_switches.cc
+++ b/content/public/common/content_switches.cc
@@ -44,6 +44,10 @@
 // Disable antialiasing on 2d canvas.
 const char kDisable2dCanvasAntialiasing[]   = "disable-canvas-aa";
 
+// Enable experimental canvas features, e.g. canvas 2D context attributes
+const char kEnableExperimentalCanvasFeatures[]
+                                        = "enable-experimental-canvas-features";
+
 // Disables accelerated compositing.
 const char kDisableAcceleratedCompositing[] = "disable-accelerated-compositing";
 
@@ -73,9 +77,6 @@
 // Disables HTML5 DB support.
 const char kDisableDatabases[]              = "disable-databases";
 
-// Disables data transfer items.
-const char kDisableDataTransferItems[]      = "disable-data-transfer-items";
-
 // Disables desktop notifications (default enabled on windows).
 const char kDisableDesktopNotifications[]   = "disable-desktop-notifications";
 
@@ -133,6 +134,9 @@
 // Manager can be used to terminate the offending process in this case.
 const char kDisableHangMonitor[]            = "disable-hang-monitor";
 
+// Disables HTML-based desktop notifications.
+const char kDisableHTMLNotifications[]      = "disable-html-notifications";
+
 // Disable the RenderThread's HistogramCustomizer.
 const char kDisableHistogramCustomizer[]    = "disable-histogram-customizer";
 
@@ -183,10 +187,7 @@
 // Disable smooth scrolling for testing.
 const char kDisableSmoothScrolling[]        = "disable-smooth-scrolling";
 
-// Disable the seccomp sandbox (Linux only)
-const char kDisableSeccompSandbox[]         = "disable-seccomp-sandbox";
-
-// Disable the seccomp filter sandbox (Linux only)
+// Disable the seccomp filter sandbox (seccomp-bpf) (Linux only).
 const char kDisableSeccompFilterSandbox[]   = "disable-seccomp-filter-sandbox";
 
 // Disable session storage.
@@ -204,6 +205,9 @@
 // Specifies the request key for the continuous speech recognition webservice.
 const char kSpeechRecognitionWebserviceKey[] = "speech-service-key";
 
+// Enables web speech synthesis api.
+const char kEnableSpeechSynthesis[]            = "enable-speech-synthesis";
+
 #if defined(OS_ANDROID)
 // Enable web audio API.
 const char kEnableWebAudio[]                = "enable-webaudio";
@@ -215,11 +219,14 @@
 const char kDisableWebAudio[]               = "disable-webaudio";
 #endif
 
+// Enables Web MIDI API.
+const char kEnableWebMIDI[]                 = "enable-web-midi";
+
 // Don't enforce the same-origin policy. (Used by people testing their sites.)
 const char kDisableWebSecurity[]            = "disable-web-security";
 
-// Disable Web Sockets support.
-const char kDisableWebSockets[]             = "disable-web-sockets";
+// Enable an experimental WebSocket implementation.
+const char kEnableExperimentalWebSocket[] = "enable-experimental-websocket";
 
 // Disables WebKit's XSSAuditor. The XSSAuditor mitigates reflective XSS.
 const char kDisableXSSAuditor[]             = "disable-xss-auditor";
@@ -248,6 +255,12 @@
 // Turns on extremely verbose logging of accessibility events.
 const char kEnableAccessibilityLogging[]    = "enable-accessibility-logging";
 
+// Enable notifications of audible/silent audio output from a render view.
+//
+// TODO(miu): Remove --enable-audible-notifications once the feature goes
+// live.  http://crbug.com/178934
+const char kEnableAudibleNotifications[]   = "enable-audible-notifications";
+
 // Enables browser plugin compositing experiment.
 const char kDisableBrowserPluginCompositing[] =
     "disable-browser-plugin-compositing";
@@ -256,6 +269,10 @@
 const char kEnableBrowserPluginForAllViewTypes[] =
     "enable-browser-plugin-for-all-view-types";
 
+// Enables Drag and Drop into and out of Browser Plugin.
+// kEnableBrowserPluginGuestViews must also be set at this time.
+const char kEnableBrowserPluginDragDrop[]   = "enable-browser-plugin-drag-drop";
+
 // Enable/Disable the creation of compositing layers for fixed position
 // elements. Three options are needed to support four possible scenarios:
 //  1. Default (disabled)
@@ -292,9 +309,6 @@
 // Disables the threaded HTML parser in WebKit
 const char kDisableThreadedHTMLParser[]     = "disable-threaded-html-parser";
 
-// Enables the fastback page cache.
-const char kEnableFastback[]                = "enable-fastback";
-
 // By default, a page is laid out to fill the entire width of the window.
 // This flag fixes the layout of the page to a default of 980 CSS pixels,
 // or to a specified width and height using --enable-fixed-layout=w,h
@@ -337,6 +351,10 @@
 
 // Enables compositor-accelerated touch-screen pinch gestures.
 const char kEnablePinch[]                   = "enable-pinch";
+const char kDisablePinch[]                  = "disable-pinch";
+
+// Enables use of cache if offline, even if it's stale
+const char kEnableOfflineCacheAccess[]      = "enable-offline-cache-access";
 
 // Enable caching of pre-parsed JS script data.  See http://crbug.com/32407.
 const char kEnablePreparsedJsCaching[]      = "enable-preparsed-js-caching";
@@ -361,8 +379,8 @@
 // is denied by the sandbox.
 const char kEnableSandboxLogging[]          = "enable-sandbox-logging";
 
-// Enable the seccomp sandbox (Linux only)
-const char kEnableSeccompSandbox[]          = "enable-seccomp-sandbox";
+// Enable spatial navigation
+const char kEnableSpatialNavigation[]       = "enable-spatial-navigation";
 
 // On platforms that support it, enables smooth scroll animation.
 const char kEnableSmoothScrolling[]         = "enable-smooth-scrolling";
@@ -423,6 +441,11 @@
 // via field trials.
 const char kDisableForceCompositingMode[]   = "disable-force-compositing-mode";
 
+// Enable the synchronous renderer compositor API. See
+// ContentRendererClient::DidCreateSynchronousCompositor()
+const char kEnableSynchronousRendererCompositor[] =
+    "enable-synchronous-renderer-compositor";
+
 // Some field trials may be randomized in the browser, and the randomly selected
 // outcome needs to be propagated to the renderer. For instance, this is used
 // to modify histograms recorded in the renderer, or to get the renderer to
@@ -562,6 +585,11 @@
 // Enables remote debug over HTTP on the specified port.
 const char kRemoteDebuggingPort[]           = "remote-debugging-port";
 
+#if defined(OS_ANDROID)
+// Enables remote debug over HTTP on the specified socket name.
+const char kRemoteDebuggingSocketName[]     = "remote-debugging-socket-name";
+#endif
+
 // Causes the renderer process to throw an assertion on launch.
 const char kRendererAssertTest[]            = "renderer-assert-test";
 
@@ -764,8 +792,16 @@
 // Defer image decoding in WebKit until painting.
 const char kEnableDeferredImageDecoding[] = "enable-deferred-image-decoding";
 
-// Disables history navigation in response to horizontal overscroll.
-const char kDisableOverscrollHistoryNavigation[] =
-    "disable-overscroll-history-navigation";
+// Use a vsync signal from the browser to the renderer to schedule rendering.
+const char kEnableVsyncNotification[] = "enable-vsync-notification";
+
+// Enables or disables history navigation in response to horizontal overscroll.
+// Set the value to '1' to enable the feature, and set to '0' to disable.
+// Defaults to enabled.
+const char kOverscrollHistoryNavigation[] =
+    "overscroll-history-navigation";
+
+// Enables 'image/webp' accept header for image requests.
+const char kEnableWebPInAcceptHeader[] = "enable-webp-in-accept-header";
 
 }  // namespace switches
diff --git a/content/public/common/content_switches.h b/content/public/common/content_switches.h
index 3eb34a1..e31a21f 100644
--- a/content/public/common/content_switches.h
+++ b/content/public/common/content_switches.h
@@ -21,6 +21,7 @@
 CONTENT_EXPORT extern const char kBrowserCrashTest[];
 CONTENT_EXPORT extern const char kBrowserSubprocessPath[];
 CONTENT_EXPORT extern const char kDisable2dCanvasAntialiasing[];
+CONTENT_EXPORT extern const char kEnableExperimentalCanvasFeatures[];
 CONTENT_EXPORT extern const char kDisable3DAPIs[];
 CONTENT_EXPORT extern const char kDisableAccelerated2dCanvas[];
 CONTENT_EXPORT extern const char kDisableAcceleratedCompositing[];
@@ -32,7 +33,6 @@
 CONTENT_EXPORT extern const char kDisableAudio[];
 extern const char kDisableBackingStoreLimit[];
 CONTENT_EXPORT extern const char kDisableDatabases[];
-extern const char kDisableDataTransferItems[];
 extern const char kDisableDesktopNotifications[];
 CONTENT_EXPORT extern const char kDisableDeviceOrientation[];
 #if defined(OS_ANDROID)
@@ -57,6 +57,7 @@
 extern const char kEnableGpuSandbox[];
 extern const char kDisableGpuWatchdog[];
 CONTENT_EXPORT extern const char kDisableHangMonitor[];
+CONTENT_EXPORT extern const char kDisableHTMLNotifications[];
 extern const char kDisableHistogramCustomizer[];
 extern const char kDisableImageTransportSurface[];
 CONTENT_EXPORT extern const char kDisableJava[];
@@ -69,29 +70,32 @@
 extern const char kDisableRemoteFonts[];
 extern const char kDisableRendererAccessibility[];
 extern const char kDisableSSLFalseStart[];
-extern const char kDisableSeccompSandbox[];
 extern const char kDisableSeccompFilterSandbox[];
 extern const char kDisableSessionStorage[];
 extern const char kDisableSharedWorkers[];
 extern const char kDisableSiteSpecificQuirks[];
 CONTENT_EXPORT extern const char kDisableSpeechInput[];
 extern const char kSpeechRecognitionWebserviceKey[];
+CONTENT_EXPORT extern const char kEnableSpeechSynthesis[];
 #if defined(OS_ANDROID)
 CONTENT_EXPORT extern const char kEnableWebAudio[];
 CONTENT_EXPORT extern const char kDisableWebRTC[];
 #else
 CONTENT_EXPORT extern const char kDisableWebAudio[];
 #endif
+extern const char kEnableWebMIDI[];
 extern const char kDisableWebSecurity[];
-extern const char kDisableWebSockets[];
+extern const char kEnableExperimentalWebSocket[];
 extern const char kDisableXSSAuditor[];
 CONTENT_EXPORT extern const char kDomAutomationController[];
 CONTENT_EXPORT extern const char kReduceSecurityForDomAutomationTests[];
 CONTENT_EXPORT extern const char kEnableAcceleratedPainting[];
 CONTENT_EXPORT extern const char kEnableAcceleratedFilters[];
 extern const char kEnableAccessibilityLogging[];
+extern const char kEnableAudibleNotifications[];
 CONTENT_EXPORT extern const char kDisableBrowserPluginCompositing[];
 CONTENT_EXPORT extern const char kEnableBrowserPluginForAllViewTypes[];
+CONTENT_EXPORT extern const char kEnableBrowserPluginDragDrop[];
 CONTENT_EXPORT extern const char kEnableCompositingForFixedPosition[];
 CONTENT_EXPORT extern const char kEnableHighDpiCompositingForFixedPosition[];
 CONTENT_EXPORT extern const char kDisableCompositingForFixedPosition[];
@@ -101,7 +105,6 @@
 CONTENT_EXPORT extern const char kEnableDownloadResumption[];
 CONTENT_EXPORT extern const char kEnableExperimentalWebKitFeatures[];
 CONTENT_EXPORT extern const char kDisableThreadedHTMLParser[];
-extern const char kEnableFastback[];
 CONTENT_EXPORT extern const char kEnableFixedLayout[];
 CONTENT_EXPORT extern const char kDisableFullScreen[];
 CONTENT_EXPORT extern const char kEnableTextServicesFramework[];
@@ -116,16 +119,19 @@
 extern const char kEnableMonitorProfile[];
 extern const char kEnableUserMediaScreenCapturing[];
 extern const char kEnablePinch[];
+CONTENT_EXPORT extern const char kEnableOfflineCacheAccess[];
+extern const char kDisablePinch[];
 extern const char kEnablePreparsedJsCaching[];
 CONTENT_EXPORT extern const char kEnablePrivilegedWebGLExtensions[];
 extern const char kEnablePruneGpuCommandBuffers[];
 extern const char kEnableSSLCachedInfo[];
 extern const char kEnableSandboxLogging[];
-extern const char kEnableSeccompSandbox[];
+extern const char kEnableSpatialNavigation[];
 CONTENT_EXPORT extern const char kEnableSoftwareCompositingGLAdapter[];
 CONTENT_EXPORT extern const char kEnableSmoothScrolling[];
 CONTENT_EXPORT extern const char kEnableStatsTable[];
 extern const char kEnableStrictSiteIsolation[];
+CONTENT_EXPORT extern const char kEnableSynchronousRendererCompositor[];
 CONTENT_EXPORT extern const char kEnableThreadedCompositing[];
 CONTENT_EXPORT extern const char kDisableThreadedCompositing[];
 extern const char kEnableVirtualGLContexts[];
@@ -171,6 +177,9 @@
 CONTENT_EXPORT extern const char kProcessType[];
 CONTENT_EXPORT extern const char kRegisterPepperPlugins[];
 CONTENT_EXPORT extern const char kRemoteDebuggingPort[];
+#if defined(OS_ANDROID)
+CONTENT_EXPORT extern const char kRemoteDebuggingSocketName[];
+#endif
 CONTENT_EXPORT extern const char kRendererAssertTest[];
 extern const char kRendererCmdPrefix[];
 CONTENT_EXPORT extern const char kRendererProcess[];
@@ -211,6 +220,7 @@
 CONTENT_EXPORT extern const char kEnableFixedPositionCreatesStackingContext[];
 CONTENT_EXPORT extern const char kDisableFixedPositionCreatesStackingContext[];
 CONTENT_EXPORT extern const char kEnableDeferredImageDecoding[];
+CONTENT_EXPORT extern const char kEnableVsyncNotification[];
 
 extern const char kEnableVisualWordMovement[];
 CONTENT_EXPORT extern const char kUseMobileUserAgent[];
@@ -219,7 +229,7 @@
 extern const char kDisableMediaHistoryLogging[];
 extern const char kDisableGestureRequirementForMediaPlayback[];
 extern const char kNetworkCountryIso[];
-extern const char kEnableWebViewSynchronousAPIs[];
+CONTENT_EXPORT extern const char kEnableWebViewSynchronousAPIs[];
 #endif
 
 #if defined(OS_CHROMEOS)
@@ -238,7 +248,9 @@
 CONTENT_EXPORT extern const char kTestCompositor[];
 #endif
 
-CONTENT_EXPORT extern const char kDisableOverscrollHistoryNavigation[];
+extern const char kEnableWebPInAcceptHeader[];
+
+CONTENT_EXPORT extern const char kOverscrollHistoryNavigation[];
 
 }  // namespace switches
 
diff --git a/content/public/common/gpu_feature_type.h b/content/public/common/gpu_feature_type.h
index 892f41e..5822b7b 100644
--- a/content/public/common/gpu_feature_type.h
+++ b/content/public/common/gpu_feature_type.h
@@ -11,34 +11,20 @@
 // on which chrome is currently running.
 // If a bit is set to 1, corresponding feature is blacklisted.
 enum GpuFeatureType {
-  GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS = 1 << 0,
-  GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING = 1 << 1,
-  GPU_FEATURE_TYPE_WEBGL = 1 << 2,
-  GPU_FEATURE_TYPE_MULTISAMPLING = 1 << 3,
-  GPU_FEATURE_TYPE_FLASH3D = 1 << 4,
-  GPU_FEATURE_TYPE_FLASH_STAGE3D = 1 << 5,
-  GPU_FEATURE_TYPE_TEXTURE_SHARING = 1 << 6,
-  GPU_FEATURE_TYPE_ACCELERATED_VIDEO_DECODE = 1 << 7,
-  GPU_FEATURE_TYPE_3D_CSS = 1 << 8,
-  GPU_FEATURE_TYPE_ACCELERATED_VIDEO = 1 << 9,
-  GPU_FEATURE_TYPE_PANEL_FITTING = 1 << 10,
-  GPU_FEATURE_TYPE_FORCE_COMPOSITING_MODE = 1 << 11,
-  GPU_FEATURE_TYPE_FLASH_STAGE3D_BASELINE = 1 << 12,
-  GPU_FEATURE_TYPE_ALL = GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS |
-                         GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING |
-                         GPU_FEATURE_TYPE_WEBGL |
-                         GPU_FEATURE_TYPE_MULTISAMPLING |
-                         GPU_FEATURE_TYPE_FLASH3D |
-                         GPU_FEATURE_TYPE_FLASH_STAGE3D |
-                         GPU_FEATURE_TYPE_TEXTURE_SHARING |
-                         GPU_FEATURE_TYPE_ACCELERATED_VIDEO_DECODE |
-                         GPU_FEATURE_TYPE_3D_CSS |
-                         GPU_FEATURE_TYPE_ACCELERATED_VIDEO |
-                         GPU_FEATURE_TYPE_PANEL_FITTING |
-                         GPU_FEATURE_TYPE_FORCE_COMPOSITING_MODE |
-                         GPU_FEATURE_TYPE_FLASH_STAGE3D_BASELINE,
-  // All flags initialized to false, i.e., no feature is blacklisted.
-  GPU_FEATURE_TYPE_UNKNOWN = 0
+  GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS = 0,
+  GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING,
+  GPU_FEATURE_TYPE_WEBGL,
+  GPU_FEATURE_TYPE_MULTISAMPLING,
+  GPU_FEATURE_TYPE_FLASH3D,
+  GPU_FEATURE_TYPE_FLASH_STAGE3D,
+  GPU_FEATURE_TYPE_TEXTURE_SHARING,
+  GPU_FEATURE_TYPE_ACCELERATED_VIDEO_DECODE,
+  GPU_FEATURE_TYPE_3D_CSS,
+  GPU_FEATURE_TYPE_ACCELERATED_VIDEO,
+  GPU_FEATURE_TYPE_PANEL_FITTING,
+  GPU_FEATURE_TYPE_FORCE_COMPOSITING_MODE,
+  GPU_FEATURE_TYPE_FLASH_STAGE3D_BASELINE,
+  NUMBER_OF_GPU_FEATURE_TYPES
 };
 
 }  // namespace content
diff --git a/content/public/common/media_stream_request.h b/content/public/common/media_stream_request.h
index 0118f3b..50545eb 100644
--- a/content/public/common/media_stream_request.h
+++ b/content/public/common/media_stream_request.h
@@ -10,6 +10,8 @@
 #include <vector>
 
 #include "base/basictypes.h"
+#include "base/callback_forward.h"
+#include "base/memory/scoped_ptr.h"
 #include "content/common/content_export.h"
 #include "googleurl/src/gurl.h"
 
@@ -131,6 +133,23 @@
   MediaStreamType video_type;
 };
 
+// Interface used by the content layer to notify chrome about changes in the
+// state of a media stream. Instances of this class are passed to content layer
+// when MediaStream access is approved using MediaResponseCallback.
+class MediaStreamUI {
+ public:
+  virtual ~MediaStreamUI() {}
+
+  // Called when MediaStream capturing is started. Chrome layer can call |stop|
+  // to stop the stream.
+  virtual void OnStarted(const base::Closure& stop) = 0;
+};
+
+// Callback used return results of media access requests.
+typedef base::Callback<void(
+    const MediaStreamDevices& devices,
+    scoped_ptr<MediaStreamUI> ui)> MediaResponseCallback;
+
 }  // namespace content
 
 #endif  // CONTENT_PUBLIC_COMMON_MEDIA_STREAM_REQUEST_H_
diff --git a/content/public/common/page_transition_types_list.h b/content/public/common/page_transition_types_list.h
index 3f7076c..de00ca9 100644
--- a/content/public/common/page_transition_types_list.h
+++ b/content/public/common/page_transition_types_list.h
@@ -100,6 +100,9 @@
 // Any of the core values above can be augmented by one or more qualifiers.
 // These qualifiers further define the transition.
 
+// A managed user attempted to visit a URL but was blocked.
+PAGE_TRANSITION(BLOCKED, 0x00800000)
+
 // User used the Forward or Back button to navigate among browsing history.
 PAGE_TRANSITION(FORWARD_BACK, 0x01000000)
 
diff --git a/content/public/common/password_form.h b/content/public/common/password_form.h
index bfc4655..21b2e56 100644
--- a/content/public/common/password_form.h
+++ b/content/public/common/password_form.h
@@ -7,6 +7,7 @@
 
 #include <map>
 #include <string>
+#include <vector>
 
 #include "base/time.h"
 #include "content/common/content_export.h"
@@ -89,6 +90,13 @@
   // has implemented some form of autofill.
   string16 username_value;
 
+  // This member is populated in cases where we there are multiple input
+  // elements that could possibly be the username. Used when our heuristics for
+  // determining the username are incorrect. Optional.
+  //
+  // When parsing an HTML form, this is typically empty.
+  std::vector<string16> possible_usernames;
+
   // The name of the password input element, Optional (improves scoring).
   //
   // When parsing an HTML form, this must always be set.
diff --git a/content/public/common/sandbox_init.h b/content/public/common/sandbox_init.h
index 646b083..b5ff62c 100644
--- a/content/public/common/sandbox_init.h
+++ b/content/public/common/sandbox_init.h
@@ -78,19 +78,6 @@
 CONTENT_EXPORT bool InitializeSandbox(int sandbox_type,
                                       const base::FilePath& allowed_path);
 
-#elif defined(OS_LINUX)
-
-// Initialize the sandbox (currently seccomp-legacy or seccomp-bpf, the setuid
-// sandbox works differently and is set-up in the Zygote).
-// The process sandbox type is determined at run time via the command line
-// switches. TODO(jln): switch to a model where the caller chooses a sandbox
-// type.
-// This should be called before any additional thread has been created.
-//
-// Returns true if a sandbox has been initialized successfully, false
-// otherwise.
-CONTENT_EXPORT bool InitializeSandbox();
-
 #endif
 
 }  // namespace content
diff --git a/content/public/common/sandbox_linux.h b/content/public/common/sandbox_linux.h
index ac63433..6824d55 100644
--- a/content/public/common/sandbox_linux.h
+++ b/content/public/common/sandbox_linux.h
@@ -20,11 +20,8 @@
   // SUID sandbox is using the network namespace.
   kSandboxLinuxNetNS = 1 << 2,
 
-  // seccomp-legacy sandbox active.
-  kSandboxLinuxSeccompLegacy = 1 << 3,
-
   // seccomp-bpf sandbox active.
-  kSandboxLinuxSeccompBpf = 1 << 4,
+  kSandboxLinuxSeccompBpf = 1 << 3,
 };
 
 }  // namespace content
diff --git a/content/public/common/socket_permission_request.h b/content/public/common/socket_permission_request.h
index 2743eeb..d2d0ea2 100644
--- a/content/public/common/socket_permission_request.h
+++ b/content/public/common/socket_permission_request.h
@@ -18,6 +18,7 @@
     TCP_LISTEN,
     UDP_BIND,
     UDP_SEND_TO,
+    UDP_MULTICAST_MEMBERSHIP
   };
 
   SocketPermissionRequest(OperationType type,
diff --git a/content/public/common/ssl_status.h b/content/public/common/ssl_status.h
index 5d750a0..049a5af 100644
--- a/content/public/common/ssl_status.h
+++ b/content/public/common/ssl_status.h
@@ -7,7 +7,7 @@
 
 #include "content/common/content_export.h"
 #include "content/public/common/security_style.h"
-#include "net/base/cert_status_flags.h"
+#include "net/cert/cert_status_flags.h"
 
 namespace content {
 
diff --git a/content/public/common/url_constants.cc b/content/public/common/url_constants.cc
index 40b3b03..1a03fa5 100644
--- a/content/public/common/url_constants.cc
+++ b/content/public/common/url_constants.cc
@@ -32,11 +32,16 @@
 
 const char kAboutBlankURL[] = "about:blank";
 const char kAboutSrcDocURL[] = "about:srcdoc";
+
+}  // namespace chrome
+
+namespace content {
+
 const char kChromeUIAppCacheInternalsHost[] = "appcache-internals";
+const char kChromeUIIndexedDBInternalsHost[] = "indexeddb-internals";
 const char kChromeUIAccessibilityHost[] = "accessibility";
 const char kChromeUIBlobInternalsHost[] = "blob-internals";
 const char kChromeUIBrowserCrashHost[] = "inducebrowsercrashforrealz";
-const char kChromeUIDevToolsHost[] = "devtools";
 const char kChromeUIGpuHost[] = "gpu";
 const char kChromeUIHistogramHost[] = "histograms";
 const char kChromeUIMediaInternalsHost[] = "media-internals";
@@ -46,10 +51,6 @@
 const char kChromeUITracingHost[] = "tracing";
 const char kChromeUIWebRTCInternalsHost[] = "webrtc-internals";
 
-}  // namespace chrome
-
-namespace content {
-
 const char kChromeUICrashURL[] = "chrome://crash";
 const char kChromeUIGpuCleanURL[] = "chrome://gpuclean";
 const char kChromeUIGpuCrashURL[] = "chrome://gpucrash";
diff --git a/content/public/common/url_constants.h b/content/public/common/url_constants.h
index ef45d26..515a45f 100644
--- a/content/public/common/url_constants.h
+++ b/content/public/common/url_constants.h
@@ -27,7 +27,6 @@
 CONTENT_EXPORT extern const char kFileSystemScheme[];
 CONTENT_EXPORT extern const char kFtpScheme[];
 CONTENT_EXPORT extern const char kGuestScheme[];
-CONTENT_EXPORT extern const char kChromeUIGpuHost[];
 CONTENT_EXPORT extern const char kHttpScheme[];
 CONTENT_EXPORT extern const char kHttpsScheme[];
 CONTENT_EXPORT extern const char kJavaScriptScheme[];
@@ -39,12 +38,18 @@
 // Hosts for about URLs.
 CONTENT_EXPORT extern const char kAboutBlankURL[];
 CONTENT_EXPORT extern const char kAboutSrcDocURL[];
+
+}  // namespace chrome
+
+namespace content {
+
 CONTENT_EXPORT extern const char kChromeUIAccessibilityHost[];
 CONTENT_EXPORT extern const char kChromeUIAppCacheInternalsHost[];
 CONTENT_EXPORT extern const char kChromeUIBlobInternalsHost[];
 CONTENT_EXPORT extern const char kChromeUIBrowserCrashHost[];
-CONTENT_EXPORT extern const char kChromeUIDevToolsHost[];
+CONTENT_EXPORT extern const char kChromeUIGpuHost[];
 CONTENT_EXPORT extern const char kChromeUIHistogramHost[];
+CONTENT_EXPORT extern const char kChromeUIIndexedDBInternalsHost[];
 CONTENT_EXPORT extern const char kChromeUIMediaInternalsHost[];
 CONTENT_EXPORT extern const char kChromeUINetworkViewCacheHost[];
 CONTENT_EXPORT extern const char kChromeUIResourcesHost[];
@@ -52,10 +57,6 @@
 CONTENT_EXPORT extern const char kChromeUITracingHost[];
 CONTENT_EXPORT extern const char kChromeUIWebRTCInternalsHost[];
 
-}  // namespace chrome
-
-namespace content {
-
 // Full about URLs (including schemes).
 CONTENT_EXPORT extern const char kChromeUICrashURL[];
 CONTENT_EXPORT extern const char kChromeUIGpuCleanURL[];
diff --git a/content/public/renderer/android/OWNERS b/content/public/renderer/android/OWNERS
new file mode 100644
index 0000000..cff1ac9
--- /dev/null
+++ b/content/public/renderer/android/OWNERS
@@ -0,0 +1,6 @@
+# While the SynchronousCompositor API is in active development include
+# all the following owners in any changes under this path.
+
+jamesr@chromium.org
+joth@chromium.org
+mkosiba@chromium.org
diff --git a/content/public/renderer/android/synchronous_compositor.h b/content/public/renderer/android/synchronous_compositor.h
new file mode 100644
index 0000000..f0c380d
--- /dev/null
+++ b/content/public/renderer/android/synchronous_compositor.h
@@ -0,0 +1,35 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_PUBLIC_RENDERER_ANDROID_SYNCHRONOUS_COMPOSTIOR_
+#define CONTENT_PUBLIC_RENDERER_ANDROID_SYNCHRONOUS_COMPOSITOR_
+
+class SkCanvas;
+
+namespace content {
+
+class SynchronousCompositorClient;
+
+// Interface for embedders that which to direct compositing operations
+// synchronously under their own control. Only meaningful when the
+// kEnableSyncrhonousRendererCompositor flag is specified.
+class SynchronousCompositor {
+ public:
+  // Allows changing or resetting the client to NULL (this must be used if
+  // the client is being deleted prior to the DidDestroyCompositor() call
+  // being received by the client). Ownership of |client| remains with
+  // the caller.
+  virtual void SetClient(SynchronousCompositorClient* client) = 0;
+
+  // "On demand" SW draw, into the supplied canvas (observing the transform
+  // and clip set there-in).
+  virtual bool DemandDrawSw(SkCanvas* canvas) = 0;
+
+ protected:
+  virtual ~SynchronousCompositor() {}
+};
+
+}  // namespace content
+
+#endif  // CONTENT_PUBLIC_RENDERER_ANDROID_SYNCHRONOUS_COMPOSTIOR_
diff --git a/content/public/renderer/android/synchronous_compositor_client.h b/content/public/renderer/android/synchronous_compositor_client.h
new file mode 100644
index 0000000..dcbe09a
--- /dev/null
+++ b/content/public/renderer/android/synchronous_compositor_client.h
@@ -0,0 +1,28 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_PUBLIC_RENDERER_ANDROID_SYNCHRONOUS_COMPOSTIOR_CLIENT_H_
+#define CONTENT_PUBLIC_RENDERER_ANDROID_SYNCRHONOUS_COMPOSITOR_CLIENT_H_
+
+namespace content {
+
+class SynchronousCompositor;
+
+class SynchronousCompositorClient {
+ public:
+  // Indication to the client that |compositor| is going out of scope, and
+  // must not be accessed within or after this call.
+  // NOTE if the client goes away before the compositor it must call
+  // SynchronousCompositor::SetClient(NULL) to release the back pointer.
+  virtual void DidDestroyCompositor(SynchronousCompositor* compositor) = 0;
+
+  // TODO(joth): Add scroll getters and setters, and invalidations.
+
+ protected:
+  virtual ~SynchronousCompositorClient() {}
+};
+
+}  // namespace content
+
+#endif  // CONTENT_PUBLIC_RENDERER_ANDROID_SYNCHRONOUS_COMPOSTIOR_CLIENT_H_
diff --git a/content/public/renderer/content_renderer_client.cc b/content/public/renderer/content_renderer_client.cc
index 8997832..fe80e4d 100644
--- a/content/public/renderer/content_renderer_client.cc
+++ b/content/public/renderer/content_renderer_client.cc
@@ -75,6 +75,11 @@
   return NULL;
 }
 
+WebKit::WebSpeechSynthesizer* ContentRendererClient::OverrideSpeechSynthesizer(
+    WebKit::WebSpeechSynthesizerClient* client) {
+  return NULL;
+}
+
 bool ContentRendererClient::RunIdleHandlerWhenWidgetsHidden() {
   return true;
 }
diff --git a/content/public/renderer/content_renderer_client.h b/content/public/renderer/content_renderer_client.h
index b12633c..8d3c737 100644
--- a/content/public/renderer/content_renderer_client.h
+++ b/content/public/renderer/content_renderer_client.h
@@ -18,11 +18,11 @@
 #include "v8/include/v8.h"
 
 class GURL;
-class MessageLoop;
 class SkBitmap;
 
 namespace base {
 class FilePath;
+class MessageLoop;
 }
 
 namespace WebKit {
@@ -37,6 +37,8 @@
 class WebPluginContainer;
 class WebRTCPeerConnectionHandler;
 class WebRTCPeerConnectionHandlerClient;
+class WebSpeechSynthesizer;
+class WebSpeechSynthesizerClient;
 class WebThemeEngine;
 class WebURLRequest;
 struct WebPluginParams;
@@ -59,6 +61,7 @@
 namespace content {
 
 class RenderView;
+class SynchronousCompositor;
 
 // Embedder API for participating in renderer logic.
 class CONTENT_EXPORT ContentRendererClient {
@@ -115,6 +118,7 @@
   // (lack of information on the error code) so the caller should take care to
   // initialize the string values with safe defaults before the call.
   virtual void GetNavigationErrorStrings(
+      WebKit::WebFrame* frame,
       const WebKit::WebURLRequest& failed_request,
       const WebKit::WebURLError& error,
       std::string* error_html,
@@ -156,6 +160,11 @@
   // the content layer will provide an engine.
   virtual WebKit::WebThemeEngine* OverrideThemeEngine();
 
+  // Allows the embedder to override the WebSpeechSynthesizer used.
+  // If it returns NULL the content layer will provide an engine.
+  virtual WebKit::WebSpeechSynthesizer* OverrideSpeechSynthesizer(
+      WebKit::WebSpeechSynthesizerClient* client);
+
   // Returns true if the renderer process should schedule the idle handler when
   // all widgets are hidden.
   virtual bool RunIdleHandlerWhenWidgetsHidden();
@@ -231,7 +240,15 @@
   // Allow the embedder to specify a different renderer compositor MessageLoop.
   // If not NULL, the returned MessageLoop must be valid for the lifetime of
   // RenderThreadImpl. If NULL, then a new thread will be created.
-  virtual MessageLoop* OverrideCompositorMessageLoop() const;
+  virtual base::MessageLoop* OverrideCompositorMessageLoop() const;
+
+  // Called when a render view's compositor instance is created, when the
+  // kEnableSynchronousRendererCompositor flag is used.
+  // NOTE this is called on the Compositor thread: the embedder must
+  // implement OverrideCompositorMessageLoop() when using this interface.
+  virtual void DidCreateSynchronousCompositor(
+      int render_view_id,
+      SynchronousCompositor* compositor) {}
 
   // Allow the embedder to disable input event filtering by the compositor.
   virtual bool ShouldCreateCompositorInputHandler() const;
diff --git a/content/public/renderer/document_state.cc b/content/public/renderer/document_state.cc
index 231c9d6..854431b 100644
--- a/content/public/renderer/document_state.cc
+++ b/content/public/renderer/document_state.cc
@@ -6,28 +6,19 @@
 
 #include "content/public/common/password_form.h"
 #include "content/public/renderer/navigation_state.h"
-#include "webkit/glue/alt_error_page_resource_fetcher.h"
 
 namespace content {
 
 DocumentState::DocumentState()
     : load_histograms_recorded_(false),
       web_timing_histograms_recorded_(false),
-      http_status_code_(0),
       was_fetched_via_spdy_(false),
       was_npn_negotiated_(false),
       was_alternate_protocol_available_(false),
       was_fetched_via_proxy_(false),
-      use_error_page_(false),
-      is_overriding_user_agent_(false),
-      must_reset_scroll_and_scale_state_(false),
       was_prefetcher_(false),
       was_referred_by_prefetcher_(false),
       load_type_(UNDEFINED_LOAD),
-      cache_policy_override_set_(false),
-      cache_policy_override_(WebKit::WebURLRequest::UseProtocolCachePolicy),
-      referrer_policy_set_(false),
-      referrer_policy_(WebKit::WebReferrerPolicyDefault),
       can_load_local_resources_(false) {
 }
 
@@ -38,11 +29,6 @@
   password_form_data_.reset(data.release());
 }
 
-void DocumentState::set_alt_error_page_fetcher(
-    webkit_glue::AltErrorPageResourceFetcher* f) {
-  alt_error_page_fetcher_.reset(f);
-}
-
 void DocumentState::set_navigation_state(NavigationState* navigation_state) {
   navigation_state_.reset(navigation_state);
 }
diff --git a/content/public/renderer/document_state.h b/content/public/renderer/document_state.h
index 3168776..144eae4 100644
--- a/content/public/renderer/document_state.h
+++ b/content/public/renderer/document_state.h
@@ -9,15 +9,11 @@
 
 #include "base/logging.h"
 #include "base/memory/scoped_ptr.h"
+#include "base/supports_user_data.h"
 #include "base/time.h"
-#include "third_party/WebKit/Source/Platform/chromium/public/WebReferrerPolicy.h"
-#include "third_party/WebKit/Source/Platform/chromium/public/WebURLRequest.h"
+#include "content/common/content_export.h"
 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDataSource.h"
 
-namespace webkit_glue {
-class AltErrorPageResourceFetcher;
-}
-
 namespace content {
 
 class NavigationState;
@@ -25,7 +21,9 @@
 
 // The RenderView stores an instance of this class in the "extra data" of each
 // WebDataSource (see RenderView::DidCreateDataSource).
-class DocumentState : public WebKit::WebDataSource::ExtraData {
+class CONTENT_EXPORT DocumentState
+    : NON_EXPORTED_BASE(public WebKit::WebDataSource::ExtraData),
+      public base::SupportsUserData {
  public:
   // The exact values of this enum are used in histograms, so new values must be
   // added to the end.
@@ -129,11 +127,6 @@
     web_timing_histograms_recorded_ = value;
   }
 
-  int http_status_code() const { return http_status_code_; }
-  void set_http_status_code(int http_status_code) {
-    http_status_code_ = http_status_code;
-  }
-
   // Indicator if SPDY was used as part of this page load.
   bool was_fetched_via_spdy() const { return was_fetched_via_spdy_; }
   void set_was_fetched_via_spdy(bool value) { was_fetched_via_spdy_ = value; }
@@ -160,47 +153,20 @@
     was_fetched_via_proxy_ = value;
   }
 
-  const GURL& searchable_form_url() const { return searchable_form_url_; }
-  void set_searchable_form_url(const GURL& url) { searchable_form_url_ = url; }
-  const std::string& searchable_form_encoding() const {
-    return searchable_form_encoding_;
-  }
-  void set_searchable_form_encoding(const std::string& encoding) {
-    searchable_form_encoding_ = encoding;
-  }
-
+  // If set, contains the PasswordForm that we believe triggered the current
+  // navigation (there is some ambiguity in the case of javascript initiated
+  // navigations). This information is used by the PasswordManager to determine
+  // if the user should be prompted to save their password.
+  //
+  // Note that setting this field doesn't affect where the data is sent or what
+  // origin we associate it with, only whether we prompt the user to save it.
+  // That is, a false positive is a usability issue (e.g. may try to save a
+  // mis-typed password) not a security issue.
   PasswordForm* password_form_data() const {
     return password_form_data_.get();
   }
   void set_password_form_data(scoped_ptr<PasswordForm> data);
 
-  const std::string& security_info() const { return security_info_; }
-  void set_security_info(const std::string& security_info) {
-    security_info_ = security_info;
-  }
-
-  // True if an error page should be used, if the http status code also
-  // indicates an error.
-  bool use_error_page() const { return use_error_page_; }
-  void set_use_error_page(bool use_error_page) {
-    use_error_page_ = use_error_page;
-  }
-
-  // True if the user agent was overridden for this page.
-  bool is_overriding_user_agent() const { return is_overriding_user_agent_; }
-  void set_is_overriding_user_agent(bool state) {
-    is_overriding_user_agent_ = state;
-  }
-
-  // True if we have to reset the scroll and scale state of the page
-  // after the provisional load has been committed.
-  bool must_reset_scroll_and_scale_state() const {
-    return must_reset_scroll_and_scale_state_;
-  }
-  void set_must_reset_scroll_and_scale_state(bool state) {
-    must_reset_scroll_and_scale_state_ = state;
-  }
-
   void set_was_prefetcher(bool value) { was_prefetcher_ = value; }
   bool was_prefetcher() const { return was_prefetcher_; }
 
@@ -215,46 +181,6 @@
   LoadType load_type() const { return load_type_; }
   void set_load_type(LoadType load_type) { load_type_ = load_type; }
 
-  // Sets the cache policy. The cache policy is only used if explicitly set and
-  // by default is not set. You can mark a NavigationState as not having a cache
-  // state by way of clear_cache_policy_override.
-  void set_cache_policy_override(
-      WebKit::WebURLRequest::CachePolicy cache_policy) {
-    cache_policy_override_ = cache_policy;
-    cache_policy_override_set_ = true;
-  }
-  WebKit::WebURLRequest::CachePolicy cache_policy_override() const {
-    return cache_policy_override_;
-  }
-  void clear_cache_policy_override() {
-    cache_policy_override_set_ = false;
-    cache_policy_override_ = WebKit::WebURLRequest::UseProtocolCachePolicy;
-  }
-  bool is_cache_policy_override_set() const {
-    return cache_policy_override_set_;
-  }
-
-  // Sets the referrer policy to use. This is only used for browser initiated
-  // navigations, otherwise, the referrer policy is defined by the frame's
-  // document.
-  WebKit::WebReferrerPolicy referrer_policy() const {
-    return referrer_policy_;
-  }
-  void set_referrer_policy(WebKit::WebReferrerPolicy referrer_policy) {
-    referrer_policy_ = referrer_policy;
-    referrer_policy_set_ = true;
-  }
-  void clear_referrer_policy() {
-    referrer_policy_ = WebKit::WebReferrerPolicyDefault;
-    referrer_policy_set_ = false;
-  }
-  bool is_referrer_policy_set() const { return referrer_policy_set_; }
-
-  webkit_glue::AltErrorPageResourceFetcher* alt_error_page_fetcher() const {
-    return alt_error_page_fetcher_.get();
-  }
-  void set_alt_error_page_fetcher(webkit_glue::AltErrorPageResourceFetcher* f);
-
   NavigationState* navigation_state() { return navigation_state_.get(); }
   void set_navigation_state(NavigationState* navigation_state);
 
@@ -273,22 +199,13 @@
   base::Time first_paint_after_load_time_;
   bool load_histograms_recorded_;
   bool web_timing_histograms_recorded_;
-  int http_status_code_;
   bool was_fetched_via_spdy_;
   bool was_npn_negotiated_;
   std::string npn_negotiated_protocol_;
   bool was_alternate_protocol_available_;
   bool was_fetched_via_proxy_;
 
-  GURL searchable_form_url_;
-  std::string searchable_form_encoding_;
   scoped_ptr<PasswordForm> password_form_data_;
-  std::string security_info_;
-
-  bool use_error_page_;
-
-  bool is_overriding_user_agent_;
-  bool must_reset_scroll_and_scale_state_;
 
   // A prefetcher is a page that contains link rel=prefetch elements.
   bool was_prefetcher_;
@@ -296,14 +213,6 @@
 
   LoadType load_type_;
 
-  bool cache_policy_override_set_;
-  WebKit::WebURLRequest::CachePolicy cache_policy_override_;
-
-  bool referrer_policy_set_;
-  WebKit::WebReferrerPolicy referrer_policy_;
-
-  scoped_ptr<webkit_glue::AltErrorPageResourceFetcher> alt_error_page_fetcher_;
-
   scoped_ptr<NavigationState> navigation_state_;
 
   bool can_load_local_resources_;
diff --git a/content/public/renderer/navigation_state.cc b/content/public/renderer/navigation_state.cc
index 9208efa..5745a2b 100644
--- a/content/public/renderer/navigation_state.cc
+++ b/content/public/renderer/navigation_state.cc
@@ -9,12 +9,14 @@
 NavigationState::NavigationState(content::PageTransition transition_type,
                                  bool is_content_initiated,
                                  int32 pending_page_id,
-                                 int pending_history_list_offset)
+                                 int pending_history_list_offset,
+                                 bool history_list_was_cleared)
     : transition_type_(transition_type),
       request_committed_(false),
       is_content_initiated_(is_content_initiated),
       pending_page_id_(pending_page_id),
       pending_history_list_offset_(pending_history_list_offset),
+      history_list_was_cleared_(history_list_was_cleared),
       was_within_same_page_(false),
       transferred_request_child_id_(-1),
       transferred_request_request_id_(-1),
diff --git a/content/public/renderer/navigation_state.h b/content/public/renderer/navigation_state.h
index 746b206..01f92a0 100644
--- a/content/public/renderer/navigation_state.h
+++ b/content/public/renderer/navigation_state.h
@@ -7,6 +7,7 @@
 
 #include <string>
 
+#include "content/common/content_export.h"
 #include "content/public/common/page_transition_types.h"
 
 namespace content {
@@ -14,20 +15,25 @@
 // NavigationState is the portion of DocumentState that is affected by
 // in-document navigation.
 // TODO(simonjam): Move this to HistoryItem's ExtraData.
-class NavigationState {
+class CONTENT_EXPORT NavigationState {
  public:
   virtual ~NavigationState();
 
   static NavigationState* CreateBrowserInitiated(
       int32 pending_page_id,
       int pending_history_list_offset,
+      bool history_list_was_cleared,
       content::PageTransition transition_type) {
-    return new NavigationState(transition_type, false, pending_page_id,
-                               pending_history_list_offset);
+    return new NavigationState(transition_type,
+                               false,
+                               pending_page_id,
+                               pending_history_list_offset,
+                               history_list_was_cleared);
   }
 
   static NavigationState* CreateContentInitiated() {
-    return new NavigationState(content::PAGE_TRANSITION_LINK, true, -1, -1);
+    return new NavigationState(
+        content::PAGE_TRANSITION_LINK, true, -1, -1, false);
   }
 
   // Contains the page_id for this navigation or -1 if there is none yet.
@@ -39,6 +45,12 @@
     return pending_history_list_offset_;
   }
 
+  // If pending_page_id() is not -1, then this returns true if the session
+  // history was cleared during this navigation.
+  bool history_list_was_cleared() const {
+    return history_list_was_cleared_;
+  }
+
   // Contains the transition type that the browser specified when it
   // initiated the load.
   content::PageTransition transition_type() const { return transition_type_; }
@@ -90,13 +102,15 @@
   NavigationState(content::PageTransition transition_type,
                   bool is_content_initiated,
                   int32 pending_page_id,
-                  int pending_history_list_offset);
+                  int pending_history_list_offset,
+                  bool history_list_was_cleared);
 
   content::PageTransition transition_type_;
   bool request_committed_;
   bool is_content_initiated_;
   int32 pending_page_id_;
   int pending_history_list_offset_;
+  bool history_list_was_cleared_;
 
   bool was_within_same_page_;
   int transferred_request_child_id_;
diff --git a/content/public/renderer/render_thread.h b/content/public/renderer/render_thread.h
index a041657..7dcefd4 100644
--- a/content/public/renderer/render_thread.h
+++ b/content/public/renderer/render_thread.h
@@ -16,9 +16,9 @@
 #endif
 
 class GURL;
-class MessageLoop;
 
 namespace base {
+class MessageLoop;
 class MessageLoopProxy;
 }
 
@@ -45,7 +45,7 @@
   RenderThread();
   virtual ~RenderThread();
 
-  virtual MessageLoop* GetMessageLoop() = 0;
+  virtual base::MessageLoop* GetMessageLoop() = 0;
   virtual IPC::SyncChannel* GetChannel() = 0;
   virtual std::string GetLocale() = 0;
   virtual IPC::SyncMessageFilter* GetSyncMessageFilter() = 0;
diff --git a/content/public/renderer/render_view.h b/content/public/renderer/render_view.h
index 44dc636..8024f49 100644
--- a/content/public/renderer/render_view.h
+++ b/content/public/renderer/render_view.h
@@ -15,10 +15,7 @@
 #include "ui/gfx/native_widget_types.h"
 
 class SkPicture;
-
-namespace webkit_glue {
 struct WebPreferences;
-}
 
 namespace WebKit {
 class WebFrame;
@@ -73,12 +70,11 @@
   virtual gfx::Size GetSize() const = 0;
 
   // Gets WebKit related preferences associated with this view.
-  virtual webkit_glue::WebPreferences& GetWebkitPreferences() = 0;
+  virtual WebPreferences& GetWebkitPreferences() = 0;
 
   // Overrides the WebKit related preferences associated with this view. Note
   // that the browser process may update the preferences at any time.
-  virtual void SetWebkitPreferences(
-      const webkit_glue::WebPreferences& preferences) = 0;
+  virtual void SetWebkitPreferences(const WebPreferences& preferences) = 0;
 
   // Returns the associated WebView. May return NULL when the view is closing.
   virtual WebKit::WebView* GetWebView() = 0;
diff --git a/content/public/renderer/renderer_ppapi_host.h b/content/public/renderer/renderer_ppapi_host.h
index 51a5e1f..e5eaa4b 100644
--- a/content/public/renderer/renderer_ppapi_host.h
+++ b/content/public/renderer/renderer_ppapi_host.h
@@ -32,12 +32,6 @@
 }
 }
 
-namespace webkit {
-namespace ppapi {
-class PluginInstance;
-}
-}
-
 namespace WebKit {
 class WebPluginContainer;
 }
diff --git a/content/public/test/android/javatests/src/org/chromium/content/browser/test/util/DOMUtils.java b/content/public/test/android/javatests/src/org/chromium/content/browser/test/util/DOMUtils.java
index 2888c51..db61486 100644
--- a/content/public/test/android/javatests/src/org/chromium/content/browser/test/util/DOMUtils.java
+++ b/content/public/test/android/javatests/src/org/chromium/content/browser/test/util/DOMUtils.java
@@ -156,8 +156,10 @@
         Rect bounds = getNodeBounds(view, viewClient, nodeName);
         Assert.assertNotNull("Failed to get DOM element bounds of '" + nodeName + "'.", bounds);
 
-        int clickX = (int) view.getRenderCoordinates().fromLocalCssToPix(bounds.exactCenterX());
-        int clickY = (int) view.getRenderCoordinates().fromLocalCssToPix(bounds.exactCenterY());
+        int clickX = (int) view.getRenderCoordinates().fromLocalCssToPix(bounds.exactCenterX())
+                + (int) view.getContentViewCore().getViewportSizeOffsetWidthPix();
+        int clickY = (int) view.getRenderCoordinates().fromLocalCssToPix(bounds.exactCenterY())
+                + (int) view.getContentViewCore().getViewportSizeOffsetHeightPix();
         return new int[] { clickX, clickY };
     }
 }
diff --git a/content/public/test/android/javatests/src/org/chromium/content/browser/test/util/TouchCommon.java b/content/public/test/android/javatests/src/org/chromium/content/browser/test/util/TouchCommon.java
index 70b046d..9e962d1 100644
--- a/content/public/test/android/javatests/src/org/chromium/content/browser/test/util/TouchCommon.java
+++ b/content/public/test/android/javatests/src/org/chromium/content/browser/test/util/TouchCommon.java
@@ -118,6 +118,13 @@
     }
 
     /**
+     * Sends (synchronously) a single click to the center of the View.
+     */
+    public void singleClickView(View v) {
+        singleClickView(v, v.getWidth() / 2, v.getHeight() / 2);
+    }
+
+    /**
      * Sends (synchronously) a single click on the specified relative coordinates inside
      * a given view.
      *
diff --git a/content/public/test/browser_test_base.cc b/content/public/test/browser_test_base.cc
index 04d6ff0..e89c28c 100644
--- a/content/public/test/browser_test_base.cc
+++ b/content/public/test/browser_test_base.cc
@@ -8,12 +8,15 @@
 #include "base/command_line.h"
 #include "base/debug/stack_trace.h"
 #include "base/process_util.h"
+#include "content/browser/renderer_host/render_process_host_impl.h"
+#include "content/public/browser/browser_thread.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/common/main_function_params.h"
+#include "content/public/test/test_utils.h"
 
 #if defined(OS_MACOSX)
 #include "base/mac/mac_util.h"
-#include "base/system_monitor/system_monitor.h"
+#include "base/power_monitor/power_monitor.h"
 #endif
 
 #if defined(OS_ANDROID)
@@ -22,6 +25,7 @@
 #include "content/public/browser/browser_thread.h"
 #endif
 
+namespace content {
 namespace {
 
 #if defined(OS_POSIX)
@@ -43,16 +47,20 @@
 }
 #endif  // defined(OS_POSIX)
 
+void RunTaskOnRendererThread(const base::Closure& task,
+                             const base::Closure& quit_task) {
+  task.Run();
+  BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, quit_task);
+}
+
 }  // namespace
 
-namespace content {
-
-extern int BrowserMain(const content::MainFunctionParams&);
+extern int BrowserMain(const MainFunctionParams&);
 
 BrowserTestBase::BrowserTestBase() {
 #if defined(OS_MACOSX)
   base::mac::SetOverrideAmIBundled(true);
-  base::SystemMonitor::AllocateSystemIOPorts();
+  base::PowerMonitor::AllocateSystemIOPorts();
 #endif
 
 #if defined(OS_POSIX)
@@ -114,10 +122,26 @@
 
 void BrowserTestBase::CreateTestServer(const base::FilePath& test_server_base) {
   CHECK(!test_server_.get());
-  test_server_.reset(new net::TestServer(
-      net::TestServer::TYPE_HTTP,
-      net::TestServer::kLocalhost,
+  test_server_.reset(new net::SpawnedTestServer(
+      net::SpawnedTestServer::TYPE_HTTP,
+      net::SpawnedTestServer::kLocalhost,
       test_server_base));
 }
 
+void BrowserTestBase::PostTaskToInProcessRendererAndWait(
+    const base::Closure& task) {
+  CHECK(CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess));
+
+  scoped_refptr<MessageLoopRunner> runner = new MessageLoopRunner;
+
+  base::MessageLoop* renderer_loop =
+      RenderProcessHostImpl::GetInProcessRendererThreadForTesting();
+  CHECK(renderer_loop);
+
+  renderer_loop->PostTask(
+      FROM_HERE,
+      base::Bind(&RunTaskOnRendererThread, task, runner->QuitClosure()));
+  runner->Run();
+}
+
 }  // namespace content
diff --git a/content/public/test/browser_test_base.h b/content/public/test/browser_test_base.h
index 026bf32..8ddcba0 100644
--- a/content/public/test/browser_test_base.h
+++ b/content/public/test/browser_test_base.h
@@ -5,9 +5,10 @@
 #ifndef CONTENT_PUBLIC_TEST_BROWSER_TEST_BASE_H_
 #define CONTENT_PUBLIC_TEST_BROWSER_TEST_BASE_H_
 
+#include "base/callback.h"
 #include "base/compiler_specific.h"
+#include "net/test/spawned_test_server.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "net/test/test_server.h"
 
 class CommandLine;
 
@@ -63,8 +64,10 @@
   virtual void RunTestOnMainThreadLoop() = 0;
 
   // Returns the testing server. Guaranteed to be non-NULL.
-  const net::TestServer* test_server() const { return test_server_.get(); }
-  net::TestServer* test_server() { return test_server_.get(); }
+  const net::SpawnedTestServer* test_server() const {
+    return test_server_.get();
+  }
+  net::SpawnedTestServer* test_server() { return test_server_.get(); }
 
 #if defined(OS_POSIX)
   // This is only needed by a test that raises SIGTERM to ensure that a specific
@@ -82,11 +85,16 @@
   // server.
   void CreateTestServer(const base::FilePath& test_server_base);
 
+  // When the test is running in --single-process mode, runs the given task on
+  // the in-process renderer thread. A nested message loop is run until it
+  // returns.
+  void PostTaskToInProcessRendererAndWait(const base::Closure& task);
+
  private:
   void ProxyRunTestOnMainThreadLoop();
 
   // Testing server, started on demand.
-  scoped_ptr<net::TestServer> test_server_;
+  scoped_ptr<net::SpawnedTestServer> test_server_;
 
 #if defined(OS_POSIX)
   bool handle_sigterm_;
diff --git a/content/public/test/content_test_suite_base.cc b/content/public/test/content_test_suite_base.cc
index ea83b47..459c37d 100644
--- a/content/public/test/content_test_suite_base.cc
+++ b/content/public/test/content_test_suite_base.cc
@@ -22,8 +22,10 @@
 #include "base/android/jni_android.h"
 #include "content/browser/android/browser_jni_registrar.h"
 #include "content/common/android/common_jni_registrar.h"
+#include "media/base/android/media_jni_registrar.h"
 #include "net/android/net_jni_registrar.h"
 #include "ui/android/ui_jni_registrar.h"
+#include "ui/gl/android/gl_jni_registrar.h"
 #include "ui/shell_dialogs/android/shell_dialogs_jni_registrar.h"
 #endif
 
@@ -53,6 +55,7 @@
   JNIEnv* env = base::android::AttachCurrentThread();
   content::android::RegisterCommonJni(env);
   content::android::RegisterBrowserJni(env);
+  media::RegisterJni(env);
   net::android::RegisterJni(env);
   ui::android::RegisterJni(env);
   ui::shell_dialogs::RegisterJni(env);
diff --git a/content/public/test/download_test_observer.cc b/content/public/test/download_test_observer.cc
index 6a0504e..3d91825 100644
--- a/content/public/test/download_test_observer.cc
+++ b/content/public/test/download_test_observer.cc
@@ -78,7 +78,7 @@
   if (filter_.Run(item_))
     event_seen_ = true;
   if (waiting_ && event_seen_)
-    MessageLoopForUI::current()->Quit();
+    base::MessageLoopForUI::current()->Quit();
 }
 
 void DownloadUpdatedObserver::OnDownloadDestroyed(DownloadItem* item) {
@@ -86,7 +86,7 @@
   item_->RemoveObserver(this);
   item_ = NULL;
   if (waiting_)
-    MessageLoopForUI::current()->Quit();
+    base::MessageLoopForUI::current()->Quit();
 }
 
 DownloadTestObserver::DownloadTestObserver(
@@ -231,7 +231,7 @@
 
 void DownloadTestObserver::SignalIfFinished() {
   if (waiting_ && IsFinished())
-    MessageLoopForUI::current()->Quit();
+    base::MessageLoopForUI::current()->Quit();
 }
 
 DownloadTestObserverTerminal::DownloadTestObserverTerminal(
@@ -379,7 +379,7 @@
         base::Bind(&DownloadTestFlushObserver::PingFileThread, this, cycle));
   } else {
     BrowserThread::PostTask(
-        BrowserThread::UI, FROM_HERE, MessageLoop::QuitClosure());
+        BrowserThread::UI, FROM_HERE, base::MessageLoop::QuitClosure());
   }
 }
 
@@ -415,7 +415,7 @@
   DCHECK_EQ(1u, called_back_count_);
 
   if (waiting_)
-    MessageLoopForUI::current()->Quit();
+    base::MessageLoopForUI::current()->Quit();
 }
 
 const DownloadUrlParameters::OnStartedCallback
diff --git a/content/public/test/fake_speech_recognition_manager.cc b/content/public/test/fake_speech_recognition_manager.cc
index 3bc2946..8f89255 100644
--- a/content/public/test/fake_speech_recognition_manager.cc
+++ b/content/public/test/fake_speech_recognition_manager.cc
@@ -54,14 +54,16 @@
 
   if (should_send_fake_response_) {
     // Give the fake result in a short while.
-    MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
-        &FakeSpeechRecognitionManager::SetFakeRecognitionResult,
-        // This class does not need to be refcounted (typically done by
-        // PostTask) since it will outlive the test and gets released only
-        // when the test shuts down. Disabling refcounting here saves a bit
-        // of unnecessary code and the factory method can return a plain
-        // pointer below as required by the real code.
-        base::Unretained(this)));
+    base::MessageLoop::current()->PostTask(
+        FROM_HERE,
+        base::Bind(
+            &FakeSpeechRecognitionManager::SetFakeRecognitionResult,
+            // This class does not need to be refcounted (typically done by
+            // PostTask) since it will outlive the test and gets released only
+            // when the test shuts down. Disabling refcounting here saves a bit
+            // of unnecessary code and the factory method can return a plain
+            // pointer below as required by the real code.
+            base::Unretained(this)));
   }
   recognition_started_event_.Signal();
 }
diff --git a/content/public/test/layouttest_support.h b/content/public/test/layouttest_support.h
index 7c370bc..e35196e 100644
--- a/content/public/test/layouttest_support.h
+++ b/content/public/test/layouttest_support.h
@@ -66,6 +66,9 @@
 // Set the device scale factor and force the compositor to resize.
 void SetDeviceScaleFactor(RenderView* render_view, float factor);
 
+// Disable system calls related to drag & drop.
+void DisableSystemDragDrop();
+
 }  // namespace content
 
 #endif  // CONTENT_PUBLIC_TEST_LAYOUTTEST_SUPPORT_H_
diff --git a/content/public/test/mock_render_process_host.cc b/content/public/test/mock_render_process_host.cc
index d877d44..235afa5 100644
--- a/content/public/test/mock_render_process_host.cc
+++ b/content/public/test/mock_render_process_host.cc
@@ -168,7 +168,7 @@
         NOTIFICATION_RENDERER_PROCESS_TERMINATED,
         Source<RenderProcessHost>(this),
         NotificationService::NoDetails());
-    MessageLoop::current()->DeleteSoon(FROM_HERE, this);
+    base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
     RenderProcessHostImpl::UnregisterHost(GetID());
   }
 }
diff --git a/content/public/test/mock_render_thread.cc b/content/public/test/mock_render_thread.cc
index a5d8e13..c680760 100644
--- a/content/public/test/mock_render_thread.cc
+++ b/content/public/test/mock_render_thread.cc
@@ -39,7 +39,7 @@
   // through this function messages, messages with reply and reply messages.
   // We can only handle one synchronous message at a time.
   if (msg->is_reply()) {
-    if (reply_deserializer_.get()) {
+    if (reply_deserializer_) {
       reply_deserializer_->SerializeOutputParameters(*msg);
       reply_deserializer_.reset();
     }
diff --git a/content/public/test/mock_render_thread.h b/content/public/test/mock_render_thread.h
index c8f1419..d90275c 100644
--- a/content/public/test/mock_render_thread.h
+++ b/content/public/test/mock_render_thread.h
@@ -38,7 +38,7 @@
 
   // RenderThread implementation:
   virtual bool Send(IPC::Message* msg) OVERRIDE;
-  virtual MessageLoop* GetMessageLoop() OVERRIDE;
+  virtual base::MessageLoop* GetMessageLoop() OVERRIDE;
   virtual IPC::SyncChannel* GetChannel() OVERRIDE;
   virtual std::string GetLocale() OVERRIDE;
   virtual IPC::SyncMessageFilter* GetSyncMessageFilter() OVERRIDE;
diff --git a/content/public/test/render_view_fake_resources_test.cc b/content/public/test/render_view_fake_resources_test.cc
index 4bb0204..eda8ef9 100644
--- a/content/public/test/render_view_fake_resources_test.cc
+++ b/content/public/test/render_view_fake_resources_test.cc
@@ -60,7 +60,7 @@
   // but we use a real RenderThread so that we can use the ResourceDispatcher
   // to fetch network resources.  These are then served canned content
   // in OnRequestResource().
-  GetContentClient()->set_renderer_for_testing(&content_renderer_client_);
+  SetRendererClientForTesting(&content_renderer_client_);
   // Generate a unique channel id so that multiple instances of the test can
   // run in parallel.
   std::string channel_id = IPC::Channel::GenerateVerifiedChannelID(
diff --git a/content/public/test/render_view_fake_resources_test.h b/content/public/test/render_view_fake_resources_test.h
index cde8596..a9688d9 100644
--- a/content/public/test/render_view_fake_resources_test.h
+++ b/content/public/test/render_view_fake_resources_test.h
@@ -127,7 +127,7 @@
 
   static const int32 kViewId;  // arbitrary id for our testing view
 
-  MessageLoopForIO message_loop_;
+  base::MessageLoopForIO message_loop_;
   ContentRendererClient content_renderer_client_;
   // channel that the renderer uses to talk to the browser.
   // For this test, we will handle the browser end of the channel.
diff --git a/content/public/test/render_view_test.cc b/content/public/test/render_view_test.cc
index dec696e..da2513e 100644
--- a/content/public/test/render_view_test.cc
+++ b/content/public/test/render_view_test.cc
@@ -5,6 +5,7 @@
 #include "content/public/test/render_view_test.h"
 
 #include "base/run_loop.h"
+#include "content/common/input_messages.h"
 #include "content/common/view_messages.h"
 #include "content/public/browser/native_web_keyboard_event.h"
 #include "content/public/common/renderer_preferences.h"
@@ -76,7 +77,7 @@
 }
 
 void RenderViewTest::ProcessPendingMessages() {
-  msg_loop_.PostTask(FROM_HERE, MessageLoop::QuitClosure());
+  msg_loop_.PostTask(FROM_HERE, base::MessageLoop::QuitClosure());
   msg_loop_.Run();
 }
 
@@ -126,12 +127,14 @@
 void RenderViewTest::SetUp() {
   // Subclasses can set the ContentClient's renderer before calling
   // RenderViewTest::SetUp().
-  if (!GetContentClient()->renderer())
-    GetContentClient()->set_renderer_for_testing(&content_renderer_client_);
+  ContentRendererClient* old_client =
+      SetRendererClientForTesting(&content_renderer_client_);
+  if (old_client)
+    SetRendererClientForTesting(old_client);
 
   // Subclasses can set render_thread_ with their own implementation before
   // calling RenderViewTest::SetUp().
-  if (!render_thread_.get())
+  if (!render_thread_)
     render_thread_.reset(new MockRenderThread());
   render_thread_->set_routing_id(kRouteId);
   render_thread_->set_surface_id(kSurfaceId);
@@ -164,7 +167,7 @@
   RenderViewImpl* view = RenderViewImpl::Create(
       kOpenerId,
       RendererPreferences(),
-      webkit_glue::WebPreferences(),
+      WebPreferences(),
       new SharedRenderViewCounter(0),
       kRouteId,
       kSurfaceId,
@@ -213,13 +216,14 @@
 void RenderViewTest::SendWebKeyboardEvent(
     const WebKit::WebKeyboardEvent& key_event) {
   RenderViewImpl* impl = static_cast<RenderViewImpl*>(view_);
-  impl->OnMessageReceived(ViewMsg_HandleInputEvent(0, &key_event, false));
+  impl->OnMessageReceived(InputMsg_HandleInputEvent(0, &key_event, false));
 }
 
 void RenderViewTest::SendWebMouseEvent(
     const WebKit::WebMouseEvent& mouse_event) {
   RenderViewImpl* impl = static_cast<RenderViewImpl*>(view_);
-  impl->OnMessageReceived(ViewMsg_HandleInputEvent(0, &mouse_event, false));
+  impl->OnMessageReceived(
+      InputMsg_HandleInputEvent(0, &mouse_event, false));
 }
 
 const char* const kGetCoordinatesScript =
@@ -278,7 +282,7 @@
   mouse_event.y = bounds.CenterPoint().y();
   mouse_event.clickCount = 1;
   scoped_ptr<IPC::Message> input_message(
-      new ViewMsg_HandleInputEvent(0, &mouse_event, false));
+      new InputMsg_HandleInputEvent(0, &mouse_event, false));
   RenderViewImpl* impl = static_cast<RenderViewImpl*>(view_);
   impl->OnMessageReceived(*input_message);
   return true;
diff --git a/content/public/test/render_view_test.h b/content/public/test/render_view_test.h
index 3b1e160..a30adac 100644
--- a/content/public/test/render_view_test.h
+++ b/content/public/test/render_view_test.h
@@ -124,7 +124,7 @@
 
   virtual void TearDown() OVERRIDE;
 
-  MessageLoop msg_loop_;
+  base::MessageLoop msg_loop_;
   scoped_ptr<MockRenderProcess> mock_process_;
   // We use a naked pointer because we don't want to expose RenderViewImpl in
   // the embedder's namespace.
diff --git a/content/public/test/test_browser_context.cc b/content/public/test/test_browser_context.cc
index b3aa752..c410d42 100644
--- a/content/public/test/test_browser_context.cc
+++ b/content/public/test/test_browser_context.cc
@@ -70,7 +70,7 @@
 }
 
 net::URLRequestContextGetter* TestBrowserContext::GetRequestContext() {
-  if (!request_context_.get()) {
+  if (!request_context_) {
     request_context_ = new TestContextURLRequestContextGetter(
         GetResourceContext()->GetRequestContext());
   }
@@ -100,7 +100,7 @@
 }
 
 ResourceContext* TestBrowserContext::GetResourceContext() {
-  if (!resource_context_.get())
+  if (!resource_context_)
     resource_context_.reset(new MockResourceContext());
   return resource_context_.get();
 }
diff --git a/content/public/test/test_browser_thread.cc b/content/public/test/test_browser_thread.cc
index 6920ce0..f024a21 100644
--- a/content/public/test/test_browser_thread.cc
+++ b/content/public/test/test_browser_thread.cc
@@ -19,10 +19,9 @@
   }
 
   TestBrowserThreadImpl(BrowserThread::ID identifier,
-                        MessageLoop* message_loop)
+                        base::MessageLoop* message_loop)
       : BrowserThreadImpl(identifier, message_loop),
-        notification_service_(NULL) {
-  }
+        notification_service_(NULL) {}
 
   virtual ~TestBrowserThreadImpl() {
     Stop();
@@ -50,9 +49,8 @@
 }
 
 TestBrowserThread::TestBrowserThread(BrowserThread::ID identifier,
-                                     MessageLoop* message_loop)
-    : impl_(new TestBrowserThreadImpl(identifier, message_loop)) {
-}
+                                     base::MessageLoop* message_loop)
+    : impl_(new TestBrowserThreadImpl(identifier, message_loop)) {}
 
 TestBrowserThread::~TestBrowserThread() {
   Stop();
@@ -64,7 +62,7 @@
 
 bool TestBrowserThread::StartIOThread() {
   base::Thread::Options options;
-  options.message_loop_type = MessageLoop::TYPE_IO;
+  options.message_loop_type = base::MessageLoop::TYPE_IO;
   return impl_->StartWithOptions(options);
 }
 
diff --git a/content/public/test/test_browser_thread.h b/content/public/test/test_browser_thread.h
index 24182e1..c4c386b 100644
--- a/content/public/test/test_browser_thread.h
+++ b/content/public/test/test_browser_thread.h
@@ -9,9 +9,8 @@
 #include "base/memory/scoped_ptr.h"
 #include "content/public/browser/browser_thread.h"
 
-class MessageLoop;
-
 namespace base {
+class MessageLoop;
 class Thread;
 }
 
@@ -24,7 +23,8 @@
 class TestBrowserThread {
  public:
   explicit TestBrowserThread(BrowserThread::ID identifier);
-  TestBrowserThread(BrowserThread::ID identifier, MessageLoop* message_loop);
+  TestBrowserThread(BrowserThread::ID identifier,
+                    base::MessageLoop* message_loop);
   ~TestBrowserThread();
 
   // We provide a subset of the capabilities of the Thread interface
diff --git a/content/public/test/test_content_client_initializer.cc b/content/public/test/test_content_client_initializer.cc
index b2ecdfe..0c210d2 100644
--- a/content/public/test/test_content_client_initializer.cc
+++ b/content/public/test/test_content_client_initializer.cc
@@ -16,12 +16,11 @@
 TestContentClientInitializer::TestContentClientInitializer() {
   notification_service_.reset(new NotificationServiceImpl());
 
-  DCHECK(!GetContentClient());
   content_client_.reset(new TestContentClient);
   SetContentClient(content_client_.get());
 
   content_browser_client_.reset(new TestContentBrowserClient());
-  content_client_->set_browser_for_testing(content_browser_client_.get());
+  content::SetBrowserClientForTesting(content_browser_client_.get());
 }
 
 TestContentClientInitializer::~TestContentClientInitializer() {
@@ -29,7 +28,6 @@
   rph_factory_.reset();
   notification_service_.reset();
 
-  DCHECK_EQ(content_client_.get(), GetContentClient());
   SetContentClient(NULL);
   content_client_.reset();
 
diff --git a/content/public/test/test_launcher.cc b/content/public/test/test_launcher.cc
index 40545d5..1d80605 100644
--- a/content/public/test/test_launcher.cc
+++ b/content/public/test/test_launcher.cc
@@ -175,7 +175,7 @@
     // If the given path ends with '/', consider it is a directory.
     // Note: This does NOT check that a directory (or file) actually exists
     // (the behavior is same as what gtest does).
-    if (file_util::EndsWithSeparator(path)) {
+    if (path.EndsWithSeparator()) {
       base::FilePath executable = command_line.GetProgram().BaseName();
       path = path.Append(executable.ReplaceExtension(
           base::FilePath::StringType(FILE_PATH_LITERAL("xml"))));
@@ -454,7 +454,7 @@
   // Split --gtest_filter at '-', if there is one, to separate into
   // positive filter and negative filter portions.
   std::string positive_filter = filter;
-  std::string negative_filter = "";
+  std::string negative_filter;
   size_t dash_pos = filter.find('-');
   if (dash_pos != std::string::npos) {
     positive_filter = filter.substr(0, dash_pos);  // Everything up to the dash.
diff --git a/content/public/test/test_renderer_host.cc b/content/public/test/test_renderer_host.cc
index 6da75ed..9a1cc85 100644
--- a/content/public/test/test_renderer_host.cc
+++ b/content/public/test/test_renderer_host.cc
@@ -125,7 +125,7 @@
 #endif
 
   // See comment above browser_context_ decl for why we check for NULL here.
-  if (!browser_context_.get())
+  if (!browser_context_)
     browser_context_.reset(new TestBrowserContext());
 
   // This will be deleted when the WebContentsImpl goes away.
@@ -146,6 +146,14 @@
       rvh())->SendNavigate(entry->GetPageID(), entry->GetURL());
 }
 
+void RenderViewHostTestHarness::FailedReload() {
+  NavigationEntry* entry = controller().GetLastCommittedEntry();
+  DCHECK(entry);
+  controller().Reload(false);
+  static_cast<TestRenderViewHost*>(
+      rvh())->SendFailedNavigate(entry->GetPageID(), entry->GetURL());
+}
+
 void RenderViewHostTestHarness::SetUp() {
 #if defined(OS_WIN)
   ole_initializer_.reset(new ui::ScopedOleInitializer());
@@ -167,7 +175,7 @@
   base::RunLoop().RunUntilIdle();
 
   // Delete any RenderProcessHosts before the BrowserContext goes away.
-  if (rvh_test_enabler_.rph_factory_.get())
+  if (rvh_test_enabler_.rph_factory_)
     rvh_test_enabler_.rph_factory_.reset();
 
   // Release the browser context on the UI thread.
diff --git a/content/public/test/test_renderer_host.h b/content/public/test/test_renderer_host.h
index 7dba135..44b5ff8 100644
--- a/content/public/test/test_renderer_host.h
+++ b/content/public/test/test_renderer_host.h
@@ -75,6 +75,7 @@
   // setting the rest of the parameters in the message to the "typical" values.
   // This is a helper function for simulating the most common types of loads.
   virtual void SendNavigate(int page_id, const GURL& url) = 0;
+  virtual void SendFailedNavigate(int page_id, const GURL& url) = 0;
 
   // Calls OnMsgNavigate on the RenderViewHost with the given information,
   // including a custom PageTransition.  Sets the rest of the
@@ -147,6 +148,7 @@
 
   // Simulates a reload of the current page.
   void Reload();
+  void FailedReload();
 
  protected:
   // testing::Test
@@ -166,7 +168,7 @@
   // SetUp().
   scoped_ptr<BrowserContext> browser_context_;
 
-  MessageLoopForUI message_loop_;
+  base::MessageLoopForUI message_loop_;
 
  private:
   // It is important not to use this directly in the implementation as
diff --git a/content/public/test/test_utils.cc b/content/public/test/test_utils.cc
index ab0fcd6..6c318c3 100644
--- a/content/public/test/test_utils.cc
+++ b/content/public/test/test_utils.cc
@@ -34,7 +34,8 @@
   if (num_quit_deferrals <= 0) {
     quit_task.Run();
   } else {
-    MessageLoop::current()->PostTask(FROM_HERE,
+    base::MessageLoop::current()->PostTask(
+        FROM_HERE,
         base::Bind(&DeferredQuitRunLoop, quit_task, num_quit_deferrals - 1));
   }
 }
@@ -63,7 +64,7 @@
 void ScriptCallback::ResultCallback(const base::Value* result) {
   if (result)
     result_.reset(result->DeepCopy());
-  MessageLoop::current()->Quit();
+  base::MessageLoop::current()->Quit();
 }
 
 }  // namespace
@@ -74,7 +75,8 @@
 }
 
 void RunThisRunLoop(base::RunLoop* run_loop) {
-  MessageLoop::ScopedNestableTaskAllower allow(MessageLoop::current());
+  base::MessageLoop::ScopedNestableTaskAllower allow(
+      base::MessageLoop::current());
 
   // If we're running inside a browser test, we might need to allow the test
   // launcher to do extra work before/after running a nested message loop.
@@ -90,8 +92,8 @@
 }
 
 void RunAllPendingInMessageLoop() {
-  MessageLoop::current()->PostTask(FROM_HERE,
-                                   MessageLoop::QuitWhenIdleClosure());
+  base::MessageLoop::current()->PostTask(
+      FROM_HERE, base::MessageLoop::QuitWhenIdleClosure());
   RunMessageLoop();
 }
 
@@ -127,7 +129,7 @@
       string16(),  // frame_xpath,
       UTF8ToUTF16(script),
       base::Bind(&ScriptCallback::ResultCallback, base::Unretained(&observer)));
-  MessageLoop* loop = MessageLoop::current();
+  base::MessageLoop* loop = base::MessageLoop::current();
   loop->Run();
   return observer.result().Pass();
 }
diff --git a/content/public/test/web_contents_tester.h b/content/public/test/web_contents_tester.h
index d6a1f7a..8b0734a 100644
--- a/content/public/test/web_contents_tester.h
+++ b/content/public/test/web_contents_tester.h
@@ -8,10 +8,7 @@
 #include "content/public/common/page_transition_types.h"
 
 class GURL;
-
-namespace webkit_glue {
 struct WebPreferences;
-}
 
 namespace content {
 
@@ -91,7 +88,7 @@
       PageTransition transition) = 0;
 
   // Promote GetWebkitPrefs to public.
-  virtual webkit_glue::WebPreferences TestGetWebkitPrefs() = 0;
+  virtual WebPreferences TestGetWebkitPrefs() = 0;
 };
 
 }  // namespace content
diff --git a/content/renderer/DEPS b/content/renderer/DEPS
index e28b22a..f309b29 100644
--- a/content/renderer/DEPS
+++ b/content/renderer/DEPS
@@ -1,7 +1,5 @@
 include_rules = [
   "+content/public/renderer",
-  "+content/public/browser/native_web_keyboard_event.h", # For tests.
-  "+content/public/browser/web_ui_controller_factory.h", # For tests.
   "+jingle/glue",
   "+media",  # For audio input/output and audio/video decoding.
   "+third_party/hyphen/hyphen.h",
@@ -10,3 +8,10 @@
   "+third_party/tcmalloc",
   "+v8/include",
 ]
+
+specific_include_rules = {
+  '.*_[a-z]*browsertest.*': [
+    "+content/public/browser",
+    "+content/shell",
+  ],
+}
diff --git a/content/renderer/accessibility/accessibility_node_serializer.cc b/content/renderer/accessibility/accessibility_node_serializer.cc
index bb010b1..7fb5d91 100644
--- a/content/renderer/accessibility/accessibility_node_serializer.cc
+++ b/content/renderer/accessibility/accessibility_node_serializer.cc
@@ -557,6 +557,9 @@
       std::set<int> unique_cell_id_set;
       dst->int_attributes[dst->ATTR_TABLE_COLUMN_COUNT] = column_count;
       dst->int_attributes[dst->ATTR_TABLE_ROW_COUNT] = row_count;
+      WebAccessibilityObject header = src.headerContainerObject();
+      if (!header.isDetached())
+        dst->int_attributes[dst->ATTR_TABLE_HEADER_ID] = header.axID();
       for (int i = 0; i < column_count * row_count; ++i) {
         WebAccessibilityObject cell = src.cellForColumnAndRow(
             i % column_count, i / column_count);
@@ -573,6 +576,20 @@
     }
   }
 
+  if (dst->role == dst->ROLE_ROW) {
+    dst->int_attributes[dst->ATTR_TABLE_ROW_INDEX] = src.rowIndex();
+    WebAccessibilityObject header = src.rowHeader();
+    if (!header.isDetached())
+      dst->int_attributes[dst->ATTR_TABLE_ROW_HEADER_ID] = header.axID();
+  }
+
+  if (dst->role == dst->ROLE_COLUMN) {
+    dst->int_attributes[dst->ATTR_TABLE_COLUMN_INDEX] = src.columnIndex();
+    WebAccessibilityObject header = src.columnHeader();
+    if (!header.isDetached())
+      dst->int_attributes[dst->ATTR_TABLE_COLUMN_HEADER_ID] = header.axID();
+  }
+
   if (dst->role == dst->ROLE_CELL ||
       dst->role == dst->ROLE_ROW_HEADER ||
       dst->role == dst->ROLE_COLUMN_HEADER) {
diff --git a/content/renderer/accessibility/renderer_accessibility_browsertest.cc b/content/renderer/accessibility/renderer_accessibility_browsertest.cc
index 062ced8..db3daf2 100644
--- a/content/renderer/accessibility/renderer_accessibility_browsertest.cc
+++ b/content/renderer/accessibility/renderer_accessibility_browsertest.cc
@@ -331,6 +331,12 @@
   EXPECT_EQ(4, accessibility->browser_tree_node_count());
   EXPECT_EQ(4, CountAccessibilityNodesSentToBrowser());
 
+  WebDocument document = view()->GetWebView()->mainFrame()->document();
+  WebAccessibilityObject root_obj = document.accessibilityObject();
+  WebAccessibilityObject node_a = root_obj.childAt(0);
+  WebAccessibilityObject node_b = node_a.childAt(0);
+  WebAccessibilityObject node_c = node_b.childAt(0);
+
   // Hide node 'B' ('C' stays visible).
   ExecuteJavaScript(
       "document.getElementById('B').style.visibility = 'hidden';");
@@ -339,9 +345,6 @@
 
   // Send a childrenChanged on 'A'.
   sink_->ClearMessages();
-  WebDocument document = view()->GetWebView()->mainFrame()->document();
-  WebAccessibilityObject root_obj = document.accessibilityObject();
-  WebAccessibilityObject node_a = root_obj.childAt(0);
   accessibility->HandleWebAccessibilityNotification(
       node_a,
       WebKit::WebAccessibilityNotificationChildrenChanged);
@@ -350,8 +353,15 @@
   EXPECT_EQ(3, accessibility->browser_tree_node_count());
   AccessibilityHostMsg_NotificationParams notification;
   GetLastAccNotification(&notification);
-  ASSERT_EQ(2U, notification.nodes.size());
-  EXPECT_EQ(2, CountAccessibilityNodesSentToBrowser());
+  ASSERT_EQ(3U, notification.nodes.size());
+
+  // RendererAccessibilityComplete notices that 'C' is being reparented,
+  // so it updates 'B' first to remove 'C' as a child, then 'A' to add it,
+  // and finally it updates 'C'.
+  EXPECT_EQ(node_b.axID(), notification.nodes[0].id);
+  EXPECT_EQ(node_a.axID(), notification.nodes[1].id);
+  EXPECT_EQ(node_c.axID(), notification.nodes[2].id);
+  EXPECT_EQ(3, CountAccessibilityNodesSentToBrowser());
 }
 
 TEST_F(RendererAccessibilityTest, ShowAccessibilityObject) {
diff --git a/content/renderer/accessibility/renderer_accessibility_complete.cc b/content/renderer/accessibility/renderer_accessibility_complete.cc
index 6ce31d7..c8111d3 100644
--- a/content/renderer/accessibility/renderer_accessibility_complete.cc
+++ b/content/renderer/accessibility/renderer_accessibility_complete.cc
@@ -4,6 +4,8 @@
 
 #include "content/renderer/accessibility/renderer_accessibility_complete.h"
 
+#include <queue>
+
 #include "base/bind.h"
 #include "base/message_loop.h"
 #include "content/renderer/accessibility/accessibility_node_serializer.h"
@@ -102,7 +104,7 @@
 RendererAccessibilityComplete::RendererAccessibilityComplete(
     RenderViewImpl* render_view)
     : RendererAccessibility(render_view),
-      ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)),
+      weak_factory_(this),
       browser_root_(NULL),
       last_scroll_offset_(gfx::Size()),
       ack_pending_(false) {
@@ -227,12 +229,11 @@
     // When no accessibility notifications are in-flight post a task to send
     // the notifications to the browser. We use PostTask so that we can queue
     // up additional notifications.
-    MessageLoop::current()->PostTask(
+    base::MessageLoop::current()->PostTask(
         FROM_HERE,
-        base::Bind(
-            &RendererAccessibilityComplete::
-                SendPendingAccessibilityNotifications,
-            weak_factory_.GetWeakPtr()));
+        base::Bind(&RendererAccessibilityComplete::
+                       SendPendingAccessibilityNotifications,
+                   weak_factory_.GetWeakPtr()));
   }
 }
 
@@ -360,9 +361,54 @@
 #endif
   }
 
+  AppendLocationChangeNotifications(&notification_msgs);
+
   Send(new AccessibilityHostMsg_Notifications(routing_id(), notification_msgs));
 }
 
+void RendererAccessibilityComplete::AppendLocationChangeNotifications(
+    std::vector<AccessibilityHostMsg_NotificationParams>* notification_msgs) {
+  std::queue<WebAccessibilityObject> objs_to_explore;
+  std::vector<BrowserTreeNode*> location_changes;
+  WebAccessibilityObject root_object = GetMainDocument().accessibilityObject();
+  objs_to_explore.push(root_object);
+
+  while (objs_to_explore.size()) {
+    WebAccessibilityObject obj = objs_to_explore.front();
+    objs_to_explore.pop();
+    int id = obj.axID();
+    if (browser_id_map_.find(id) != browser_id_map_.end()) {
+      BrowserTreeNode* browser_node = browser_id_map_[id];
+      gfx::Rect new_location = obj.boundingBoxRect();
+      if (browser_node->location != new_location) {
+        browser_node->location = new_location;
+        location_changes.push_back(browser_node);
+      }
+    }
+
+    for (unsigned i = 0; i < obj.childCount(); ++i)
+      objs_to_explore.push(obj.childAt(i));
+  }
+
+  if (location_changes.size() == 0)
+    return;
+
+  AccessibilityHostMsg_NotificationParams notification_msg;
+  notification_msg.notification_type =
+      static_cast<AccessibilityNotification>(-1);
+  notification_msg.id = root_object.axID();
+  notification_msg.nodes.resize(location_changes.size());
+  for (size_t i = 0; i < location_changes.size(); i++) {
+    AccessibilityNodeData& serialized_node = notification_msg.nodes[i];
+    serialized_node.id = location_changes[i]->id;
+    serialized_node.location = location_changes[i]->location;
+    serialized_node.bool_attributes[
+        AccessibilityNodeData::ATTR_UPDATE_LOCATION_ONLY] = true;
+  }
+
+  notification_msgs->push_back(notification_msg);
+}
+
 RendererAccessibilityComplete::BrowserTreeNode*
 RendererAccessibilityComplete::CreateBrowserTreeNode() {
   return new RendererAccessibilityComplete::BrowserTreeNode();
@@ -397,24 +443,45 @@
     browser_root_ = CreateBrowserTreeNode();
     browser_node = browser_root_;
     browser_node->id = obj.axID();
+    browser_node->location = obj.boundingBoxRect();
+    browser_node->parent = NULL;
     browser_id_map_[browser_node->id] = browser_node;
   }
 
-  // Serialize this node. This fills in all of the fields in
-  // AccessibilityNodeData except child_ids, which we handle below.
-  dst->push_back(AccessibilityNodeData());
-  AccessibilityNodeData* serialized_node = &dst->back();
-  SerializeAccessibilityNode(obj, serialized_node);
-  if (serialized_node->id == browser_root_->id)
-    serialized_node->role = AccessibilityNodeData::ROLE_ROOT_WEB_AREA;
-
-  // Create set of the ids of the children of |obj| so we can quickly look
+  // Iterate over the ids of the children of |obj|.
+  // Create a set of the child ids so we can quickly look
   // up which children are new and which ones were there before.
+  // Also catch the case where a child is already in the browser tree
+  // data structure with a different parent, and make sure the old parent
+  // clears this node first.
   base::hash_set<int32> new_child_ids;
+  const WebDocument& document = GetMainDocument();
   for (unsigned i = 0; i < obj.childCount(); i++) {
     WebAccessibilityObject child = obj.childAt(i);
     if (ShouldIncludeChildNode(obj, child)) {
-      new_child_ids.insert(child.axID());
+      int new_child_id = child.axID();
+      new_child_ids.insert(new_child_id);
+
+      BrowserTreeNode* child = browser_id_map_[new_child_id];
+      if (child && child->parent != browser_node) {
+        // The child is being reparented. Find the WebKit accessibility
+        // object corresponding to the old parent, or the closest ancestor
+        // still in the tree.
+        BrowserTreeNode* parent = child->parent;
+        WebAccessibilityObject parent_obj;
+        while (parent) {
+          parent_obj = document.accessibilityObjectFromID(parent->id);
+          if (!parent_obj.isDetached())
+            break;
+          parent = parent->parent;
+        }
+        CHECK(parent);
+        // Call SerializeChangedNodes recursively on the old parent,
+        // so that the update that clears |child| from its old parent
+        // occurs stricly before the update that adds |child| to its
+        // new parent.
+        SerializeChangedNodes(parent_obj, dst);
+      }
     }
   }
 
@@ -439,6 +506,14 @@
     }
   }
 
+  // Serialize this node. This fills in all of the fields in
+  // AccessibilityNodeData except child_ids, which we handle below.
+  dst->push_back(AccessibilityNodeData());
+  AccessibilityNodeData* serialized_node = &dst->back();
+  SerializeAccessibilityNode(obj, serialized_node);
+  if (serialized_node->id == browser_root_->id)
+    serialized_node->role = AccessibilityNodeData::ROLE_ROOT_WEB_AREA;
+
   // Iterate over the children, make note of the ones that are new
   // and need to be serialized, and update the BrowserTreeNode
   // data structure to reflect the new tree.
@@ -462,10 +537,14 @@
     new_child_ids.erase(child_id);
     serialized_node->child_ids.push_back(child_id);
     if (browser_child_id_map.find(child_id) != browser_child_id_map.end()) {
-      browser_node->children.push_back(browser_child_id_map[child_id]);
+      BrowserTreeNode* reused_child = browser_child_id_map[child_id];
+      reused_child->location = obj.boundingBoxRect();
+      browser_node->children.push_back(reused_child);
     } else {
       BrowserTreeNode* new_child = CreateBrowserTreeNode();
       new_child->id = child_id;
+      new_child->location = obj.boundingBoxRect();
+      new_child->parent = browser_node;
       browser_node->children.push_back(new_child);
       browser_id_map_[child_id] = new_child;
       children_to_serialize.push_back(child);
@@ -625,7 +704,7 @@
 }
 
 void RendererAccessibilityComplete::OnFatalError() {
-  CHECK(false);
+  CHECK(false) << "Invalid accessibility tree.";
 }
 
 }  // namespace content
diff --git a/content/renderer/accessibility/renderer_accessibility_complete.h b/content/renderer/accessibility/renderer_accessibility_complete.h
index 41d0880..7fff8c2 100644
--- a/content/renderer/accessibility/renderer_accessibility_complete.h
+++ b/content/renderer/accessibility/renderer_accessibility_complete.h
@@ -54,6 +54,8 @@
     BrowserTreeNode();
     virtual ~BrowserTreeNode();
     int32 id;
+    gfx::Rect location;
+    BrowserTreeNode* parent;
     std::vector<BrowserTreeNode*> children;
   };
 
@@ -63,6 +65,13 @@
   // Send queued notifications from the renderer to the browser.
   void SendPendingAccessibilityNotifications();
 
+  // Check the entire accessibility tree to see if any nodes have
+  // changed location, by comparing their locations to the cached
+  // versions. If any have moved, append a notification to |notifications|
+  // that updates the coordinates of these objects.
+  void AppendLocationChangeNotifications(
+      std::vector<AccessibilityHostMsg_NotificationParams>* notifications);
+
  private:
   // Handle an accessibility notification to be sent to the browser process.
   void HandleAccessibilityNotification(
diff --git a/content/renderer/accessibility/renderer_accessibility_focus_only.cc b/content/renderer/accessibility/renderer_accessibility_focus_only.cc
index 71da433..aab2746 100644
--- a/content/renderer/accessibility/renderer_accessibility_focus_only.cc
+++ b/content/renderer/accessibility/renderer_accessibility_focus_only.cc
@@ -96,9 +96,11 @@
   // has focus, otherwise the focused node.
   notification.id = node_has_focus ? next_id_ : 1;
 
-  // Always include the root of the tree, the document. It always has id 1.
-  notification.nodes.push_back(AccessibilityNodeData());
+  notification.nodes.resize(2);
   AccessibilityNodeData& root = notification.nodes[0];
+  AccessibilityNodeData& child = notification.nodes[1];
+
+  // Always include the root of the tree, the document. It always has id 1.
   root.id = 1;
   root.role = AccessibilityNodeData::ROLE_ROOT_WEB_AREA;
   root.state =
@@ -109,8 +111,6 @@
   root.location = gfx::Rect(render_view_->size());
   root.child_ids.push_back(next_id_);
 
-  notification.nodes.push_back(AccessibilityNodeData());
-  AccessibilityNodeData& child = notification.nodes[1];
   child.id = next_id_;
   child.role = AccessibilityNodeData::ROLE_GROUP;
 
diff --git a/content/renderer/active_notification_tracker.cc b/content/renderer/active_notification_tracker.cc
index 5f4a40e..11e16c2 100644
--- a/content/renderer/active_notification_tracker.cc
+++ b/content/renderer/active_notification_tracker.cc
@@ -55,7 +55,7 @@
   scoped_ptr<WebNotification> notification(notification_table_.Lookup(id));
   notification_table_.Remove(id);
   DCHECK(notification.get());
-  if (notification.get())
+  if (notification)
     reverse_notification_table_.erase(*notification);
 }
 
diff --git a/content/renderer/android/synchronous_compositor_output_surface.cc b/content/renderer/android/synchronous_compositor_output_surface.cc
new file mode 100644
index 0000000..87792ea
--- /dev/null
+++ b/content/renderer/android/synchronous_compositor_output_surface.cc
@@ -0,0 +1,69 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/android/synchronous_compositor_output_surface.h"
+
+#include "base/logging.h"
+#include "cc/output/output_surface_client.h"
+#include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h"
+#include "content/public/renderer/android/synchronous_compositor_client.h"
+#include "content/public/renderer/content_renderer_client.h"
+#include "skia/ext/refptr.h"
+#include "third_party/skia/include/core/SkCanvas.h"
+#include "third_party/skia/include/core/SkPicture.h"
+
+namespace content {
+
+SynchronousCompositorOutputSurface::SynchronousCompositorOutputSurface(
+    int32 routing_id,
+    WebGraphicsContext3DCommandBufferImpl* context)
+    : cc::OutputSurface(scoped_ptr<WebKit::WebGraphicsContext3D>(context)),
+      compositor_client_(NULL),
+      routing_id_(routing_id) {
+  // WARNING: may be called on any thread.
+}
+
+SynchronousCompositorOutputSurface::~SynchronousCompositorOutputSurface() {
+  DCHECK(CalledOnValidThread());
+  if (compositor_client_)
+    compositor_client_->DidDestroyCompositor(this);
+}
+
+bool SynchronousCompositorOutputSurface::BindToClient(
+    cc::OutputSurfaceClient* surface_client) {
+  DCHECK(CalledOnValidThread());
+  if (!cc::OutputSurface::BindToClient(surface_client))
+    return false;
+  GetContentClient()->renderer()->DidCreateSynchronousCompositor(routing_id_,
+                                                                 this);
+  return true;
+}
+
+void SynchronousCompositorOutputSurface::SendFrameToParentCompositor(
+    cc::CompositorFrame* frame) {
+  // Intentional no-op: see http://crbug.com/237006
+}
+
+void SynchronousCompositorOutputSurface::SetClient(
+    SynchronousCompositorClient* compositor_client) {
+  DCHECK(CalledOnValidThread());
+  compositor_client_ = compositor_client;
+}
+
+bool SynchronousCompositorOutputSurface::DemandDrawSw(SkCanvas* canvas) {
+  DCHECK(CalledOnValidThread());
+  NOTIMPLEMENTED();  // TODO(joth): call through to OutputSurfaceClient
+  return false;
+}
+
+// Not using base::NonThreadSafe as we want to enforce a more exacting threading
+// requirement: SynchronousCompositorOutputSurface() must only be used by
+// embedders that supply their own compositor loop via
+// OverrideCompositorMessageLoop().
+bool SynchronousCompositorOutputSurface::CalledOnValidThread() const {
+  return base::MessageLoop::current() && (base::MessageLoop::current() ==
+      GetContentClient()->renderer()->OverrideCompositorMessageLoop());
+}
+
+}  // namespace content
diff --git a/content/renderer/android/synchronous_compositor_output_surface.h b/content/renderer/android/synchronous_compositor_output_surface.h
new file mode 100644
index 0000000..04af44f
--- /dev/null
+++ b/content/renderer/android/synchronous_compositor_output_surface.h
@@ -0,0 +1,56 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_RENDERER_ANDROID_SYNCHRONOUS_COMPOSITOR_OUTPUT_SURFACE_H_
+#define CONTENT_RENDERER_ANDOIRD_SYNCHRONOUS_COMPOSITOR_OUTPUT_SURFACE_H_
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "base/memory/scoped_ptr.h"
+#include "cc/output/output_surface.h"
+#include "content/public/renderer/android/synchronous_compositor.h"
+
+namespace content {
+
+class SynchronousCompositorClient;
+class WebGraphicsContext3DCommandBufferImpl;
+
+// Specialization of the output surface that adapts it to implement the
+// content::SynchronousCompositor public API. This class effects an "inversion
+// of control" - enabling drawing to be  orchestrated by the embedding
+// layer, instead of driven by the compositor internals - hence it holds two
+// 'client' pointers (including |client_| in the OutputSurface baseclass) which
+// represent the consumers of the two roles in plays.
+// This class can be created only on the main thread, but then becomes pinned
+// to a fixed thread when BindToClient is called.
+class SynchronousCompositorOutputSurface
+    : NON_EXPORTED_BASE(public cc::OutputSurface),
+      NON_EXPORTED_BASE(public SynchronousCompositor) {
+ public:
+  SynchronousCompositorOutputSurface(
+      int32 routing_id,
+      WebGraphicsContext3DCommandBufferImpl* context);
+  virtual ~SynchronousCompositorOutputSurface();
+
+  // OutputSurface.
+  virtual bool BindToClient(cc::OutputSurfaceClient* surface_client) OVERRIDE;
+  virtual void SendFrameToParentCompositor(cc::CompositorFrame* frame) OVERRIDE;
+
+  // SynchronousCompositor.
+  virtual void SetClient(SynchronousCompositorClient* compositor_client)
+      OVERRIDE;
+  virtual bool DemandDrawSw(SkCanvas* canvas) OVERRIDE;
+
+ private:
+  bool CalledOnValidThread() const;
+
+  SynchronousCompositorClient* compositor_client_;
+  int routing_id_;
+
+  DISALLOW_COPY_AND_ASSIGN(SynchronousCompositorOutputSurface);
+};
+
+}  // namespace content
+
+#endif  // CONTENT_RENDERER_ANDROID_SYNCHRONOUS_COMPOSITOR_OUTPUT_SURFACE_H_
diff --git a/content/renderer/browser_plugin/browser_plugin.cc b/content/renderer/browser_plugin/browser_plugin.cc
index b4921e5..002d2a5 100644
--- a/content/renderer/browser_plugin/browser_plugin.cc
+++ b/content/renderer/browser_plugin/browser_plugin.cc
@@ -52,25 +52,6 @@
 
 namespace {
 
-static bool shouldIgnoreKeyBoardEvent(const WebKit::WebKeyboardEvent* event) {
-  if (event->type == WebKit::WebInputEvent::Char)
-    return false;
-  int keycode = event->windowsKeyCode;
-  if (keycode == ui::VKEY_SHIFT ||
-      keycode == ui::VKEY_CONTROL ||
-      keycode == ui::VKEY_MENU ||
-      keycode == ui::VKEY_LWIN)  // The search key on chromeOS.
-    return true;
-  // We don't want to handle keys like volume control, or app launchers inside
-  // of BrowserPlugin. These keys should be handled either by the browser, or
-  // the OS.
-  if ((keycode >= ui::VKEY_BROWSER_BACK &&
-       keycode <= ui::VKEY_MEDIA_LAUNCH_APP2) ||
-      (keycode >= ui::VKEY_F1 && keycode <= ui::VKEY_F24))
-    return true;
-  return false;
-}
-
 static std::string TerminationStatusToString(base::TerminationStatus status) {
   switch (status) {
     case base::TERMINATION_STATUS_NORMAL_TERMINATION:
@@ -95,6 +76,8 @@
 
 static std::string PermissionTypeToString(BrowserPluginPermissionType type) {
   switch (type) {
+    case BrowserPluginPermissionTypeDownload:
+      return browser_plugin::kPermissionTypeDownload;
     case BrowserPluginPermissionTypeGeolocation:
       return browser_plugin::kPermissionTypeGeolocation;
     case BrowserPluginPermissionTypeMedia:
@@ -108,7 +91,7 @@
       NOTREACHED();
       break;
   }
-  return "";
+  return std::string();
 }
 
 typedef std::map<WebKit::WebPluginContainer*,
@@ -128,6 +111,7 @@
       container_(NULL),
       damage_buffer_sequence_id_(0),
       resize_ack_received_(true),
+      last_device_scale_factor_(1.0f),
       sad_guest_(NULL),
       guest_crashed_(false),
       auto_size_ack_pending_(false),
@@ -139,13 +123,12 @@
       plugin_focused_(false),
       visible_(true),
       size_changed_in_flight_(false),
-      allocate_instance_id_sent_(false),
-      browser_plugin_manager_(render_view->browser_plugin_manager()),
+      before_first_navigation_(true),
+      browser_plugin_manager_(render_view->GetBrowserPluginManager()),
       current_nav_entry_index_(0),
       nav_entry_count_(0),
       compositing_enabled_(false),
-      ALLOW_THIS_IN_INITIALIZER_LIST(
-          weak_ptr_factory_(this)) {
+      weak_ptr_factory_(this) {
 }
 
 BrowserPlugin::~BrowserPlugin() {
@@ -171,8 +154,14 @@
 bool BrowserPlugin::OnMessageReceived(const IPC::Message& message) {
   bool handled = true;
   IPC_BEGIN_MESSAGE_MAP(BrowserPlugin, message)
+    IPC_MESSAGE_HANDLER(BrowserPluginMsg_AddMessageToConsole,
+                        OnAddMessageToConsole)
     IPC_MESSAGE_HANDLER(BrowserPluginMsg_AdvanceFocus, OnAdvanceFocus)
+    IPC_MESSAGE_HANDLER(BrowserPluginMsg_Attach_ACK, OnAttachACK)
     IPC_MESSAGE_HANDLER(BrowserPluginMsg_BuffersSwapped, OnBuffersSwapped)
+    IPC_MESSAGE_HANDLER(BrowserPluginMsg_Close, OnClose)
+    IPC_MESSAGE_HANDLER_GENERIC(BrowserPluginMsg_CompositorFrameSwapped,
+                                OnCompositorFrameSwapped(message))
     IPC_MESSAGE_HANDLER(BrowserPluginMsg_GuestContentWindowReady,
                         OnGuestContentWindowReady)
     IPC_MESSAGE_HANDLER(BrowserPluginMsg_GuestGone, OnGuestGone)
@@ -222,7 +211,7 @@
 std::string BrowserPlugin::GetDOMAttributeValue(
     const std::string& attribute_name) const {
   if (!container())
-    return "";
+    return std::string();
 
   return container()->element().getAttribute(
       WebKit::WebString::fromUTF8(attribute_name)).utf8();
@@ -332,16 +321,16 @@
   if (!HasGuest()) {
     // On initial navigation, we request an instance ID from the browser
     // process. We essentially ignore all subsequent calls to SetSrcAttribute
-    // until we receive an instance ID. |allocate_instance_id_sent_|
+    // until we receive an instance ID. |before_first_navigation_|
     // prevents BrowserPlugin from allocating more than one instance ID.
     // Upon receiving an instance ID from the browser process, we continue
     // the process of navigation by populating the
-    // BrowserPluginHostMsg_CreateGuest_Params with the current state of
+    // BrowserPluginHostMsg_Attach_Params with the current state of
     // BrowserPlugin and sending a BrowserPluginHostMsg_CreateGuest to the
     // browser process in order to create a new guest.
-    if (!allocate_instance_id_sent_) {
+    if (before_first_navigation_) {
       browser_plugin_manager()->AllocateInstanceID(this);
-      allocate_instance_id_sent_ = true;
+      before_first_navigation_ = false;
     }
     return true;
   }
@@ -413,37 +402,46 @@
 
 bool BrowserPlugin::UsesPendingDamageBuffer(
     const BrowserPluginMsg_UpdateRect_Params& params) {
-  if (!pending_damage_buffer_.get())
+  if (!pending_damage_buffer_)
     return false;
   return damage_buffer_sequence_id_ == params.damage_buffer_sequence_id;
 }
 
-void BrowserPlugin::SetInstanceID(int instance_id, bool new_guest) {
+void BrowserPlugin::Attach(int instance_id) {
   CHECK(instance_id != browser_plugin::kInstanceIDNone);
+  before_first_navigation_ = false;
   instance_id_ = instance_id;
   browser_plugin_manager()->AddBrowserPlugin(instance_id, this);
 
-  BrowserPluginHostMsg_CreateGuest_Params create_guest_params;
+  BrowserPluginHostMsg_Attach_Params create_guest_params;
   create_guest_params.focused = ShouldGuestBeFocused();
   create_guest_params.visible = visible_;
   create_guest_params.name = GetNameAttribute();
-  GetDamageBufferWithSizeParams(&create_guest_params.auto_size_params,
-                                &create_guest_params.resize_guest_params);
-
-  if (!new_guest) {
-    browser_plugin_manager()->Send(
-        new BrowserPluginHostMsg_Attach(render_view_routing_id_,
-                                        instance_id_, create_guest_params));
-    return;
-  }
-
   create_guest_params.storage_partition_id = storage_partition_id_;
   create_guest_params.persist_storage = persist_storage_;
   create_guest_params.src = GetSrcAttribute();
+  GetDamageBufferWithSizeParams(&create_guest_params.auto_size_params,
+                                &create_guest_params.resize_guest_params);
+
   browser_plugin_manager()->Send(
-      new BrowserPluginHostMsg_CreateGuest(render_view_routing_id_,
-                                           instance_id_,
-                                           create_guest_params));
+      new BrowserPluginHostMsg_Attach(render_view_routing_id_,
+                                      instance_id_, create_guest_params));
+}
+
+void BrowserPlugin::DidCommitCompositorFrame() {
+  if (compositing_helper_)
+    compositing_helper_->DidCommitCompositorFrame();
+}
+
+void BrowserPlugin::OnAddMessageToConsole(
+    int instance_id, const base::DictionaryValue& message_info) {
+  std::map<std::string, base::Value*> props;
+  // Fill in the info provided by the browser.
+  for (DictionaryValue::Iterator iter(message_info); !iter.IsAtEnd();
+           iter.Advance()) {
+    props[iter.key()] = iter.value().DeepCopy();
+  }
+  TriggerEvent(browser_plugin::kEventConsoleMessage, &props);
 }
 
 void BrowserPlugin::OnAdvanceFocus(int instance_id, bool reverse) {
@@ -451,6 +449,20 @@
   render_view_->GetWebView()->advanceFocus(reverse);
 }
 
+void BrowserPlugin::OnAttachACK(
+    int instance_id,
+    const BrowserPluginMsg_Attach_ACK_Params& params) {
+  // Update BrowserPlugin attributes to match the state of the guest.
+  if (!params.name.empty())
+    OnUpdatedName(instance_id, params.name);
+  if (!params.storage_partition_id.empty()) {
+    std::string partition_name =
+        (params.persist_storage ? browser_plugin::kPersistPrefix : "") +
+            params.storage_partition_id;
+    UpdateDOMAttribute(browser_plugin::kAttributePartition, partition_name);
+  }
+}
+
 void BrowserPlugin::OnBuffersSwapped(int instance_id,
                                      const gfx::Size& size,
                                      std::string mailbox_name,
@@ -466,6 +478,23 @@
                                         GetDeviceScaleFactor());
 }
 
+void BrowserPlugin::OnClose(int instance_id) {
+  TriggerEvent(browser_plugin::kEventClose, NULL);
+}
+
+void BrowserPlugin::OnCompositorFrameSwapped(const IPC::Message& message) {
+  BrowserPluginMsg_CompositorFrameSwapped::Param param;
+  if (!BrowserPluginMsg_CompositorFrameSwapped::Read(&message, &param))
+    return;
+  scoped_ptr<cc::CompositorFrame> frame(new cc::CompositorFrame);
+  param.b.AssignTo(frame.get());
+
+  EnableCompositing(true);
+  compositing_helper_->OnCompositorFrameSwapped(frame.Pass(),
+                                                param.c /* route_id */,
+                                                param.d /* host_id */);
+}
+
 void BrowserPlugin::OnGuestContentWindowReady(int instance_id,
                                               int content_window_routing_id) {
   DCHECK(content_window_routing_id != MSG_ROUTING_NONE);
@@ -655,7 +684,8 @@
 
   if ((!auto_size && (width() != params.view_size.width() ||
                       height() != params.view_size.height())) ||
-      (auto_size && (!InAutoSizeBounds(params.view_size)))) {
+      (auto_size && (!InAutoSizeBounds(params.view_size))) ||
+      GetDeviceScaleFactor() != params.scale_factor) {
     // We are HW accelerated, render widget does not expect an ack,
     // but we still need to update the size.
     if (!params.needs_ack) {
@@ -702,7 +732,7 @@
     // with the last seen view size.
     if (container_ && !size_changed_in_flight_) {
       size_changed_in_flight_ = true;
-      MessageLoop::current()->PostTask(
+      base::MessageLoop::current()->PostTask(
           FROM_HERE,
           base::Bind(&BrowserPlugin::SizeChangedDueToAutoSize,
                      base::Unretained(this),
@@ -735,11 +765,9 @@
                                        params.scroll_rect,
                                        params.view_size);
   }
-  for (unsigned i = 0; i < params.copy_rects.size(); i++) {
-    backing_store_->PaintToBackingStore(params.bitmap_rect,
-                                        params.copy_rects,
-                                        current_damage_buffer_->memory());
-  }
+  backing_store_->PaintToBackingStore(params.bitmap_rect,
+                                      params.copy_rects,
+                                      current_damage_buffer_->memory());
 
   // Invalidate the container.
   // If the BrowserPlugin is scheduled to be deleted, then container_ will be
@@ -769,8 +797,8 @@
 NPObject* BrowserPlugin::GetContentWindow() const {
   if (content_window_routing_id_ == MSG_ROUTING_NONE)
     return NULL;
-  RenderViewImpl* guest_render_view = static_cast<RenderViewImpl*>(
-      ChildThread::current()->ResolveRoute(content_window_routing_id_));
+  RenderViewImpl* guest_render_view = RenderViewImpl::FromRoutingID(
+      content_window_routing_id_);
   if (!guest_render_view)
     return NULL;
   WebKit::WebFrame* guest_frame = guest_render_view->GetWebView()->mainFrame();
@@ -808,11 +836,11 @@
   // If the BrowserPlugin already has a guest attached to it then we probably
   // shouldn't allow attaching a different guest.
   // TODO(fsamuel): We may wish to support reattaching guests in the future:
-  // http://crbug.com/156219
+  // http://crbug.com/156219.
   if (browser_plugin->HasGuest())
     return false;
 
-  browser_plugin->SetInstanceID(window_id, false);
+  browser_plugin->Attach(window_id);
   return true;
 }
 
@@ -830,7 +858,7 @@
 }
 
 bool BrowserPlugin::ParsePartitionAttribute(std::string* error_message) {
-  if (allocate_instance_id_sent_) {
+  if (!before_first_navigation_) {
     *error_message = browser_plugin::kErrorAlreadyNavigated;
     return false;
   }
@@ -883,6 +911,18 @@
   return render_view_->GetWebView()->deviceScaleFactor();
 }
 
+void BrowserPlugin::UpdateDeviceScaleFactor(float device_scale_factor) {
+  if (last_device_scale_factor_ == device_scale_factor || !resize_ack_received_)
+    return;
+
+  BrowserPluginHostMsg_ResizeGuest_Params params;
+  PopulateResizeGuestParameters(&params, gfx::Size(width(), height()));
+  browser_plugin_manager()->Send(new BrowserPluginHostMsg_ResizeGuest(
+      render_view_routing_id_,
+      instance_id_,
+      params));
+}
+
 void BrowserPlugin::TriggerEvent(const std::string& event_name,
                                  std::map<std::string, base::Value*>* props) {
   if (!container() || !container()->element().document().frame())
@@ -938,9 +978,8 @@
   }
 
   v8::Isolate* isolate = v8::Isolate::GetCurrent();
-  v8::Persistent<v8::Value> weak_request =
-      v8::Persistent<v8::Value>::New(isolate,
-                                     WebKit::WebBindings::toV8Value(request));
+  v8::Persistent<v8::Value> weak_request(
+      isolate, WebKit::WebBindings::toV8Value(request));
 
   AliveV8PermissionRequestItem* new_item =
       new std::pair<int, base::WeakPtr<BrowserPlugin> >(
@@ -973,10 +1012,11 @@
     // Asynchronously remove item from |alive_v8_permission_request_objects_|.
     // Note that we are using weak pointer for the following PostTask, so we
     // don't need to worry about BrowserPlugin going away.
-    MessageLoop::current()->PostTask(
+    base::MessageLoop::current()->PostTask(
         FROM_HERE,
         base::Bind(&BrowserPlugin::OnRequestObjectGarbageCollected,
-                   plugin, request_id));
+                   plugin,
+                   request_id));
   }
 }
 
@@ -1143,11 +1183,11 @@
   // Will be a no-op if the mouse is not currently locked.
   if (render_view_)
     render_view_->mouse_lock_dispatcher()->OnLockTargetDestroyed(this);
-  MessageLoop::current()->DeleteSoon(FROM_HERE, this);
+  base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
 }
 
 NPObject* BrowserPlugin::scriptableObject() {
-  if (!bindings_.get())
+  if (!bindings_)
     return NULL;
 
   NPObject* browser_plugin_np_object(bindings_->np_object());
@@ -1224,8 +1264,12 @@
 bool BrowserPlugin::ShouldForwardToBrowserPlugin(
     const IPC::Message& message) {
   switch (message.type()) {
+    case BrowserPluginMsg_AddMessageToConsole::ID:
     case BrowserPluginMsg_AdvanceFocus::ID:
+    case BrowserPluginMsg_Attach_ACK::ID:
     case BrowserPluginMsg_BuffersSwapped::ID:
+    case BrowserPluginMsg_Close::ID:
+    case BrowserPluginMsg_CompositorFrameSwapped::ID:
     case BrowserPluginMsg_GuestContentWindowReady::ID:
     case BrowserPluginMsg_GuestGone::ID:
     case BrowserPluginMsg_GuestResponsive::ID:
@@ -1288,6 +1332,10 @@
     const gfx::Size& view_size) {
   params->view_size = view_size;
   params->scale_factor = GetDeviceScaleFactor();
+  if (last_device_scale_factor_ != params->scale_factor){
+    params->repaint = true;
+    last_device_scale_factor_ = params->scale_factor;
+  }
 
   // In HW compositing mode, we do not need a damage buffer.
   if (compositing_enabled_)
@@ -1306,7 +1354,7 @@
   params->damage_buffer_size = size;
   pending_damage_buffer_.reset(
       CreateDamageBuffer(size, &params->damage_buffer_handle));
-  if (!pending_damage_buffer_.get())
+  if (!pending_damage_buffer_)
     NOTREACHED();
   params->damage_buffer_sequence_id = ++damage_buffer_sequence_id_;
 }
@@ -1332,7 +1380,7 @@
       content::RenderThread::Get()->HostAllocateSharedMemoryBuffer(
           size).release());
 
-  if (shared_buf.get()) {
+  if (shared_buf) {
     if (shared_buf->Map(size)) {
       // Insert the magic word.
       *static_cast<unsigned int*>(shared_buf->memory()) = 0xdeadbeef;
@@ -1403,16 +1451,6 @@
       event.type == WebKit::WebInputEvent::ContextMenu)
     return false;
 
-  if (WebKit::WebInputEvent::isKeyboardEventType(event.type)) {
-    // TODO(mthiesse): This is a temporary solution for BrowserPlugin capturing
-    // keys like the search key on chromeOS. The guest should be allowed to
-    // handle these key events (as javascript allows this), so a better solution
-    // is needed.
-    if (shouldIgnoreKeyBoardEvent(
-        static_cast<const WebKit::WebKeyboardEvent*>(&event)))
-      return false;
-  }
-
   const WebKit::WebInputEvent* modified_event = &event;
   scoped_ptr<WebKit::WebTouchEvent> touch_event;
   // WebKit gives BrowserPlugin a list of touches that are down, but the browser
@@ -1455,7 +1493,7 @@
         WebDropData(drag_data),
         mask,
         position));
-  return false;
+  return true;
 }
 
 void BrowserPlugin::didReceiveResponse(
@@ -1481,6 +1519,16 @@
     const WebKit::WebURLError& error) {
 }
 
+bool BrowserPlugin::executeEditCommand(const WebKit::WebString& name) {
+  browser_plugin_manager()->Send(new BrowserPluginHostMsg_ExecuteEditCommand(
+      render_view_routing_id_,
+      instance_id_,
+      name.utf8()));
+
+  // BrowserPlugin swallows edit commands.
+  return true;
+}
+
 void BrowserPlugin::OnLockMouseACK(bool succeeded) {
   browser_plugin_manager()->Send(new BrowserPluginHostMsg_LockMouse_ACK(
       render_view_routing_id_,
diff --git a/content/renderer/browser_plugin/browser_plugin.h b/content/renderer/browser_plugin/browser_plugin.h
index 4c7d14b..be6b995 100644
--- a/content/renderer/browser_plugin/browser_plugin.h
+++ b/content/renderer/browser_plugin/browser_plugin.h
@@ -14,6 +14,7 @@
 #if defined(OS_WIN)
 #include "base/shared_memory.h"
 #endif
+#include "base/values.h"
 #include "content/common/browser_plugin/browser_plugin_message_enums.h"
 #include "content/renderer/browser_plugin/browser_plugin_backing_store.h"
 #include "content/renderer/browser_plugin/browser_plugin_bindings.h"
@@ -23,6 +24,7 @@
 
 struct BrowserPluginHostMsg_AutoSize_Params;
 struct BrowserPluginHostMsg_ResizeGuest_Params;
+struct BrowserPluginMsg_Attach_ACK_Params;
 struct BrowserPluginMsg_LoadCommit_Params;
 struct BrowserPluginMsg_UpdateRect_Params;
 
@@ -114,6 +116,10 @@
   // Indicates whether the guest should be focused.
   bool ShouldGuestBeFocused() const;
 
+  // Embedder's device scale factor changed, we need to update the guest
+  // renderer.
+  void UpdateDeviceScaleFactor(float device_scale_factor);
+
   // Tells the BrowserPlugin to tell the guest to navigate to the previous
   // navigation entry in the navigation history.
   void Back();
@@ -149,9 +155,16 @@
   // Called by browser plugin binding.
   void OnEmbedderDecidedPermission(int request_id, bool allow);
 
-  // Sets the instance ID of the BrowserPlugin and requests a guest from the
-  // browser process.
-  void SetInstanceID(int instance_id, bool new_guest);
+  // Attaches this BrowserPlugin to a guest with the provided |instance_id|.
+  // If the |instance_id| is not yet associated with a guest, a new guest
+  // will be created. If the |instance_id| has not yet been allocated or the
+  // embedder is not permitted access to that particular guest, then the
+  // embedder will be killed.
+  void Attach(int instance_id);
+
+  // Notify the plugin about a compositor commit so that frame ACKs could be
+  // sent, if needed.
+  void DidCommitCompositorFrame();
 
   // Returns whether a message should be forwarded to BrowserPlugin.
   static bool ShouldForwardToBrowserPlugin(const IPC::Message& message);
@@ -194,6 +207,7 @@
       const WebKit::WebURL& url,
       void* notify_data,
       const WebKit::WebURLError& error) OVERRIDE;
+  virtual bool executeEditCommand(const WebKit::WebString& name) OVERRIDE;
 
   // MouseLockDispatcher::LockTarget implementation.
   virtual void OnLockMouseACK(bool succeeded) OVERRIDE;
@@ -288,10 +302,6 @@
   bool UsesPendingDamageBuffer(
       const BrowserPluginMsg_UpdateRect_Params& params);
 
-  // Sets the instance ID of the BrowserPlugin and requests a guest from the
-  // browser process.
-  void SetInstanceID(int instance_id);
-
   void AddPermissionRequestToMap(int request_id,
                                  BrowserPluginPermissionType type);
 
@@ -318,12 +328,19 @@
 
   // IPC message handlers.
   // Please keep in alphabetical order.
+  void OnAddMessageToConsole(
+      int instance_id,
+      const base::DictionaryValue& message_info);
   void OnAdvanceFocus(int instance_id, bool reverse);
+  void OnAttachACK(int instance_id,
+                   const BrowserPluginMsg_Attach_ACK_Params& ack_params);
   void OnBuffersSwapped(int instance_id,
                         const gfx::Size& size,
                         std::string mailbox_name,
                         int gpu_route_id,
                         int gpu_host_id);
+  void OnClose(int instance_id);
+  void OnCompositorFrameSwapped(const IPC::Message& message);
   void OnGuestContentWindowReady(int instance_id,
                                  int content_window_routing_id);
   void OnGuestGone(int instance_id, int process_id, int status);
@@ -367,6 +384,7 @@
   uint32 damage_buffer_sequence_id_;
   bool resize_ack_received_;
   gfx::Rect plugin_rect_;
+  float last_device_scale_factor_;
   // Bitmap for crashed plugin. Lazily initialized, non-owning pointer.
   SkBitmap* sad_guest_;
   bool guest_crashed_;
@@ -387,7 +405,7 @@
 
   gfx::Size last_view_size_;
   bool size_changed_in_flight_;
-  bool allocate_instance_id_sent_;
+  bool before_first_navigation_;
 
   // Each permission request item in the map is a pair of request id and
   // permission type.
diff --git a/content/renderer/browser_plugin/browser_plugin_bindings.cc b/content/renderer/browser_plugin/browser_plugin_bindings.cc
index 0ec0936..9ded3f9 100644
--- a/content/renderer/browser_plugin/browser_plugin_bindings.cc
+++ b/content/renderer/browser_plugin/browser_plugin_bindings.cc
@@ -815,7 +815,7 @@
 BrowserPluginBindings::BrowserPluginBindings(BrowserPlugin* instance)
     : instance_(instance),
       np_object_(NULL),
-      ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) {
+      weak_ptr_factory_(this) {
   NPObject* obj =
       WebBindings::createObject(NULL, &browser_plugin_message_class);
   np_object_ = static_cast<BrowserPluginBindings::BrowserPluginNPObject*>(obj);
diff --git a/content/renderer/browser_plugin/browser_plugin_browsertest.cc b/content/renderer/browser_plugin/browser_plugin_browsertest.cc
index e8f38ee..7b6a373 100644
--- a/content/renderer/browser_plugin/browser_plugin_browsertest.cc
+++ b/content/renderer/browser_plugin/browser_plugin_browsertest.cc
@@ -98,8 +98,7 @@
 
 void BrowserPluginTest::SetUp() {
   test_content_renderer_client_.reset(new TestContentRendererClient);
-  GetContentClient()->set_renderer_for_testing(
-      test_content_renderer_client_.get());
+  SetRendererClientForTesting(test_content_renderer_client_.get());
   BrowserPluginManager::set_factory_for_testing(
       TestBrowserPluginManagerFactory::GetInstance());
   content::RenderViewTest::SetUp();
@@ -122,7 +121,7 @@
 
   v8::Local<v8::String> v8_str = value->ToString();
   int length = v8_str->Utf8Length() + 1;
-  scoped_array<char> str(new char[length]);
+  scoped_ptr<char[]> str(new char[length]);
   v8_str->WriteUtf8(str.get(), length);
   return str.get();
 }
@@ -160,15 +159,15 @@
 // satisfy its resize request.
 TEST_F(BrowserPluginTest, InitialResize) {
   LoadHTML(GetHTMLForBrowserPluginObject().c_str());
-  // Verify that the information in CreateGuest is correct.
+  // Verify that the information in Attach is correct.
   int instance_id = 0;
   {
     const IPC::Message* msg =
         browser_plugin_manager()->sink().GetUniqueMessageMatching(
-            BrowserPluginHostMsg_CreateGuest::ID);
+            BrowserPluginHostMsg_Attach::ID);
     ASSERT_TRUE(msg);
-    BrowserPluginHostMsg_CreateGuest_Params params;
-    BrowserPluginHostMsg_CreateGuest::Read(msg, &instance_id, &params);
+    BrowserPluginHostMsg_Attach_Params params;
+    BrowserPluginHostMsg_Attach::Read(msg, &instance_id, &params);
     EXPECT_EQ(640, params.resize_guest_params.view_size.width());
     EXPECT_EQ(480, params.resize_guest_params.view_size.height());
   }
@@ -235,15 +234,15 @@
   // Verify that we're reporting the correct URL to navigate to based on the
   // src attribute.
   {
-    // Ensure we get a CreateGuest on the initial navigation.
+    // Ensure we get a Attach on the initial navigation.
     const IPC::Message* msg =
         browser_plugin_manager()->sink().GetUniqueMessageMatching(
-            BrowserPluginHostMsg_CreateGuest::ID);
+            BrowserPluginHostMsg_Attach::ID);
     ASSERT_TRUE(msg);
 
     int instance_id = 0;
-    BrowserPluginHostMsg_CreateGuest_Params params;
-    BrowserPluginHostMsg_CreateGuest::Read(msg, &instance_id, &params);
+    BrowserPluginHostMsg_Attach_Params params;
+    BrowserPluginHostMsg_Attach::Read(msg, &instance_id, &params);
     EXPECT_EQ("foo", params.src);
   }
 
@@ -253,10 +252,10 @@
   // Verify that the src attribute is updated as well.
   ExecuteJavaScript("document.getElementById('browserplugin').src = 'bar'");
   {
-    // Verify that we do not get a CreateGuest on subsequent navigations.
+    // Verify that we do not get a Attach on subsequent navigations.
     const IPC::Message* create_msg =
         browser_plugin_manager()->sink().GetUniqueMessageMatching(
-            BrowserPluginHostMsg_CreateGuest::ID);
+            BrowserPluginHostMsg_Attach::ID);
     ASSERT_FALSE(create_msg);
 
     const IPC::Message* msg =
@@ -279,14 +278,14 @@
   LoadHTML(GetHTMLForBrowserPluginObject().c_str());
   int instance_id = 0;
   {
-    // Ensure we get a CreateGuest on the initial navigation and grab the
+    // Ensure we get a Attach on the initial navigation and grab the
     // BrowserPlugin's instance_id from there.
     const IPC::Message* msg =
         browser_plugin_manager()->sink().GetUniqueMessageMatching(
-            BrowserPluginHostMsg_CreateGuest::ID);
+            BrowserPluginHostMsg_Attach::ID);
     ASSERT_TRUE(msg);
-    BrowserPluginHostMsg_CreateGuest_Params params;
-    BrowserPluginHostMsg_CreateGuest::Read(msg, &instance_id, &params);
+    BrowserPluginHostMsg_Attach_Params params;
+    BrowserPluginHostMsg_Attach::Read(msg, &instance_id, &params);
   }
   MockBrowserPlugin* browser_plugin =
       static_cast<MockBrowserPlugin*>(
@@ -374,15 +373,15 @@
 TEST_F(BrowserPluginTest, GuestCrash) {
   LoadHTML(GetHTMLForBrowserPluginObject().c_str());
 
-  // Grab the BrowserPlugin's instance ID from its CreateGuest message.
+  // Grab the BrowserPlugin's instance ID from its Attach message.
   int instance_id = 0;
   {
     const IPC::Message* msg =
         browser_plugin_manager()->sink().GetFirstMessageMatching(
-            BrowserPluginHostMsg_CreateGuest::ID);
+            BrowserPluginHostMsg_Attach::ID);
     ASSERT_TRUE(msg);
-    BrowserPluginHostMsg_CreateGuest_Params params;
-    BrowserPluginHostMsg_CreateGuest::Read(msg, &instance_id, &params);
+    BrowserPluginHostMsg_Attach_Params params;
+    BrowserPluginHostMsg_Attach::Read(msg, &instance_id, &params);
   }
   MockBrowserPlugin* browser_plugin =
       static_cast<MockBrowserPlugin*>(
@@ -483,11 +482,11 @@
   // Grab the BrowserPlugin's instance ID from its resize message.
   const IPC::Message* msg =
       browser_plugin_manager()->sink().GetFirstMessageMatching(
-          BrowserPluginHostMsg_CreateGuest::ID);
+          BrowserPluginHostMsg_Attach::ID);
   ASSERT_TRUE(msg);
   int instance_id = 0;
-  BrowserPluginHostMsg_CreateGuest_Params params;
-  BrowserPluginHostMsg_CreateGuest::Read(msg, &instance_id, &params);
+  BrowserPluginHostMsg_Attach_Params params;
+  BrowserPluginHostMsg_Attach::Read(msg, &instance_id, &params);
 
   MockBrowserPlugin* browser_plugin =
       static_cast<MockBrowserPlugin*>(
@@ -653,12 +652,12 @@
   {
     const IPC::Message* create_msg =
     browser_plugin_manager()->sink().GetUniqueMessageMatching(
-        BrowserPluginHostMsg_CreateGuest::ID);
+        BrowserPluginHostMsg_Attach::ID);
     ASSERT_TRUE(create_msg);
 
     int create_instance_id = 0;
-    BrowserPluginHostMsg_CreateGuest_Params params;
-    BrowserPluginHostMsg_CreateGuest::Read(
+    BrowserPluginHostMsg_Attach_Params params;
+    BrowserPluginHostMsg_Attach::Read(
         create_msg,
         &create_instance_id,
         &params);
@@ -704,14 +703,14 @@
 
   LoadHTML(GetHTMLForBrowserPluginObject().c_str());
   ExecuteJavaScript(kAddEventListener);
-  // Grab the BrowserPlugin's instance ID from its CreateGuest message.
+  // Grab the BrowserPlugin's instance ID from its Attach message.
   const IPC::Message* msg =
       browser_plugin_manager()->sink().GetFirstMessageMatching(
-          BrowserPluginHostMsg_CreateGuest::ID);
+          BrowserPluginHostMsg_Attach::ID);
   ASSERT_TRUE(msg);
   int instance_id = 0;
-  BrowserPluginHostMsg_CreateGuest_Params params;
-  BrowserPluginHostMsg_CreateGuest::Read(msg, &instance_id, &params);
+  BrowserPluginHostMsg_Attach_Params params;
+  BrowserPluginHostMsg_Attach::Read(msg, &instance_id, &params);
 
   MockBrowserPlugin* browser_plugin =
       static_cast<MockBrowserPlugin*>(
@@ -761,14 +760,14 @@
 
   LoadHTML(GetHTMLForBrowserPluginObject().c_str());
   ExecuteJavaScript(kAddEventListener);
-  // Grab the BrowserPlugin's instance ID from its CreateGuest message.
+  // Grab the BrowserPlugin's instance ID from its Attach message.
   const IPC::Message* msg =
       browser_plugin_manager()->sink().GetFirstMessageMatching(
-          BrowserPluginHostMsg_CreateGuest::ID);
+          BrowserPluginHostMsg_Attach::ID);
   ASSERT_TRUE(msg);
   int instance_id = 0;
-  BrowserPluginHostMsg_CreateGuest_Params params;
-  BrowserPluginHostMsg_CreateGuest::Read(msg, &instance_id, &params);
+  BrowserPluginHostMsg_Attach_Params params;
+  BrowserPluginHostMsg_Attach::Read(msg, &instance_id, &params);
 
   MockBrowserPlugin* browser_plugin =
       static_cast<MockBrowserPlugin*>(
@@ -789,15 +788,15 @@
 TEST_F(BrowserPluginTest, RemoveBrowserPluginOnExit) {
   LoadHTML(GetHTMLForBrowserPluginObject().c_str());
 
-  // Grab the BrowserPlugin's instance ID from its CreateGuest message.
+  // Grab the BrowserPlugin's instance ID from its Attach message.
   int instance_id = 0;
   {
     const IPC::Message* msg =
         browser_plugin_manager()->sink().GetFirstMessageMatching(
-            BrowserPluginHostMsg_CreateGuest::ID);
+            BrowserPluginHostMsg_Attach::ID);
     ASSERT_TRUE(msg);
-    BrowserPluginHostMsg_CreateGuest_Params params;
-    BrowserPluginHostMsg_CreateGuest::Read(msg, &instance_id, &params);
+    BrowserPluginHostMsg_Attach_Params params;
+    BrowserPluginHostMsg_Attach::Read(msg, &instance_id, &params);
   }
 
   MockBrowserPlugin* browser_plugin =
@@ -844,18 +843,18 @@
 
   int instance_id = 0;
   // Set some autosize parameters before navigating then navigate.
-  // Verify that the BrowserPluginHostMsg_CreateGuest message contains
+  // Verify that the BrowserPluginHostMsg_Attach message contains
   // the correct autosize parameters.
   ExecuteJavaScript(kSetAutoSizeParametersAndNavigate);
   ProcessPendingMessages();
   {
     const IPC::Message* create_msg =
     browser_plugin_manager()->sink().GetUniqueMessageMatching(
-        BrowserPluginHostMsg_CreateGuest::ID);
+        BrowserPluginHostMsg_Attach::ID);
     ASSERT_TRUE(create_msg);
 
-    BrowserPluginHostMsg_CreateGuest_Params params;
-    BrowserPluginHostMsg_CreateGuest::Read(
+    BrowserPluginHostMsg_Attach_Params params;
+    BrowserPluginHostMsg_Attach::Read(
         create_msg,
         &instance_id,
         &params);
diff --git a/content/renderer/browser_plugin/browser_plugin_browsertest.h b/content/renderer/browser_plugin/browser_plugin_browsertest.h
index 42d378f..44f10a9 100644
--- a/content/renderer/browser_plugin/browser_plugin_browsertest.h
+++ b/content/renderer/browser_plugin/browser_plugin_browsertest.h
@@ -31,7 +31,7 @@
   virtual void TearDown() OVERRIDE;
   MockBrowserPluginManager* browser_plugin_manager() const {
     return static_cast<MockBrowserPluginManager*>(
-        static_cast<RenderViewImpl*>(view_)->browser_plugin_manager());
+        static_cast<RenderViewImpl*>(view_)->GetBrowserPluginManager());
   }
   std::string ExecuteScriptAndReturnString(const std::string& script);
   int ExecuteScriptAndReturnInt(const std::string& script);
diff --git a/content/renderer/browser_plugin/browser_plugin_compositing_helper.cc b/content/renderer/browser_plugin/browser_plugin_compositing_helper.cc
index cdaeefc..fb32cdc 100644
--- a/content/renderer/browser_plugin/browser_plugin_compositing_helper.cc
+++ b/content/renderer/browser_plugin/browser_plugin_compositing_helper.cc
@@ -4,6 +4,7 @@
 
 #include "content/renderer/browser_plugin/browser_plugin_compositing_helper.h"
 
+#include "cc/layers/delegated_renderer_layer.h"
 #include "cc/layers/solid_color_layer.h"
 #include "cc/layers/texture_layer.h"
 #include "cc/output/context_provider.h"
@@ -26,8 +27,8 @@
     int host_routing_id)
     : instance_id_(instance_id),
       host_routing_id_(host_routing_id),
-      last_gpu_route_id_(0),
-      last_gpu_host_id_(0),
+      last_route_id_(0),
+      last_host_id_(0),
       last_mailbox_valid_(false),
       ack_pending_(true),
       ack_pending_for_crashed_guest_(false),
@@ -38,23 +39,51 @@
 BrowserPluginCompositingHelper::~BrowserPluginCompositingHelper() {
 }
 
-void BrowserPluginCompositingHelper::EnableCompositing(bool enable) {
-  if (enable && !texture_layer_) {
-    texture_layer_ = cc::TextureLayer::CreateForMailbox();
-    texture_layer_->SetIsDrawable(true);
-    texture_layer_->SetContentsOpaque(true);
+void BrowserPluginCompositingHelper::DidCommitCompositorFrame() {
+  if (!delegated_layer_ || !ack_pending_)
+    return;
 
+  cc::CompositorFrameAck ack;
+  delegated_layer_->TakeUnusedResourcesForChildCompositor(&ack.resources);
+
+  browser_plugin_manager_->Send(
+      new BrowserPluginHostMsg_CompositorFrameACK(
+          host_routing_id_,
+          instance_id_,
+          last_route_id_,
+          last_host_id_,
+          ack));
+
+  ack_pending_ = false;
+}
+
+void BrowserPluginCompositingHelper::EnableCompositing(bool enable) {
+  if (enable && !background_layer_) {
     background_layer_ = cc::SolidColorLayer::Create();
     background_layer_->SetMasksToBounds(true);
     background_layer_->SetBackgroundColor(
         SkColorSetARGBInline(255, 255, 255, 255));
-    background_layer_->AddChild(texture_layer_);
     web_layer_.reset(new webkit::WebLayerImpl(background_layer_));
   }
 
   container_->setWebLayer(enable ? web_layer_.get() : NULL);
 }
 
+void BrowserPluginCompositingHelper::CheckSizeAndAdjustLayerBounds(
+    const gfx::Size& new_size,
+    float device_scale_factor,
+    cc::Layer* layer) {
+  if (buffer_size_ != new_size) {
+    buffer_size_ = new_size;
+    // The container size is in DIP, so is the layer size.
+    // Buffer size is in physical pixels, so we need to adjust
+    // it by the device scale factor.
+    gfx::Size device_scale_adjusted_size = gfx::ToFlooredSize(
+        gfx::ScaleSize(buffer_size_, 1.0f / device_scale_factor));
+    layer->SetBounds(device_scale_adjusted_size);
+  }
+}
+
 // If we have a mailbox that was freed up from the compositor,
 // but we are not expected to return it to the guest renderer
 // via an ACK, we should free it because we now own it.
@@ -95,17 +124,24 @@
     const std::string& mailbox_name,
     int gpu_route_id,
     int gpu_host_id,
-    unsigned sync_point) {
+    unsigned sync_point,
+    bool lost_resource) {
+  if (lost_resource) {
+    // Recurse with an empty mailbox if the one being released was lost.
+    MailboxReleased(std::string(), gpu_route_id, gpu_host_id, 0, false);
+    return;
+  }
+
   // This means the GPU process crashed and we have nothing further to do.
   // Nobody is expecting an ACK and the buffer doesn't need to be deleted
   // because it went away with the GPU process.
-  if (last_gpu_host_id_ != gpu_host_id)
+  if (last_host_id_ != gpu_host_id)
     return;
 
   // This means the guest crashed.
   // Either ACK the last buffer, so texture transport could
   // be destroyed of delete the mailbox if nobody wants it back.
-  if (last_gpu_route_id_ != gpu_route_id) {
+  if (last_route_id_ != gpu_route_id) {
     if (!ack_pending_for_crashed_guest_) {
       FreeMailboxMemory(mailbox_name, sync_point);
     } else {
@@ -148,6 +184,7 @@
   container_ = NULL;
 
   texture_layer_ = NULL;
+  delegated_layer_ = NULL;
   background_layer_ = NULL;
   web_layer_.reset();
 }
@@ -158,29 +195,38 @@
     int gpu_route_id,
     int gpu_host_id,
     float device_scale_factor) {
+  DCHECK(!delegated_layer_);
   // If the guest crashed but the GPU process didn't, we may still have
   // a transport surface waiting on an ACK, which we must send to
   // avoid leaking.
-  if (last_gpu_route_id_ != gpu_route_id && last_gpu_host_id_ == gpu_host_id)
+  if (last_route_id_ != gpu_route_id && last_host_id_ == gpu_host_id)
     ack_pending_for_crashed_guest_ = ack_pending_;
 
   // If these mismatch, we are either just starting up, GPU process crashed or
   // guest renderer crashed.
   // In this case, we are communicating with a new image transport
   // surface and must ACK with the new ID's and an empty mailbox.
-  if (last_gpu_route_id_ != gpu_route_id || last_gpu_host_id_ != gpu_host_id)
+  if (last_route_id_ != gpu_route_id || last_host_id_ != gpu_host_id)
     last_mailbox_valid_ = false;
 
-  last_gpu_route_id_ = gpu_route_id;
-  last_gpu_host_id_ = gpu_host_id;
+  last_route_id_ = gpu_route_id;
+  last_host_id_ = gpu_host_id;
 
   ack_pending_ = true;
   // Browser plugin getting destroyed, do a fast ACK.
-  if (!texture_layer_) {
-    MailboxReleased(mailbox_name, gpu_route_id, gpu_host_id, 0);
+  if (!background_layer_) {
+    MailboxReleased(mailbox_name, gpu_route_id, gpu_host_id, 0, false);
     return;
   }
 
+  if (!texture_layer_) {
+    texture_layer_ = cc::TextureLayer::CreateForMailbox(NULL);
+    texture_layer_->SetIsDrawable(true);
+    texture_layer_->SetContentsOpaque(true);
+
+    background_layer_->AddChild(texture_layer_);
+  }
+
   // The size of browser plugin container is not always equal to the size
   // of the buffer that arrives here. This could be for a number of reasons,
   // including autosize and a resize in progress.
@@ -191,19 +237,13 @@
   // when a new buffer arrives.
   // Visually, this will either display a smaller part of the buffer
   // or introduce a gutter around it.
-  if (buffer_size_ != size) {
-    buffer_size_ = size;
-    // The container size is in DIP, so is the layer size.
-    // Buffer size is in physical pixels, so we need to adjust
-    // it by the device scale factor.
-    gfx::Size device_scale_adjusted_size = gfx::ToFlooredSize(
-        gfx::ScaleSize(buffer_size_, 1.0f / device_scale_factor));
-    texture_layer_->SetBounds(device_scale_adjusted_size);
-  }
+  CheckSizeAndAdjustLayerBounds(size,
+                                device_scale_factor,
+                                texture_layer_.get());
 
   bool current_mailbox_valid = !mailbox_name.empty();
   if (!last_mailbox_valid_) {
-    MailboxReleased(std::string(), gpu_route_id, gpu_host_id, 0);
+    MailboxReleased(std::string(), gpu_route_id, gpu_host_id, 0, false);
     if (!current_mailbox_valid)
       return;
   }
@@ -222,9 +262,39 @@
   last_mailbox_valid_ = current_mailbox_valid;
 }
 
+void BrowserPluginCompositingHelper::OnCompositorFrameSwapped(
+    scoped_ptr<cc::CompositorFrame> frame,
+    int route_id,
+    int host_id) {
+  DCHECK(!texture_layer_);
+  if (!delegated_layer_) {
+    delegated_layer_ = cc::DelegatedRendererLayer::Create();
+    delegated_layer_->SetIsDrawable(true);
+    delegated_layer_->SetContentsOpaque(true);
+
+    background_layer_->AddChild(delegated_layer_);
+  }
+
+  cc::DelegatedFrameData *frame_data = frame->delegated_frame_data.get();
+  if (!frame_data)
+    return;
+
+  CheckSizeAndAdjustLayerBounds(
+      frame_data->render_pass_list.back()->output_rect.size(),
+      frame->metadata.device_scale_factor,
+      delegated_layer_.get());
+
+  delegated_layer_->SetFrameData(frame->delegated_frame_data.Pass());
+  last_route_id_ = route_id;
+  last_host_id_ = host_id;
+  ack_pending_ = true;
+}
+
 void BrowserPluginCompositingHelper::UpdateVisibility(bool visible) {
   if (texture_layer_)
     texture_layer_->SetIsDrawable(visible);
+  if (delegated_layer_)
+    delegated_layer_->SetIsDrawable(visible);
 }
 
 }  // namespace content
diff --git a/content/renderer/browser_plugin/browser_plugin_compositing_helper.h b/content/renderer/browser_plugin/browser_plugin_compositing_helper.h
index 998b739..b323aae 100644
--- a/content/renderer/browser_plugin/browser_plugin_compositing_helper.h
+++ b/content/renderer/browser_plugin/browser_plugin_compositing_helper.h
@@ -13,8 +13,11 @@
 #include "ui/gfx/size.h"
 
 namespace cc {
+class CompositorFrame;
+class Layer;
 class SolidColorLayer;
 class TextureLayer;
+class DelegatedRendererLayer;
 }
 
 namespace WebKit {
@@ -33,6 +36,7 @@
                                  BrowserPluginManager* manager,
                                  int instance_id,
                                  int host_routing_id);
+  void DidCommitCompositorFrame();
   void EnableCompositing(bool);
   void OnContainerDestroy();
   void OnBuffersSwapped(const gfx::Size& size,
@@ -40,22 +44,29 @@
                         int gpu_route_id,
                         int gpu_host_id,
                         float device_scale_factor);
+  void OnCompositorFrameSwapped(scoped_ptr<cc::CompositorFrame> frame,
+                                int route_id,
+                                int host_id);
   void UpdateVisibility(bool);
  protected:
   // Friend RefCounted so that the dtor can be non-public.
   friend class base::RefCounted<BrowserPluginCompositingHelper>;
  private:
   ~BrowserPluginCompositingHelper();
+  void CheckSizeAndAdjustLayerBounds(const gfx::Size& new_size,
+                                     float device_scale_factor,
+                                     cc::Layer* layer);
   void FreeMailboxMemory(const std::string& mailbox_name,
                          unsigned sync_point);
   void MailboxReleased(const std::string& mailbox_name,
                        int gpu_route_id,
                        int gpu_host_id,
-                       unsigned sync_point);
+                       unsigned sync_point,
+                       bool lost_resource);
   int instance_id_;
   int host_routing_id_;
-  int last_gpu_route_id_;
-  int last_gpu_host_id_;
+  int last_route_id_;
+  int last_host_id_;
   bool last_mailbox_valid_;
   bool ack_pending_;
   bool ack_pending_for_crashed_guest_;
@@ -64,6 +75,7 @@
 
   scoped_refptr<cc::SolidColorLayer> background_layer_;
   scoped_refptr<cc::TextureLayer> texture_layer_;
+  scoped_refptr<cc::DelegatedRendererLayer> delegated_layer_;
   scoped_ptr<WebKit::WebLayer> web_layer_;
   WebKit::WebPluginContainer* container_;
 
diff --git a/content/renderer/browser_plugin/browser_plugin_manager.cc b/content/renderer/browser_plugin/browser_plugin_manager.cc
index c7458e1..e960120 100644
--- a/content/renderer/browser_plugin/browser_plugin_manager.cc
+++ b/content/renderer/browser_plugin/browser_plugin_manager.cc
@@ -45,6 +45,14 @@
   return instances_.Lookup(instance_id);
 }
 
+void BrowserPluginManager::UpdateDeviceScaleFactor(float device_scale_factor) {
+  IDMap<BrowserPlugin>::iterator iter(&instances_);
+  while (!iter.IsAtEnd()) {
+    iter.GetCurrentValue()->UpdateDeviceScaleFactor(device_scale_factor);
+    iter.Advance();
+  }
+}
+
 void BrowserPluginManager::UpdateFocusState() {
   IDMap<BrowserPlugin>::iterator iter(&instances_);
   while (!iter.IsAtEnd()) {
diff --git a/content/renderer/browser_plugin/browser_plugin_manager.h b/content/renderer/browser_plugin/browser_plugin_manager.h
index a4a59da..a0fea21 100644
--- a/content/renderer/browser_plugin/browser_plugin_manager.h
+++ b/content/renderer/browser_plugin/browser_plugin_manager.h
@@ -53,6 +53,7 @@
   void AddBrowserPlugin(int instance_id, BrowserPlugin* browser_plugin);
   void RemoveBrowserPlugin(int instance_id);
   BrowserPlugin* GetBrowserPlugin(int instance_id) const;
+  void UpdateDeviceScaleFactor(float device_scale_factor);
   void UpdateFocusState();
   RenderViewImpl* render_view() const { return render_view_; }
 
diff --git a/content/renderer/browser_plugin/browser_plugin_manager_impl.cc b/content/renderer/browser_plugin/browser_plugin_manager_impl.cc
index cbe7245..11b7be0 100644
--- a/content/renderer/browser_plugin/browser_plugin_manager_impl.cc
+++ b/content/renderer/browser_plugin/browser_plugin_manager_impl.cc
@@ -67,13 +67,21 @@
   return handled;
 }
 
+void BrowserPluginManagerImpl::DidCommitCompositorFrame() {
+  IDMap<BrowserPlugin>::iterator iter(&instances_);
+  while (!iter.IsAtEnd()) {
+    iter.GetCurrentValue()->DidCommitCompositorFrame();
+    iter.Advance();
+  }
+}
+
 void BrowserPluginManagerImpl::OnAllocateInstanceIDACK(
     const IPC::Message& message, int request_id, int instance_id) {
   BrowserPlugin* plugin =
       pending_allocate_instance_id_requests_.Lookup(request_id);
   pending_allocate_instance_id_requests_.Remove(request_id);
   if (plugin)
-    plugin->SetInstanceID(instance_id, true /* new_guest */);
+    plugin->Attach(instance_id);
 }
 
 void BrowserPluginManagerImpl::OnPluginAtPositionRequest(
diff --git a/content/renderer/browser_plugin/browser_plugin_manager_impl.h b/content/renderer/browser_plugin/browser_plugin_manager_impl.h
index 2496474..2ac49ab 100644
--- a/content/renderer/browser_plugin/browser_plugin_manager_impl.h
+++ b/content/renderer/browser_plugin/browser_plugin_manager_impl.h
@@ -34,6 +34,8 @@
 
   // RenderViewObserver override. Call on render thread.
   virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+  virtual void DidCommitCompositorFrame() OVERRIDE;
+
  private:
   virtual ~BrowserPluginManagerImpl();
 
diff --git a/content/renderer/browser_plugin/mock_browser_plugin_manager.cc b/content/renderer/browser_plugin/mock_browser_plugin_manager.cc
index 7c314c4..3759535 100644
--- a/content/renderer/browser_plugin/mock_browser_plugin_manager.cc
+++ b/content/renderer/browser_plugin/mock_browser_plugin_manager.cc
@@ -30,7 +30,7 @@
 void MockBrowserPluginManager::AllocateInstanceID(
     BrowserPlugin* browser_plugin) {
   int instance_id = ++browser_plugin_counter_;
-  MessageLoop::current()->PostTask(
+  base::MessageLoop::current()->PostTask(
       FROM_HERE,
       base::Bind(&MockBrowserPluginManager::AllocateInstanceIDACK,
                  this,
@@ -41,7 +41,7 @@
 void MockBrowserPluginManager::AllocateInstanceIDACK(
     BrowserPlugin* browser_plugin,
     int instance_id) {
-  browser_plugin->SetInstanceID(instance_id, true);
+  browser_plugin->Attach(instance_id);
 }
 
 bool MockBrowserPluginManager::Send(IPC::Message* msg) {
@@ -50,7 +50,7 @@
   // through this function messages, messages with reply and reply messages.
   // We can only handle one synchronous message at a time.
   if (msg->is_reply()) {
-    if (reply_deserializer_.get()) {
+    if (reply_deserializer_) {
       reply_deserializer_->SerializeOutputParameters(*msg);
       reply_deserializer_.reset();
     }
diff --git a/content/renderer/cpp_bound_class_unittest.cc b/content/renderer/cpp_bound_class_unittest.cc
new file mode 100644
index 0000000..df2cd22
--- /dev/null
+++ b/content/renderer/cpp_bound_class_unittest.cc
@@ -0,0 +1,229 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Tests for CppBoundClass, in conjunction with CppBindingExample.  Binds
+// a CppBindingExample class into JavaScript in a custom test shell and tests
+// the binding from the outside by loading JS into the shell.
+
+#include "base/utf_string_conversions.h"
+#include "content/public/renderer/render_view_observer.h"
+#include "content/public/test/render_view_test.h"
+#include "third_party/WebKit/Source/Platform/chromium/public/WebURLRequest.h"
+#include "webkit/glue/cpp_binding_example.h"
+#include "webkit/glue/webkit_glue.h"
+
+using webkit_glue::CppArgumentList;
+using webkit_glue::CppBindingExample;
+using webkit_glue::CppVariant;
+
+namespace content {
+
+class CppBindingExampleSubObject : public CppBindingExample {
+ public:
+  CppBindingExampleSubObject() {
+    sub_value_.Set("sub!");
+    BindProperty("sub_value", &sub_value_);
+  }
+ private:
+  CppVariant sub_value_;
+};
+
+
+class CppBindingExampleWithOptionalFallback : public CppBindingExample {
+ public:
+  CppBindingExampleWithOptionalFallback() {
+    BindProperty("sub_object", sub_object_.GetAsCppVariant());
+  }
+
+  void set_fallback_method_enabled(bool state) {
+    BindFallbackCallback(state ?
+        base::Bind(&CppBindingExampleWithOptionalFallback::fallbackMethod,
+                   base::Unretained(this))
+        : CppBoundClass::Callback());
+  }
+
+  // The fallback method does nothing, but because of it the JavaScript keeps
+  // running when a nonexistent method is called on an object.
+  void fallbackMethod(const CppArgumentList& args, CppVariant* result) {
+  }
+
+ private:
+  CppBindingExampleSubObject sub_object_;
+};
+
+class TestObserver : public RenderViewObserver {
+ public:
+  explicit TestObserver(RenderView* render_view)
+      : RenderViewObserver(render_view) {}
+  virtual void DidClearWindowObject(WebKit::WebFrame* frame) OVERRIDE {
+    example_bound_class_.BindToJavascript(frame, "example");
+  }
+  void set_fallback_method_enabled(bool use_fallback) {
+    example_bound_class_.set_fallback_method_enabled(use_fallback);
+  }
+ private:
+  CppBindingExampleWithOptionalFallback example_bound_class_;
+};
+
+class CppBoundClassTest : public RenderViewTest {
+ public:
+  CppBoundClassTest() {}
+
+  virtual void SetUp() OVERRIDE {
+    RenderViewTest::SetUp();
+    observer_.reset(new TestObserver(view_));
+    observer_->set_fallback_method_enabled(useFallback());
+
+    WebKit::WebURLRequest url_request;
+    url_request.initialize();
+    url_request.setURL(GURL("about:blank"));
+
+    GetMainFrame()->loadRequest(url_request);
+    ProcessPendingMessages();
+  }
+
+  // Executes the specified JavaScript and checks that the resulting document
+  // text is empty.
+  void CheckJavaScriptFailure(const std::string& javascript) {
+    ExecuteJavaScript(javascript.c_str());
+    EXPECT_EQ("", UTF16ToASCII(webkit_glue::DumpDocumentText(GetMainFrame())));
+  }
+
+  void CheckTrue(const std::string& expression) {
+    int was_page_a = -1;
+    string16 check_page_a =
+        ASCIIToUTF16(std::string("Number(") + expression + ")");
+    EXPECT_TRUE(ExecuteJavaScriptAndReturnIntValue(check_page_a, &was_page_a));
+    EXPECT_EQ(1, was_page_a);
+  }
+
+ protected:
+  virtual bool useFallback() {
+    return false;
+  }
+
+ private:
+  scoped_ptr<TestObserver> observer_;
+};
+
+class CppBoundClassWithFallbackMethodTest : public CppBoundClassTest {
+ protected:
+  virtual bool useFallback() OVERRIDE {
+    return true;
+  }
+};
+
+// Ensures that the example object has been bound to JS.
+TEST_F(CppBoundClassTest, ObjectExists) {
+  CheckTrue("typeof window.example == 'object'");
+
+  // An additional check to test our test.
+  CheckTrue("typeof window.invalid_object == 'undefined'");
+}
+
+TEST_F(CppBoundClassTest, PropertiesAreInitialized) {
+  CheckTrue("example.my_value == 10");
+
+  CheckTrue("example.my_other_value == 'Reinitialized!'");
+}
+
+TEST_F(CppBoundClassTest, SubOject) {
+  CheckTrue("typeof window.example.sub_object == 'object'");
+
+  CheckTrue("example.sub_object.sub_value == 'sub!'");
+}
+
+TEST_F(CppBoundClassTest, SetAndGetProperties) {
+  // The property on the left will be set to the value on the right, then
+  // checked to make sure it holds that same value.
+  static const std::string tests[] = {
+    "example.my_value", "7",
+    "example.my_value", "'test'",
+    "example.my_other_value", "3.14",
+    "example.my_other_value", "false",
+    "" // Array end marker: insert additional test pairs before this.
+  };
+
+  for (int i = 0; tests[i] != ""; i += 2) {
+    std::string left = tests[i];
+    std::string right = tests[i + 1];
+    // left = right;
+    std::string js = left;
+    js.append(" = ");
+    js.append(right);
+    js.append(";");
+    ExecuteJavaScript(js.c_str());
+    std::string expression = left;
+    expression += " == ";
+    expression += right;
+    CheckTrue(expression);
+  }
+}
+
+TEST_F(CppBoundClassTest, SetAndGetPropertiesWithCallbacks) {
+  // TODO(dglazkov): fix NPObject issues around failing property setters and
+  // getters and add tests for situations when GetProperty or SetProperty fail.
+  ExecuteJavaScript("example.my_value_with_callback = 10;");
+  CheckTrue("example.my_value_with_callback == 10");
+
+  ExecuteJavaScript("example.my_value_with_callback = 11;");
+  CheckTrue("example.my_value_with_callback == 11");
+
+  CheckTrue("example.same == 42");
+
+  ExecuteJavaScript("example.same = 24;");
+  CheckTrue("example.same == 42");
+}
+
+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",
+    "example.echoValue(13) == 13",
+    "example.echoValue(2.718) == 2.718",
+    "example.echoValue('yes') == 'yes'",
+    "example.echoValue() == null",     // Too few arguments
+
+    "example.echoType(false) == true",
+    "example.echoType(19) == 3.14159",
+    "example.echoType(9.876) == 3.14159",
+    "example.echoType('test string') == 'Success!'",
+    "example.echoType() == null",      // Too few arguments
+
+    // Comparing floats that aren't integer-valued is usually problematic due
+    // to rounding, but exact powers of 2 should also be safe.
+    "example.plus(2.5, 18.0) == 20.5",
+    "example.plus(2, 3.25) == 5.25",
+    "example.plus(2, 3) == 5",
+    "example.plus() == null",             // Too few arguments
+    "example.plus(1) == null",            // Too few arguments
+    "example.plus(1, 'test') == null",    // Wrong argument type
+    "example.plus('test', 2) == null",    // Wrong argument type
+    "example.plus('one', 'two') == null", // Wrong argument type
+    "" // Array end marker: insert additional test pairs before this.
+  };
+
+  for (int i = 0; tests[i] != ""; i++)
+    CheckTrue(tests[i]);
+
+  ExecuteJavaScript("example.my_value = 3.25; example.my_other_value = 1.25;");
+  CheckTrue("example.plus(example.my_value, example.my_other_value) == 4.5");
+}
+
+// Tests that invoking a nonexistent method with no fallback method stops the
+// script's execution
+TEST_F(CppBoundClassTest,
+       InvokeNonexistentMethodNoFallback) {
+  std::string js = "example.nonExistentMethod();document.writeln('SUCCESS');";
+  CheckJavaScriptFailure(js);
+}
+
+// Ensures existent methods can be invoked successfully when the fallback method
+// is used
+TEST_F(CppBoundClassWithFallbackMethodTest,
+       InvokeExistentMethodsWithFallback) {
+  CheckTrue("example.echoValue(34) == 34");
+}
+
+}  // namespace content
diff --git a/content/renderer/date_time_formatter.cc b/content/renderer/date_time_formatter.cc
index d3c16e3..1adb0de 100644
--- a/content/renderer/date_time_formatter.cc
+++ b/content/renderer/date_time_formatter.cc
@@ -95,7 +95,7 @@
   UErrorCode success = U_ZERO_ERROR;
   if (year_ == 0 && month_ == 0 && day_ == 0 &&
       hour_ == 0 && minute_ == 0 && second_ == 0) {
-    return "";
+    return std::string();
   }
 
   std::string result;
@@ -113,7 +113,7 @@
       return result;
   }
   LOG(WARNING) << "Calendar not created: error " <<  success;
-  return "";
+  return std::string();
 }
 
 void DateTimeFormatter::ExtractType(
diff --git a/content/renderer/devtools/devtools_agent.cc b/content/renderer/devtools/devtools_agent.cc
index 868f5ec..674cbc5 100644
--- a/content/renderer/devtools/devtools_agent.cc
+++ b/content/renderer/devtools/devtools_agent.cc
@@ -47,19 +47,17 @@
 class WebKitClientMessageLoopImpl
     : public WebDevToolsAgentClient::WebKitClientMessageLoop {
  public:
-  WebKitClientMessageLoopImpl() : message_loop_(MessageLoop::current()) { }
-  virtual ~WebKitClientMessageLoopImpl() {
-    message_loop_ = NULL;
-  }
+  WebKitClientMessageLoopImpl() : message_loop_(base::MessageLoop::current()) {}
+  virtual ~WebKitClientMessageLoopImpl() { message_loop_ = NULL; }
   virtual void run() {
-    MessageLoop::ScopedNestableTaskAllower allow(message_loop_);
+    base::MessageLoop::ScopedNestableTaskAllower allow(message_loop_);
     message_loop_->Run();
   }
   virtual void quitNow() {
     message_loop_->QuitNow();
   }
  private:
-  MessageLoop* message_loop_;
+  base::MessageLoop* message_loop_;
 };
 
 typedef std::map<int, DevToolsAgent*> IdToAgentMap;
@@ -69,7 +67,9 @@
 } //  namespace
 
 DevToolsAgent::DevToolsAgent(RenderViewImpl* render_view)
-    : RenderViewObserver(render_view), is_attached_(false) {
+    : RenderViewObserver(render_view),
+      is_attached_(false),
+      is_devtools_client_(false) {
   g_agent_for_routing_id.Get()[routing_id()] = this;
 
   render_view->webview()->setDevToolsAgentClient(this);
@@ -135,7 +135,13 @@
 void DevToolsAgent::setTraceEventCallback(TraceEventCallback cb) {
   TraceLog* trace_log = TraceLog::GetInstance();
   trace_log->SetEventCallback(cb);
-  trace_log->SetEnabled(!!cb, TraceLog::RECORD_UNTIL_FULL);
+  if (!!cb) {
+    trace_log->SetEnabled(base::debug::CategoryFilter(
+        base::debug::CategoryFilter::kDefaultCategoryFilterString),
+        TraceLog::RECORD_UNTIL_FULL);
+  } else {
+    trace_log->SetDisabled();
+  }
 }
 
 #if defined(USE_TCMALLOC) && !defined(OS_WIN)
@@ -237,6 +243,10 @@
 }
 
 void DevToolsAgent::OnSetupDevToolsClient() {
+  // We only want to register once per render view.
+  if (is_devtools_client_)
+    return;
+  is_devtools_client_ = true;
   new DevToolsClient(static_cast<RenderViewImpl*>(render_view()));
 }
 
diff --git a/content/renderer/devtools/devtools_agent.h b/content/renderer/devtools/devtools_agent.h
index e3a3bdd..7926f44 100644
--- a/content/renderer/devtools/devtools_agent.h
+++ b/content/renderer/devtools/devtools_agent.h
@@ -65,6 +65,7 @@
   void OnSetupDevToolsClient();
 
   bool is_attached_;
+  bool is_devtools_client_;
 
   DISALLOW_COPY_AND_ASSIGN(DevToolsAgent);
 };
diff --git a/content/renderer/devtools/devtools_agent_filter.cc b/content/renderer/devtools/devtools_agent_filter.cc
index 7a4e90b..76062d9 100644
--- a/content/renderer/devtools/devtools_agent_filter.cc
+++ b/content/renderer/devtools/devtools_agent_filter.cc
@@ -42,9 +42,8 @@
 
 DevToolsAgentFilter::DevToolsAgentFilter()
     : message_handled_(false),
-      render_thread_loop_(MessageLoop::current()),
-      current_routing_id_(0) {
-}
+      render_thread_loop_(base::MessageLoop::current()),
+      current_routing_id_(0) {}
 
 bool DevToolsAgentFilter::OnMessageReceived(const IPC::Message& message) {
   // Dispatch debugger commands directly from IO.
diff --git a/content/renderer/devtools/devtools_agent_filter.h b/content/renderer/devtools/devtools_agent_filter.h
index 9e4f8ae..e7f7861 100644
--- a/content/renderer/devtools/devtools_agent_filter.h
+++ b/content/renderer/devtools/devtools_agent_filter.h
@@ -9,9 +9,12 @@
 
 #include "ipc/ipc_channel_proxy.h"
 
-class MessageLoop;
 struct DevToolsMessageData;
 
+namespace base {
+class MessageLoop;
+}
+
 namespace content {
 
 // DevToolsAgentFilter is registered as an IPC filter in order to be able to
@@ -37,7 +40,7 @@
   void OnDispatchOnInspectorBackend(const std::string& message);
 
   bool message_handled_;
-  MessageLoop* render_thread_loop_;
+  base::MessageLoop* render_thread_loop_;
   int current_routing_id_;
 
   DISALLOW_COPY_AND_ASSIGN(DevToolsAgentFilter);
diff --git a/content/renderer/devtools/devtools_client.cc b/content/renderer/devtools/devtools_client.cc
index 7ec522c..5f760e6 100644
--- a/content/renderer/devtools/devtools_client.cc
+++ b/content/renderer/devtools/devtools_client.cc
@@ -9,12 +9,14 @@
 #include "base/utf_string_conversions.h"
 #include "content/common/devtools_messages.h"
 #include "content/public/common/content_switches.h"
+#include "content/public/common/url_constants.h"
 #include "content/renderer/render_thread_impl.h"
 #include "content/renderer/render_view_impl.h"
 #include "third_party/WebKit/Source/Platform/chromium/public/WebFloatPoint.h"
 #include "third_party/WebKit/Source/Platform/chromium/public/WebString.h"
 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDevToolsFrontend.h"
 #include "ui/base/ui_base_switches.h"
+#include "webkit/appcache/appcache_interfaces.h"
 
 using WebKit::WebDevToolsFrontend;
 using WebKit::WebString;
@@ -35,6 +37,7 @@
           render_view->webview(),
           this,
           ASCIIToUTF16(command_line.GetSwitchValueASCII(switches::kLang))));
+  appcache::AddSupportedScheme(chrome::kChromeDevToolsScheme);
 }
 
 DevToolsClient::~DevToolsClient() {
diff --git a/content/renderer/do_not_track_bindings.cc b/content/renderer/do_not_track_bindings.cc
deleted file mode 100644
index 0c2731b..0000000
--- a/content/renderer/do_not_track_bindings.cc
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/renderer/do_not_track_bindings.h"
-
-#include "content/renderer/render_view_impl.h"
-#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
-#include "v8/include/v8.h"
-
-using WebKit::WebFrame;
-
-namespace content {
-
-namespace {
-
-v8::Handle<v8::Value> GetDoNotTrack(v8::Local<v8::String> property,
-                                    const v8::AccessorInfo& info) {
-  WebFrame* frame = WebFrame::frameForCurrentContext();
-  if (!frame)
-    return v8::Null();
-  RenderViewImpl* view = RenderViewImpl::FromWebView(frame->view());
-  if (!view)
-    return v8::Null();
-  if (view->enable_do_not_track())
-    return v8::String::New("1");
-  return v8::Null();
-}
-
-}  // namespace
-
-void InjectDoNotTrackBindings(WebFrame* frame) {
-  v8::HandleScope handle_scope;
-
-  v8::Handle<v8::Context> v8_context = frame->mainWorldScriptContext();
-  if (v8_context.IsEmpty())
-    return;
-
-  v8::Context::Scope scope(v8_context);
-
-  v8::Handle<v8::Object> global = v8_context->Global();
-  v8::Handle<v8::Object> navigator =
-      global->Get(v8::String::New("navigator"))->ToObject();
-  if (navigator.IsEmpty())
-    return;
-  navigator->SetAccessor(v8::String::New("doNotTrack"), GetDoNotTrack);
-}
-
-}  // namespace content
diff --git a/content/renderer/do_not_track_bindings.h b/content/renderer/do_not_track_bindings.h
deleted file mode 100644
index cc0edff..0000000
--- a/content/renderer/do_not_track_bindings.h
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_RENDERER_DO_NOT_TRACK_BINDINGS_H_
-#define CONTENT_RENDERER_DO_NOT_TRACK_BINDINGS_H_
-
-namespace WebKit {
-class WebFrame;
-}
-
-namespace content {
-void InjectDoNotTrackBindings(WebKit::WebFrame* frame);
-}  // namespace content
-
-#endif  // CONTENT_RENDERER_DO_NOT_TRACK_BINDINGS_H_
diff --git a/content/renderer/dom_operations_browsertest.cc b/content/renderer/dom_operations_browsertest.cc
new file mode 100644
index 0000000..0d333a5
--- /dev/null
+++ b/content/renderer/dom_operations_browsertest.cc
@@ -0,0 +1,139 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/bind.h"
+#include "base/command_line.h"
+#include "base/files/file_path.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/common/content_switches.h"
+#include "content/public/renderer/render_view.h"
+#include "content/shell/shell.h"
+#include "content/test/content_browser_test.h"
+#include "content/test/content_browser_test_utils.h"
+#include "net/base/net_util.h"
+#include "webkit/glue/dom_operations.h"
+
+namespace content {
+
+class DomOperationsTests : public ContentBrowserTest {
+ public:
+  virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
+    command_line->AppendSwitch(switches::kSingleProcess);
+#if defined(OS_WIN) && defined(USE_AURA)
+    // Don't want to try to create a GPU process.
+    command_line->AppendSwitch(switches::kDisableAcceleratedCompositing);
+#endif
+  }
+
+  // Test function GetAllSavableResourceLinksForCurrentPage with a web page.
+  // We expect result of GetAllSavableResourceLinksForCurrentPage exactly
+  // matches expected_resources_set.
+  void GetSavableResourceLinksForPage(
+      const base::FilePath& page_file_path,
+      const std::set<GURL>& expected_resources_set) {
+    // Convert local file path to file URL.
+    GURL file_url = net::FilePathToFileURL(page_file_path);
+    // Load the test file.
+    NavigateToURL(shell(), file_url);
+
+    PostTaskToInProcessRendererAndWait(
+        base::Bind(&DomOperationsTests::CheckResources, base::Unretained(this),
+                   page_file_path, expected_resources_set, file_url,
+                   shell()->web_contents()->GetRoutingID()));
+  }
+
+  void CheckResources(const base::FilePath& page_file_path,
+                      const std::set<GURL>& expected_resources_set,
+                      const GURL& file_url,
+                      int render_view_id) {
+    // Get all savable resource links for the page.
+    std::vector<GURL> resources_list;
+    std::vector<GURL> referrer_urls_list;
+    std::vector<WebKit::WebReferrerPolicy> referrer_policies_list;
+    std::vector<GURL> frames_list;
+    webkit_glue::SavableResourcesResult result(&resources_list,
+                                               &referrer_urls_list,
+                                               &referrer_policies_list,
+                                               &frames_list);
+
+    const char* savable_schemes[] = {
+      "http",
+      "https",
+      "file",
+      NULL
+    };
+
+    RenderView* render_view = RenderView::FromRoutingID(render_view_id);
+
+    ASSERT_TRUE(webkit_glue::GetAllSavableResourceLinksForCurrentPage(
+        render_view->GetWebView(), file_url, &result, savable_schemes));
+    // Check all links of sub-resource
+    for (std::vector<GURL>::const_iterator cit = resources_list.begin();
+         cit != resources_list.end(); ++cit) {
+      ASSERT_TRUE(expected_resources_set.find(*cit) !=
+                  expected_resources_set.end());
+    }
+    // Check all links of frame.
+    for (std::vector<GURL>::const_iterator cit = frames_list.begin();
+         cit != frames_list.end(); ++cit) {
+      ASSERT_TRUE(expected_resources_set.find(*cit) !=
+                  expected_resources_set.end());
+    }
+  }
+};
+
+// Test function GetAllSavableResourceLinksForCurrentPage with a web page
+// which has valid savable resource links.
+IN_PROC_BROWSER_TEST_F(DomOperationsTests,
+                       GetSavableResourceLinksWithPageHasValidLinks) {
+  std::set<GURL> expected_resources_set;
+
+  const char* expected_sub_resource_links[] = {
+    "file:///c:/yt/css/base_all-vfl36460.css",
+    "file:///c:/yt/js/base_all_with_bidi-vfl36451.js",
+    "file:///c:/yt/img/pixel-vfl73.gif"
+  };
+  const char* expected_frame_links[] = {
+    "youtube_1.htm",
+    "youtube_2.htm"
+  };
+  // Add all expected links of sub-resource to expected set.
+  for (size_t i = 0; i < arraysize(expected_sub_resource_links); ++i)
+    expected_resources_set.insert(GURL(expected_sub_resource_links[i]));
+  // Add all expected links of frame to expected set.
+  for (size_t i = 0; i < arraysize(expected_frame_links); ++i) {
+    const base::FilePath expected_frame_url =
+        GetTestFilePath("dom_serializer", expected_frame_links[i]);
+    expected_resources_set.insert(
+        net::FilePathToFileURL(expected_frame_url));
+  }
+
+  base::FilePath page_file_path =
+      GetTestFilePath("dom_serializer", "youtube_1.htm");
+  GetSavableResourceLinksForPage(page_file_path, expected_resources_set);
+}
+
+// Test function GetAllSavableResourceLinksForCurrentPage with a web page
+// which does not have valid savable resource links.
+IN_PROC_BROWSER_TEST_F(DomOperationsTests,
+                       GetSavableResourceLinksWithPageHasInvalidLinks) {
+  std::set<GURL> expected_resources_set;
+
+  const char* expected_frame_links[] = {
+    "youtube_2.htm"
+  };
+  // Add all expected links of frame to expected set.
+  for (size_t i = 0; i < arraysize(expected_frame_links); ++i) {
+    base::FilePath expected_frame_url =
+        GetTestFilePath("dom_serializer", expected_frame_links[i]);
+    expected_resources_set.insert(
+        net::FilePathToFileURL(expected_frame_url));
+  }
+
+  base::FilePath page_file_path =
+      GetTestFilePath("dom_serializer", "youtube_2.htm");
+  GetSavableResourceLinksForPage(page_file_path, expected_resources_set);
+}
+
+}  // namespace content
diff --git a/content/renderer/dom_serializer_browsertest.cc b/content/renderer/dom_serializer_browsertest.cc
new file mode 100644
index 0000000..3df004d
--- /dev/null
+++ b/content/renderer/dom_serializer_browsertest.cc
@@ -0,0 +1,1019 @@
+// Copyright (c) 2010 The Chromium Authors. 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"
+#include "base/command_line.h"
+#include "base/compiler_specific.h"
+#include "base/file_util.h"
+#include "base/files/file_path.h"
+#include "base/hash_tables.h"
+#include "base/string_util.h"
+#include "base/utf_string_conversions.h"
+#include "content/public/common/content_switches.h"
+#include "content/public/renderer/render_view.h"
+#include "content/public/renderer/render_view_observer.h"
+#include "content/public/test/test_utils.h"
+#include "content/shell/shell.h"
+#include "content/test/content_browser_test.h"
+#include "content/test/content_browser_test_utils.h"
+#include "net/base/net_util.h"
+#include "net/url_request/url_request_context.h"
+#include "third_party/WebKit/Source/Platform/chromium/public/WebCString.h"
+#include "third_party/WebKit/Source/Platform/chromium/public/WebData.h"
+#include "third_party/WebKit/Source/Platform/chromium/public/WebString.h"
+#include "third_party/WebKit/Source/Platform/chromium/public/WebURL.h"
+#include "third_party/WebKit/Source/Platform/chromium/public/WebVector.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/WebView.h"
+#include "webkit/base/file_path_string_conversions.h"
+#include "webkit/glue/dom_operations.h"
+
+using WebKit::WebCString;
+using WebKit::WebData;
+using WebKit::WebDocument;
+using WebKit::WebElement;
+using WebKit::WebFrame;
+using WebKit::WebNode;
+using WebKit::WebNodeCollection;
+using WebKit::WebNodeList;
+using WebKit::WebPageSerializer;
+using WebKit::WebPageSerializerClient;
+using WebKit::WebNode;
+using WebKit::WebString;
+using WebKit::WebURL;
+using WebKit::WebView;
+using WebKit::WebVector;
+
+namespace content {
+
+// Iterate recursively over sub-frames to find one with with a given url.
+WebFrame* FindSubFrameByURL(WebView* web_view, const GURL& url) {
+  if (!web_view->mainFrame())
+    return NULL;
+
+  std::vector<WebFrame*> stack;
+  stack.push_back(web_view->mainFrame());
+
+  while (!stack.empty()) {
+    WebFrame* current_frame = stack.back();
+    stack.pop_back();
+    if (GURL(current_frame->document().url()) == url)
+      return current_frame;
+    WebNodeCollection all = current_frame->document().all();
+    for (WebNode node = all.firstItem();
+         !node.isNull(); node = all.nextItem()) {
+      if (!node.isElementNode())
+        continue;
+      // Check frame tag and iframe tag
+      WebElement element = node.to<WebElement>();
+      if (!element.hasTagName("frame") && !element.hasTagName("iframe"))
+        continue;
+      WebFrame* sub_frame = WebFrame::fromFrameOwnerElement(element);
+      if (sub_frame)
+        stack.push_back(sub_frame);
+    }
+  }
+  return NULL;
+}
+
+// Helper function that test whether the first node in the doc is a doc type
+// node.
+bool HasDocType(const WebDocument& doc) {
+  WebNode node = doc.firstChild();
+  if (node.isNull())
+    return false;
+  return node.nodeType() == WebNode::DocumentTypeNode;
+}
+
+  // Helper function for checking whether input node is META tag. Return true
+// means it is META element, otherwise return false. The parameter charset_info
+// return actual charset info if the META tag has charset declaration.
+bool IsMetaElement(const WebNode& node, std::string& charset_info) {
+  if (!node.isElementNode())
+    return false;
+  const WebElement meta = node.toConst<WebElement>();
+  if (!meta.hasTagName("meta"))
+    return false;
+  charset_info.erase(0, charset_info.length());
+  // Check the META charset declaration.
+  WebString httpEquiv = meta.getAttribute("http-equiv");
+  if (LowerCaseEqualsASCII(httpEquiv, "content-type")) {
+    std::string content = meta.getAttribute("content").utf8();
+    int pos = content.find("charset", 0);
+    if (pos > -1) {
+      // Add a dummy charset declaration to charset_info, which indicates this
+      // META tag has charset declaration although we do not get correct value
+      // yet.
+      charset_info.append("has-charset-declaration");
+      int remaining_length = content.length() - pos - 7;
+      if (!remaining_length)
+        return true;
+      int start_pos = pos + 7;
+      // Find "=" symbol.
+      while (remaining_length--)
+        if (content[start_pos++] == L'=')
+          break;
+      // Skip beginning space.
+      while (remaining_length) {
+        if (content[start_pos] > 0x0020)
+          break;
+        ++start_pos;
+        --remaining_length;
+      }
+      if (!remaining_length)
+        return true;
+      int end_pos = start_pos;
+      // Now we find out the start point of charset info. Search the end point.
+      while (remaining_length--) {
+        if (content[end_pos] <= 0x0020 || content[end_pos] == L';')
+          break;
+        ++end_pos;
+      }
+      // Get actual charset info.
+      charset_info = content.substr(start_pos, end_pos - start_pos);
+      return true;
+    }
+  }
+  return true;
+}
+
+class LoadObserver : public RenderViewObserver {
+ public:
+  LoadObserver(RenderView* render_view, const base::Closure& quit_closure)
+      : RenderViewObserver(render_view),
+        quit_closure_(quit_closure) {}
+
+  virtual void DidFinishLoad(WebKit::WebFrame* frame) OVERRIDE {
+    if (frame == render_view()->GetWebView()->mainFrame())
+      quit_closure_.Run();
+  }
+
+ private:
+  base::Closure quit_closure_;
+};
+
+class DomSerializerTests : public ContentBrowserTest,
+                           public WebPageSerializerClient {
+ public:
+  DomSerializerTests()
+    : serialized_(false),
+      local_directory_name_(FILE_PATH_LITERAL("./dummy_files/")) {}
+
+  virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
+    command_line->AppendSwitch(switches::kSingleProcess);
+#if defined(OS_WIN) && defined(USE_AURA)
+    // Don't want to try to create a GPU process.
+    command_line->AppendSwitch(switches::kDisableAcceleratedCompositing);
+#endif
+  }
+
+  // DomSerializerDelegate.
+  virtual void didSerializeDataForFrame(const WebURL& frame_web_url,
+                                        const WebCString& data,
+                                        PageSerializationStatus status) {
+
+    GURL frame_url(frame_web_url);
+    // If the all frames are finished saving, check all finish status
+    if (status == WebPageSerializerClient::AllFramesAreFinished) {
+      SerializationFinishStatusMap::iterator it =
+          serialization_finish_status_.begin();
+      for (; it != serialization_finish_status_.end(); ++it)
+        ASSERT_TRUE(it->second);
+      serialized_ = true;
+      return;
+    }
+
+    // Check finish status of current frame.
+    SerializationFinishStatusMap::iterator it =
+        serialization_finish_status_.find(frame_url.spec());
+    // New frame, set initial status as false.
+    if (it == serialization_finish_status_.end())
+      serialization_finish_status_[frame_url.spec()] = false;
+
+    it = serialization_finish_status_.find(frame_url.spec());
+    ASSERT_TRUE(it != serialization_finish_status_.end());
+    // In process frame, finish status should be false.
+    ASSERT_FALSE(it->second);
+
+    // Add data to corresponding frame's content.
+    serialized_frame_map_[frame_url.spec()] += data.data();
+
+    // Current frame is completed saving, change the finish status.
+    if (status == WebPageSerializerClient::CurrentFrameIsFinished)
+      it->second = true;
+  }
+
+  bool HasSerializedFrame(const GURL& frame_url) {
+    return serialized_frame_map_.find(frame_url.spec()) !=
+           serialized_frame_map_.end();
+  }
+
+  const std::string& GetSerializedContentForFrame(
+      const GURL& frame_url) {
+    return serialized_frame_map_[frame_url.spec()];
+  }
+
+  RenderView* GetRenderView() {
+    // We could have the test on the UI thread get the WebContent's routing ID,
+    // but we know this will be the first RV so skip that and just hardcode it.
+    return RenderView::FromRoutingID(1);
+  }
+
+  WebView* GetWebView() {
+    return GetRenderView()->GetWebView();
+  }
+
+  WebFrame* GetMainFrame() {
+    return GetWebView()->mainFrame();
+  }
+
+  // Load web page according to input content and relative URLs within
+  // the document.
+  void LoadContents(const std::string& contents,
+                    const GURL& base_url,
+                    const WebString encoding_info) {
+    scoped_refptr<MessageLoopRunner> runner = new MessageLoopRunner;
+    LoadObserver observer(GetRenderView(), runner->QuitClosure());
+
+    // If input encoding is empty, use UTF-8 as default encoding.
+    if (encoding_info.isEmpty()) {
+      GetMainFrame()->loadHTMLString(contents, base_url);
+    } else {
+      WebData data(contents.data(), contents.length());
+
+      // Do not use WebFrame.LoadHTMLString because it assumes that input
+      // html contents use UTF-8 encoding.
+      // TODO(darin): This should use WebFrame::loadData.
+      WebFrame* web_frame = GetMainFrame();
+
+      ASSERT_TRUE(web_frame != NULL);
+
+      web_frame->loadData(data, "text/html", encoding_info, base_url);
+    }
+
+    runner->Run();
+  }
+
+  // Serialize page DOM according to specific page URL. The parameter
+  // recursive_serialization indicates whether we will serialize all
+  // sub-frames.
+  void SerializeDomForURL(const GURL& page_url,
+                          bool recursive_serialization) {
+    // Find corresponding WebFrame according to page_url.
+    WebFrame* web_frame = FindSubFrameByURL(GetWebView(), page_url);
+    ASSERT_TRUE(web_frame != NULL);
+    // Add input file URl to links_.
+    links_.assign(&page_url,1);
+    // Add dummy file path to local_path_.
+    WebString file_path = webkit_base::FilePathStringToWebString(
+        FILE_PATH_LITERAL("c:\\dummy.htm"));
+    local_paths_.assign(&file_path, 1);
+    // Start serializing DOM.
+    bool result = WebPageSerializer::serialize(web_frame,
+       recursive_serialization,
+       static_cast<WebPageSerializerClient*>(this),
+       links_,
+       local_paths_,
+       webkit_base::FilePathToWebString(local_directory_name_));
+    ASSERT_TRUE(result);
+    ASSERT_TRUE(serialized_);
+  }
+
+  void SerializeHTMLDOMWithDocTypeOnRenderer(const GURL& file_url) {
+    // Make sure original contents have document type.
+    WebFrame* web_frame = FindSubFrameByURL(GetWebView(), file_url);
+    ASSERT_TRUE(web_frame != NULL);
+    WebDocument doc = web_frame->document();
+    ASSERT_TRUE(HasDocType(doc));
+    // Do serialization.
+    SerializeDomForURL(file_url, false);
+    // Load the serialized contents.
+    ASSERT_TRUE(HasSerializedFrame(file_url));
+    const std::string& serialized_contents =
+        GetSerializedContentForFrame(file_url);
+    LoadContents(serialized_contents, file_url,
+                 web_frame->document().encoding());
+    // Make sure serialized contents still have document type.
+    web_frame = GetMainFrame();
+    doc = web_frame->document();
+    ASSERT_TRUE(HasDocType(doc));
+  }
+
+  void SerializeHTMLDOMWithoutDocTypeOnRenderer(const GURL& file_url) {
+    // Make sure original contents do not have document type.
+    WebFrame* web_frame = FindSubFrameByURL(GetWebView(), file_url);
+    ASSERT_TRUE(web_frame != NULL);
+    WebDocument doc = web_frame->document();
+    ASSERT_TRUE(!HasDocType(doc));
+    // Do serialization.
+    SerializeDomForURL(file_url, false);
+    // Load the serialized contents.
+    ASSERT_TRUE(HasSerializedFrame(file_url));
+    const std::string& serialized_contents =
+        GetSerializedContentForFrame(file_url);
+    LoadContents(serialized_contents, file_url,
+                 web_frame->document().encoding());
+    // Make sure serialized contents do not have document type.
+    web_frame = GetMainFrame();
+    doc = web_frame->document();
+    ASSERT_TRUE(!HasDocType(doc));
+  }
+
+  void SerializeXMLDocWithBuiltInEntitiesOnRenderer(
+      const GURL& xml_file_url, const std::string& original_contents) {
+    // Do serialization.
+    SerializeDomForURL(xml_file_url, false);
+    // Compare the serialized contents with original contents.
+    ASSERT_TRUE(HasSerializedFrame(xml_file_url));
+    const std::string& serialized_contents =
+        GetSerializedContentForFrame(xml_file_url);
+    ASSERT_EQ(original_contents, serialized_contents);
+  }
+
+  void SerializeHTMLDOMWithAddingMOTWOnRenderer(
+      const GURL& file_url, const std::string& original_contents) {
+    // Make sure original contents does not have MOTW;
+    std::string motw_declaration =
+       WebPageSerializer::generateMarkOfTheWebDeclaration(file_url).utf8();
+    ASSERT_FALSE(motw_declaration.empty());
+    // The encoding of original contents is ISO-8859-1, so we convert the MOTW
+    // declaration to ASCII and search whether original contents has it or not.
+    ASSERT_TRUE(std::string::npos == original_contents.find(motw_declaration));
+
+    // Do serialization.
+    SerializeDomForURL(file_url, false);
+    // Make sure the serialized contents have MOTW ;
+    ASSERT_TRUE(HasSerializedFrame(file_url));
+    const std::string& serialized_contents =
+        GetSerializedContentForFrame(file_url);
+    ASSERT_FALSE(std::string::npos ==
+        serialized_contents.find(motw_declaration));
+  }
+
+  void SerializeHTMLDOMWithNoMetaCharsetInOriginalDocOnRenderer(
+      const GURL& file_url) {
+    // Make sure there is no META charset declaration in original document.
+    WebFrame* web_frame = FindSubFrameByURL(GetWebView(), file_url);
+    ASSERT_TRUE(web_frame != NULL);
+    WebDocument doc = web_frame->document();
+    ASSERT_TRUE(doc.isHTMLDocument());
+    WebElement head_element = doc.head();
+    ASSERT_TRUE(!head_element.isNull());
+    // Go through all children of HEAD element.
+    for (WebNode child = head_element.firstChild(); !child.isNull();
+         child = child.nextSibling()) {
+      std::string charset_info;
+      if (IsMetaElement(child, charset_info))
+        ASSERT_TRUE(charset_info.empty());
+    }
+    // Do serialization.
+    SerializeDomForURL(file_url, false);
+
+    // Load the serialized contents.
+    ASSERT_TRUE(HasSerializedFrame(file_url));
+    const std::string& serialized_contents =
+        GetSerializedContentForFrame(file_url);
+    LoadContents(serialized_contents, file_url,
+                 web_frame->document().encoding());
+    // Make sure the first child of HEAD element is META which has charset
+    // declaration in serialized contents.
+    web_frame = GetMainFrame();
+    ASSERT_TRUE(web_frame != NULL);
+    doc = web_frame->document();
+    ASSERT_TRUE(doc.isHTMLDocument());
+    head_element = doc.head();
+    ASSERT_TRUE(!head_element.isNull());
+    WebNode meta_node = head_element.firstChild();
+    ASSERT_TRUE(!meta_node.isNull());
+    // Get meta charset info.
+    std::string charset_info2;
+    ASSERT_TRUE(IsMetaElement(meta_node, charset_info2));
+    ASSERT_TRUE(!charset_info2.empty());
+    ASSERT_EQ(charset_info2,
+              std::string(web_frame->document().encoding().utf8()));
+
+    // Make sure no more additional META tags which have charset declaration.
+    for (WebNode child = meta_node.nextSibling(); !child.isNull();
+         child = child.nextSibling()) {
+      std::string charset_info;
+      if (IsMetaElement(child, charset_info))
+        ASSERT_TRUE(charset_info.empty());
+    }
+  }
+
+  void SerializeHTMLDOMWithMultipleMetaCharsetInOriginalDocOnRenderer(
+      const GURL& file_url) {
+    // Make sure there are multiple META charset declarations in original
+    // document.
+    WebFrame* web_frame = FindSubFrameByURL(GetWebView(), file_url);
+    ASSERT_TRUE(web_frame != NULL);
+    WebDocument doc = web_frame->document();
+    ASSERT_TRUE(doc.isHTMLDocument());
+    WebElement head_ele = doc.head();
+    ASSERT_TRUE(!head_ele.isNull());
+    // Go through all children of HEAD element.
+    int charset_declaration_count = 0;
+    for (WebNode child = head_ele.firstChild(); !child.isNull();
+         child = child.nextSibling()) {
+      std::string charset_info;
+      if (IsMetaElement(child, charset_info) && !charset_info.empty())
+        charset_declaration_count++;
+    }
+    // The original doc has more than META tags which have charset declaration.
+    ASSERT_TRUE(charset_declaration_count > 1);
+
+    // Do serialization.
+    SerializeDomForURL(file_url, false);
+
+    // Load the serialized contents.
+    ASSERT_TRUE(HasSerializedFrame(file_url));
+    const std::string& serialized_contents =
+        GetSerializedContentForFrame(file_url);
+    LoadContents(serialized_contents, file_url,
+                 web_frame->document().encoding());
+    // Make sure only first child of HEAD element is META which has charset
+    // declaration in serialized contents.
+    web_frame = GetMainFrame();
+    ASSERT_TRUE(web_frame != NULL);
+    doc = web_frame->document();
+    ASSERT_TRUE(doc.isHTMLDocument());
+    head_ele = doc.head();
+    ASSERT_TRUE(!head_ele.isNull());
+    WebNode meta_node = head_ele.firstChild();
+    ASSERT_TRUE(!meta_node.isNull());
+    // Get meta charset info.
+    std::string charset_info2;
+    ASSERT_TRUE(IsMetaElement(meta_node, charset_info2));
+    ASSERT_TRUE(!charset_info2.empty());
+    ASSERT_EQ(charset_info2,
+              std::string(web_frame->document().encoding().utf8()));
+
+    // Make sure no more additional META tags which have charset declaration.
+    for (WebNode child = meta_node.nextSibling(); !child.isNull();
+         child = child.nextSibling()) {
+      std::string charset_info;
+      if (IsMetaElement(child, charset_info))
+        ASSERT_TRUE(charset_info.empty());
+    }
+  }
+
+  void SerializeHTMLDOMWithEntitiesInTextOnRenderer() {
+    base::FilePath page_file_path = GetTestFilePath(
+        "dom_serializer", "dom_serializer/htmlentities_in_text.htm");
+    // Get file URL. The URL is dummy URL to identify the following loading
+    // actions. The test content is in constant:original_contents.
+    GURL file_url = net::FilePathToFileURL(page_file_path);
+    ASSERT_TRUE(file_url.SchemeIsFile());
+    // Test contents.
+    static const char* const original_contents =
+        "<html><body>&amp;&lt;&gt;\"\'</body></html>";
+    // Load the test contents.
+    LoadContents(original_contents, file_url, WebString());
+
+    // Get BODY's text content in DOM.
+    WebFrame* web_frame = FindSubFrameByURL(GetWebView(), file_url);
+    ASSERT_TRUE(web_frame != NULL);
+    WebDocument doc = web_frame->document();
+    ASSERT_TRUE(doc.isHTMLDocument());
+    WebElement body_ele = doc.body();
+    ASSERT_TRUE(!body_ele.isNull());
+    WebNode text_node = body_ele.firstChild();
+    ASSERT_TRUE(text_node.isTextNode());
+    ASSERT_TRUE(std::string(text_node.createMarkup().utf8()) ==
+                "&amp;&lt;&gt;\"\'");
+    // Do serialization.
+    SerializeDomForURL(file_url, false);
+    // Compare the serialized contents with original contents.
+    ASSERT_TRUE(HasSerializedFrame(file_url));
+    const std::string& serialized_contents =
+        GetSerializedContentForFrame(file_url);
+    // Compare the serialized contents with original contents to make sure
+    // they are same.
+    // Because we add MOTW when serializing DOM, so before comparison, we also
+    // need to add MOTW to original_contents.
+    std::string original_str =
+      WebPageSerializer::generateMarkOfTheWebDeclaration(file_url).utf8();
+    original_str += original_contents;
+    // Since WebCore now inserts a new HEAD element if there is no HEAD element
+    // when creating BODY element. (Please see
+    // HTMLParser::bodyCreateErrorCheck.) We need to append the HEAD content and
+    // corresponding META content if we find WebCore-generated HEAD element.
+    if (!doc.head().isNull()) {
+      WebString encoding = web_frame->document().encoding();
+      std::string htmlTag("<html>");
+      std::string::size_type pos = original_str.find(htmlTag);
+      ASSERT_NE(std::string::npos, pos);
+      pos += htmlTag.length();
+      std::string head_part("<head>");
+      head_part +=
+          WebPageSerializer::generateMetaCharsetDeclaration(encoding).utf8();
+      head_part += "</head>";
+      original_str.insert(pos, head_part);
+    }
+    ASSERT_EQ(original_str, serialized_contents);
+  }
+
+  void SerializeHTMLDOMWithEntitiesInAttributeValueOnRenderer() {
+    base::FilePath page_file_path = GetTestFilePath(
+        "dom_serializer", "dom_serializer/htmlentities_in_attribute_value.htm");
+    // Get file URL. The URL is dummy URL to identify the following loading
+    // actions. The test content is in constant:original_contents.
+    GURL file_url = net::FilePathToFileURL(page_file_path);
+    ASSERT_TRUE(file_url.SchemeIsFile());
+    // Test contents.
+    static const char* const original_contents =
+        "<html><body title=\"&amp;&lt;&gt;&quot;&#39;\"></body></html>";
+    // Load the test contents.
+    LoadContents(original_contents, file_url, WebString());
+    // Get value of BODY's title attribute in DOM.
+    WebFrame* web_frame = FindSubFrameByURL(GetWebView(), file_url);
+    ASSERT_TRUE(web_frame != NULL);
+    WebDocument doc = web_frame->document();
+    ASSERT_TRUE(doc.isHTMLDocument());
+    WebElement body_ele = doc.body();
+    ASSERT_TRUE(!body_ele.isNull());
+    WebString value = body_ele.getAttribute("title");
+    ASSERT_TRUE(std::string(value.utf8()) == "&<>\"\'");
+    // Do serialization.
+    SerializeDomForURL(file_url, false);
+    // Compare the serialized contents with original contents.
+    ASSERT_TRUE(HasSerializedFrame(file_url));
+    const std::string& serialized_contents =
+        GetSerializedContentForFrame(file_url);
+    // Compare the serialized contents with original contents to make sure
+    // they are same.
+    std::string original_str =
+        WebPageSerializer::generateMarkOfTheWebDeclaration(file_url).utf8();
+    original_str += original_contents;
+    if (!doc.isNull()) {
+      WebString encoding = web_frame->document().encoding();
+      std::string htmlTag("<html>");
+      std::string::size_type pos = original_str.find(htmlTag);
+      ASSERT_NE(std::string::npos, pos);
+      pos += htmlTag.length();
+      std::string head_part("<head>");
+      head_part +=
+          WebPageSerializer::generateMetaCharsetDeclaration(encoding).utf8();
+      head_part += "</head>";
+      original_str.insert(pos, head_part);
+    }
+    ASSERT_EQ(original_str, serialized_contents);
+  }
+
+  void SerializeHTMLDOMWithNonStandardEntitiesOnRenderer(const GURL& file_url) {
+    // Get value of BODY's title attribute in DOM.
+    WebFrame* web_frame = FindSubFrameByURL(GetWebView(), file_url);
+    WebDocument doc = web_frame->document();
+    ASSERT_TRUE(doc.isHTMLDocument());
+    WebElement body_element = doc.body();
+    // Unescaped string for "&percnt;&nsup;&sup1;&apos;".
+    static const wchar_t parsed_value[] = {
+      '%', 0x2285, 0x00b9, '\'', 0
+    };
+    WebString value = body_element.getAttribute("title");
+    ASSERT_TRUE(UTF16ToWide(value) == parsed_value);
+    ASSERT_TRUE(UTF16ToWide(body_element.innerText()) == parsed_value);
+
+    // Do serialization.
+    SerializeDomForURL(file_url, false);
+    // Check the serialized string.
+    ASSERT_TRUE(HasSerializedFrame(file_url));
+    const std::string& serialized_contents =
+        GetSerializedContentForFrame(file_url);
+    // Confirm that the serialized string has no non-standard HTML entities.
+    ASSERT_EQ(std::string::npos, serialized_contents.find("&percnt;"));
+    ASSERT_EQ(std::string::npos, serialized_contents.find("&nsup;"));
+    ASSERT_EQ(std::string::npos, serialized_contents.find("&sup1;"));
+    ASSERT_EQ(std::string::npos, serialized_contents.find("&apos;"));
+  }
+
+  void SerializeHTMLDOMWithBaseTagOnRenderer(const GURL& file_url,
+                                             const GURL& path_dir_url) {
+    // There are total 2 available base tags in this test file.
+    const int kTotalBaseTagCountInTestFile = 2;
+
+    // Since for this test, we assume there is no savable sub-resource links for
+    // this test file, also all links are relative URLs in this test file, so we
+    // need to check those relative URLs and make sure document has BASE tag.
+    WebFrame* web_frame = FindSubFrameByURL(GetWebView(), file_url);
+    ASSERT_TRUE(web_frame != NULL);
+    WebDocument doc = web_frame->document();
+    ASSERT_TRUE(doc.isHTMLDocument());
+    // Go through all descent nodes.
+    WebNodeCollection all = doc.all();
+    int original_base_tag_count = 0;
+    for (WebNode node = all.firstItem(); !node.isNull();
+         node = all.nextItem()) {
+      if (!node.isElementNode())
+        continue;
+      WebElement element = node.to<WebElement>();
+      if (element.hasTagName("base")) {
+        original_base_tag_count++;
+      } else {
+        // Get link.
+        WebString value =
+            webkit_glue::GetSubResourceLinkFromElement(element);
+        if (value.isNull() && element.hasTagName("a")) {
+          value = element.getAttribute("href");
+          if (value.isEmpty())
+            value = WebString();
+        }
+        // Each link is relative link.
+        if (!value.isNull()) {
+          GURL link(value.utf8());
+          ASSERT_TRUE(link.scheme().empty());
+        }
+      }
+    }
+    ASSERT_EQ(original_base_tag_count, kTotalBaseTagCountInTestFile);
+    // Make sure in original document, the base URL is not equal with the
+    // |path_dir_url|.
+    GURL original_base_url(doc.baseURL());
+    ASSERT_NE(original_base_url, path_dir_url);
+
+    // Do serialization.
+    SerializeDomForURL(file_url, false);
+
+    // Load the serialized contents.
+    ASSERT_TRUE(HasSerializedFrame(file_url));
+    const std::string& serialized_contents =
+        GetSerializedContentForFrame(file_url);
+    LoadContents(serialized_contents, file_url,
+                 web_frame->document().encoding());
+
+    // Make sure all links are absolute URLs and doc there are some number of
+    // BASE tags in serialized HTML data. Each of those BASE tags have same base
+    // URL which is as same as URL of current test file.
+    web_frame = GetMainFrame();
+    ASSERT_TRUE(web_frame != NULL);
+    doc = web_frame->document();
+    ASSERT_TRUE(doc.isHTMLDocument());
+    // Go through all descent nodes.
+    all = doc.all();
+    int new_base_tag_count = 0;
+    for (WebNode node = all.firstItem(); !node.isNull();
+         node = all.nextItem()) {
+      if (!node.isElementNode())
+        continue;
+      WebElement element = node.to<WebElement>();
+      if (element.hasTagName("base")) {
+        new_base_tag_count++;
+      } else {
+        // Get link.
+        WebString value =
+            webkit_glue::GetSubResourceLinkFromElement(element);
+        if (value.isNull() && element.hasTagName("a")) {
+          value = element.getAttribute("href");
+          if (value.isEmpty())
+            value = WebString();
+        }
+        // Each link is absolute link.
+        if (!value.isNull()) {
+          GURL link(std::string(value.utf8()));
+          ASSERT_FALSE(link.scheme().empty());
+        }
+      }
+    }
+    // We have one more added BASE tag which is generated by JavaScript.
+    ASSERT_EQ(new_base_tag_count, original_base_tag_count + 1);
+    // Make sure in new document, the base URL is equal with the |path_dir_url|.
+    GURL new_base_url(doc.baseURL());
+    ASSERT_EQ(new_base_url, path_dir_url);
+  }
+
+  void SerializeHTMLDOMWithEmptyHeadOnRenderer() {
+    base::FilePath page_file_path = GetTestFilePath(
+        "dom_serializer", "empty_head.htm");
+    GURL file_url = net::FilePathToFileURL(page_file_path);
+    ASSERT_TRUE(file_url.SchemeIsFile());
+
+    // Load the test html content.
+    static const char* const empty_head_contents =
+      "<html><head></head><body>hello world</body></html>";
+    LoadContents(empty_head_contents, file_url, WebString());
+
+    // Make sure the head tag is empty.
+    WebFrame* web_frame = GetMainFrame();
+    ASSERT_TRUE(web_frame != NULL);
+    WebDocument doc = web_frame->document();
+    ASSERT_TRUE(doc.isHTMLDocument());
+    WebElement head_element = doc.head();
+    ASSERT_TRUE(!head_element.isNull());
+    ASSERT_TRUE(!head_element.hasChildNodes());
+    ASSERT_TRUE(head_element.childNodes().length() == 0);
+
+    // Do serialization.
+    SerializeDomForURL(file_url, false);
+    // Make sure the serialized contents have META ;
+    ASSERT_TRUE(HasSerializedFrame(file_url));
+    const std::string& serialized_contents =
+        GetSerializedContentForFrame(file_url);
+
+    // Reload serialized contents and make sure there is only one META tag.
+    LoadContents(serialized_contents, file_url,
+                 web_frame->document().encoding());
+    web_frame = GetMainFrame();
+    ASSERT_TRUE(web_frame != NULL);
+    doc = web_frame->document();
+    ASSERT_TRUE(doc.isHTMLDocument());
+    head_element = doc.head();
+    ASSERT_TRUE(!head_element.isNull());
+    ASSERT_TRUE(head_element.hasChildNodes());
+    ASSERT_TRUE(head_element.childNodes().length() == 1);
+    WebNode meta_node = head_element.firstChild();
+    ASSERT_TRUE(!meta_node.isNull());
+    // Get meta charset info.
+    std::string charset_info;
+    ASSERT_TRUE(IsMetaElement(meta_node, charset_info));
+    ASSERT_TRUE(!charset_info.empty());
+    ASSERT_EQ(charset_info,
+              std::string(web_frame->document().encoding().utf8()));
+
+    // Check the body's first node is text node and its contents are
+    // "hello world"
+    WebElement body_element = doc.body();
+    ASSERT_TRUE(!body_element.isNull());
+    WebNode text_node = body_element.firstChild();
+    ASSERT_TRUE(text_node.isTextNode());
+    WebString text_node_contents = text_node.nodeValue();
+    ASSERT_TRUE(std::string(text_node_contents.utf8()) == "hello world");
+  }
+
+  void SerializeDocumentWithDownloadedIFrameOnRenderer(const GURL& file_url) {
+    // Do a recursive serialization. We pass if we don't crash.
+    SerializeDomForURL(file_url, true);
+  }
+
+  void SubResourceForElementsInNonHTMLNamespaceOnRenderer(
+      const GURL& file_url) {
+    WebFrame* web_frame = FindSubFrameByURL(GetWebView(), file_url);
+    ASSERT_TRUE(web_frame != NULL);
+    WebDocument doc = web_frame->document();
+    WebNode lastNodeInBody = doc.body().lastChild();
+    ASSERT_EQ(WebNode::ElementNode, lastNodeInBody.nodeType());
+    WebString uri = webkit_glue::GetSubResourceLinkFromElement(
+        lastNodeInBody.to<WebElement>());
+    EXPECT_TRUE(uri.isNull());
+  }
+
+ private:
+  // Map frame_url to corresponding serialized_content.
+  typedef base::hash_map<std::string, std::string> SerializedFrameContentMap;
+  SerializedFrameContentMap serialized_frame_map_;
+  // Map frame_url to corresponding status of serialization finish.
+  typedef base::hash_map<std::string, bool> SerializationFinishStatusMap;
+  SerializationFinishStatusMap serialization_finish_status_;
+  // Flag indicates whether the process of serializing DOM is finished or not.
+  bool serialized_;
+  // The links_ contain dummy original URLs of all saved links.
+  WebVector<WebURL> links_;
+  // The local_paths_ contain dummy corresponding local file paths of all saved
+  // links, which matched links_ one by one.
+  WebVector<WebString> local_paths_;
+  // The local_directory_name_ is dummy relative path of directory which
+  // contain all saved auxiliary files included all sub frames and resources.
+  const base::FilePath local_directory_name_;
+};
+
+// If original contents have document type, the serialized contents also have
+// document type.
+IN_PROC_BROWSER_TEST_F(DomSerializerTests, SerializeHTMLDOMWithDocType) {
+  base::FilePath page_file_path =
+      GetTestFilePath("dom_serializer", "youtube_1.htm");
+  GURL file_url = net::FilePathToFileURL(page_file_path);
+  ASSERT_TRUE(file_url.SchemeIsFile());
+  // Load the test file.
+  NavigateToURL(shell(), file_url);
+
+  PostTaskToInProcessRendererAndWait(
+        base::Bind(&DomSerializerTests::SerializeHTMLDOMWithDocTypeOnRenderer,
+                   base::Unretained(this), file_url));
+}
+
+// If original contents do not have document type, the serialized contents
+// also do not have document type.
+IN_PROC_BROWSER_TEST_F(DomSerializerTests, SerializeHTMLDOMWithoutDocType) {
+  base::FilePath page_file_path =
+      GetTestFilePath("dom_serializer", "youtube_2.htm");
+  GURL file_url = net::FilePathToFileURL(page_file_path);
+  ASSERT_TRUE(file_url.SchemeIsFile());
+  // Load the test file.
+  NavigateToURL(shell(), file_url);
+
+  PostTaskToInProcessRendererAndWait(
+        base::Bind(
+            &DomSerializerTests::SerializeHTMLDOMWithoutDocTypeOnRenderer,
+            base::Unretained(this), file_url));
+}
+
+// Serialize XML document which has all 5 built-in entities. After
+// finishing serialization, the serialized contents should be same
+// with original XML document.
+IN_PROC_BROWSER_TEST_F(DomSerializerTests, SerializeXMLDocWithBuiltInEntities) {
+  base::FilePath page_file_path =
+      GetTestFilePath("dom_serializer", "note.html");
+  base::FilePath xml_file_path = GetTestFilePath("dom_serializer", "note.xml");
+  // Read original contents for later comparison.
+  std::string original_contents;
+  ASSERT_TRUE(file_util::ReadFileToString(xml_file_path, &original_contents));
+  // Get file URL.
+  GURL file_url = net::FilePathToFileURL(page_file_path);
+  GURL xml_file_url = net::FilePathToFileURL(xml_file_path);
+  ASSERT_TRUE(file_url.SchemeIsFile());
+  // Load the test file.
+  NavigateToURL(shell(), file_url);
+
+  PostTaskToInProcessRendererAndWait(
+        base::Bind(
+            &DomSerializerTests::SerializeXMLDocWithBuiltInEntitiesOnRenderer,
+            base::Unretained(this), xml_file_url, original_contents));
+}
+
+// When serializing DOM, we add MOTW declaration before html tag.
+IN_PROC_BROWSER_TEST_F(DomSerializerTests, SerializeHTMLDOMWithAddingMOTW) {
+  base::FilePath page_file_path =
+      GetTestFilePath("dom_serializer", "youtube_2.htm");
+  // Read original contents for later comparison .
+  std::string original_contents;
+  ASSERT_TRUE(file_util::ReadFileToString(page_file_path, &original_contents));
+  // Get file URL.
+  GURL file_url = net::FilePathToFileURL(page_file_path);
+  ASSERT_TRUE(file_url.SchemeIsFile());
+
+  // Load the test file.
+  NavigateToURL(shell(), file_url);
+
+  PostTaskToInProcessRendererAndWait(
+        base::Bind(
+            &DomSerializerTests::SerializeHTMLDOMWithAddingMOTWOnRenderer,
+            base::Unretained(this), file_url, original_contents));
+}
+
+// When serializing DOM, we will add the META which have correct charset
+// declaration as first child of HEAD element for resolving WebKit bug:
+// http://bugs.webkit.org/show_bug.cgi?id=16621 even the original document
+// does not have META charset declaration.
+IN_PROC_BROWSER_TEST_F(DomSerializerTests,
+                       SerializeHTMLDOMWithNoMetaCharsetInOriginalDoc) {
+  base::FilePath page_file_path =
+      GetTestFilePath("dom_serializer", "youtube_1.htm");
+  // Get file URL.
+  GURL file_url = net::FilePathToFileURL(page_file_path);
+  ASSERT_TRUE(file_url.SchemeIsFile());
+  // Load the test file.
+  NavigateToURL(shell(), file_url);
+
+  PostTaskToInProcessRendererAndWait(
+        base::Bind(
+            &DomSerializerTests::
+                SerializeHTMLDOMWithNoMetaCharsetInOriginalDocOnRenderer,
+            base::Unretained(this), file_url));
+}
+
+// When serializing DOM, if the original document has multiple META charset
+// declaration, we will add the META which have correct charset declaration
+// as first child of HEAD element and remove all original META charset
+// declarations.
+IN_PROC_BROWSER_TEST_F(DomSerializerTests,
+                       SerializeHTMLDOMWithMultipleMetaCharsetInOriginalDoc) {
+  base::FilePath page_file_path =
+      GetTestFilePath("dom_serializer", "youtube_2.htm");
+  // Get file URL.
+  GURL file_url = net::FilePathToFileURL(page_file_path);
+  ASSERT_TRUE(file_url.SchemeIsFile());
+  // Load the test file.
+  NavigateToURL(shell(), file_url);
+
+  PostTaskToInProcessRendererAndWait(
+        base::Bind(
+            &DomSerializerTests::
+                SerializeHTMLDOMWithMultipleMetaCharsetInOriginalDocOnRenderer,
+            base::Unretained(this), file_url));
+}
+
+// Test situation of html entities in text when serializing HTML DOM.
+IN_PROC_BROWSER_TEST_F(DomSerializerTests, SerializeHTMLDOMWithEntitiesInText) {
+  // Need to spin up the renderer and also navigate to a file url so that the
+  // renderer code doesn't attempt a fork when it sees a load to file scheme
+  // from non-file scheme.
+  NavigateToURL(shell(), GetTestUrl(".", "simple_page.html"));
+
+  PostTaskToInProcessRendererAndWait(
+        base::Bind(
+            &DomSerializerTests::SerializeHTMLDOMWithEntitiesInTextOnRenderer,
+            base::Unretained(this)));
+}
+
+// Test situation of html entities in attribute value when serializing
+// HTML DOM.
+// This test started to fail at WebKit r65388. See http://crbug.com/52279.
+IN_PROC_BROWSER_TEST_F(DomSerializerTests,
+                       SerializeHTMLDOMWithEntitiesInAttributeValue) {
+  // Need to spin up the renderer and also navigate to a file url so that the
+  // renderer code doesn't attempt a fork when it sees a load to file scheme
+  // from non-file scheme.
+  NavigateToURL(shell(), GetTestUrl(".", "simple_page.html"));
+
+  PostTaskToInProcessRendererAndWait(
+        base::Bind(
+            &DomSerializerTests::
+                SerializeHTMLDOMWithEntitiesInAttributeValueOnRenderer,
+            base::Unretained(this)));
+}
+
+// Test situation of non-standard HTML entities when serializing HTML DOM.
+// This test started to fail at WebKit r65351. See http://crbug.com/52279.
+IN_PROC_BROWSER_TEST_F(DomSerializerTests,
+                       SerializeHTMLDOMWithNonStandardEntities) {
+  // Make a test file URL and load it.
+  base::FilePath page_file_path = GetTestFilePath(
+      "dom_serializer", "nonstandard_htmlentities.htm");
+  GURL file_url = net::FilePathToFileURL(page_file_path);
+  NavigateToURL(shell(), file_url);
+
+  PostTaskToInProcessRendererAndWait(
+        base::Bind(
+            &DomSerializerTests::
+                SerializeHTMLDOMWithNonStandardEntitiesOnRenderer,
+            base::Unretained(this), file_url));
+}
+
+// Test situation of BASE tag in original document when serializing HTML DOM.
+// When serializing, we should comment the BASE tag, append a new BASE tag.
+// rewrite all the savable URLs to relative local path, and change other URLs
+// to absolute URLs.
+IN_PROC_BROWSER_TEST_F(DomSerializerTests, SerializeHTMLDOMWithBaseTag) {
+  base::FilePath page_file_path = GetTestFilePath(
+      "dom_serializer", "html_doc_has_base_tag.htm");
+
+  // Get page dir URL which is base URL of this file.
+  base::FilePath dir_name = page_file_path.DirName();
+  dir_name = dir_name.Append(
+      base::FilePath::StringType(base::FilePath::kSeparators[0], 1));
+  GURL path_dir_url = net::FilePathToFileURL(dir_name);
+
+  // Get file URL.
+  GURL file_url = net::FilePathToFileURL(page_file_path);
+  ASSERT_TRUE(file_url.SchemeIsFile());
+  // Load the test file.
+  NavigateToURL(shell(), file_url);
+
+  PostTaskToInProcessRendererAndWait(
+        base::Bind(
+            &DomSerializerTests::SerializeHTMLDOMWithBaseTagOnRenderer,
+            base::Unretained(this), file_url, path_dir_url));
+}
+
+// Serializing page which has an empty HEAD tag.
+IN_PROC_BROWSER_TEST_F(DomSerializerTests, SerializeHTMLDOMWithEmptyHead) {
+  // Need to spin up the renderer and also navigate to a file url so that the
+  // renderer code doesn't attempt a fork when it sees a load to file scheme
+  // from non-file scheme.
+  NavigateToURL(shell(), GetTestUrl(".", "simple_page.html"));
+
+  PostTaskToInProcessRendererAndWait(
+        base::Bind(&DomSerializerTests::SerializeHTMLDOMWithEmptyHeadOnRenderer,
+                   base::Unretained(this)));
+}
+
+// Test that we don't crash when the page contains an iframe that
+// was handled as a download (http://crbug.com/42212).
+IN_PROC_BROWSER_TEST_F(DomSerializerTests,
+                       SerializeDocumentWithDownloadedIFrame) {
+  base::FilePath page_file_path = GetTestFilePath(
+      "dom_serializer", "iframe-src-is-exe.htm");
+  GURL file_url = net::FilePathToFileURL(page_file_path);
+  ASSERT_TRUE(file_url.SchemeIsFile());
+  // Load the test file.
+  NavigateToURL(shell(), file_url);
+
+  PostTaskToInProcessRendererAndWait(
+        base::Bind(
+            &DomSerializerTests::
+                SerializeDocumentWithDownloadedIFrameOnRenderer,
+            base::Unretained(this), file_url));
+}
+
+IN_PROC_BROWSER_TEST_F(DomSerializerTests,
+                       SubResourceForElementsInNonHTMLNamespace) {
+  base::FilePath page_file_path = GetTestFilePath(
+      "dom_serializer", "non_html_namespace.htm");
+  GURL file_url = net::FilePathToFileURL(page_file_path);
+  NavigateToURL(shell(), file_url);
+
+  PostTaskToInProcessRendererAndWait(
+        base::Bind(
+            &DomSerializerTests::
+                SubResourceForElementsInNonHTMLNamespaceOnRenderer,
+            base::Unretained(this), file_url));
+}
+
+}  // namespace content
diff --git a/content/renderer/dom_storage/webstoragearea_impl.cc b/content/renderer/dom_storage/webstoragearea_impl.cc
index c09ed03..72d5fe2 100644
--- a/content/renderer/dom_storage/webstoragearea_impl.cc
+++ b/content/renderer/dom_storage/webstoragearea_impl.cc
@@ -37,8 +37,7 @@
 
 WebStorageAreaImpl::WebStorageAreaImpl(
     int64 namespace_id, const GURL& origin)
-    : ALLOW_THIS_IN_INITIALIZER_LIST(
-          connection_id_(g_all_areas_map.Pointer()->Add(this))),
+    : connection_id_(g_all_areas_map.Pointer()->Add(this)),
       cached_area_(dispatcher()->
           OpenCachedArea(connection_id_, namespace_id, origin)) {
 }
diff --git a/content/renderer/favicon_helper.cc b/content/renderer/favicon_helper.cc
deleted file mode 100644
index 541847e..0000000
--- a/content/renderer/favicon_helper.cc
+++ /dev/null
@@ -1,220 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/renderer/favicon_helper.h"
-
-#include "base/bind.h"
-#include "base/command_line.h"
-#include "base/message_loop.h"
-#include "content/common/icon_messages.h"
-#include "content/public/renderer/render_view.h"
-#include "net/base/data_url.h"
-#include "third_party/WebKit/Source/Platform/chromium/public/WebURLRequest.h"
-#include "third_party/WebKit/Source/Platform/chromium/public/WebVector.h"
-#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
-#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
-#include "ui/base/ui_base_switches.h"
-#include "ui/gfx/favicon_size.h"
-#include "ui/gfx/size.h"
-#include "ui/gfx/skbitmap_operations.h"
-#include "webkit/glue/image_decoder.h"
-#include "webkit/glue/multi_resolution_image_resource_fetcher.h"
-#include "webkit/glue/webkit_glue.h"
-
-using WebKit::WebFrame;
-using WebKit::WebIconURL;
-using WebKit::WebVector;
-using WebKit::WebURL;
-using WebKit::WebURLRequest;
-using webkit_glue::MultiResolutionImageResourceFetcher;
-
-namespace content {
-
-namespace {
-
-bool TouchEnabled() {
-// Based on the definition of chrome::kEnableTouchIcon.
-#if defined(OS_ANDROID)
-  return true;
-#else
-  return false;
-#endif
-}
-
-}  // namespace
-
-
-static FaviconURL::IconType ToFaviconType(WebIconURL::Type type) {
-  switch (type) {
-    case WebIconURL::TypeFavicon:
-      return FaviconURL::FAVICON;
-    case WebIconURL::TypeTouch:
-      return FaviconURL::TOUCH_ICON;
-    case WebIconURL::TypeTouchPrecomposed:
-      return FaviconURL::TOUCH_PRECOMPOSED_ICON;
-    case WebIconURL::TypeInvalid:
-      return FaviconURL::INVALID_ICON;
-  }
-  return FaviconURL::INVALID_ICON;
-}
-
-FaviconHelper::FaviconHelper(RenderView* render_view)
-    : RenderViewObserver(render_view),
-      icon_types_changed_(WebIconURL::TypeInvalid),
-      ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) {
-}
-
-void FaviconHelper::DidChangeIcon(WebKit::WebFrame* frame,
-                                  WebKit::WebIconURL::Type icon_type) {
-  if (frame->parent())
-    return;
-
-  if (!TouchEnabled() && icon_type != WebIconURL::TypeFavicon)
-    return;
-
-  DCHECK(!render_view()->GetWebView() ||
-         frame == render_view()->GetWebView()->mainFrame());
-
-  weak_ptr_factory_.InvalidateWeakPtrs();
-  icon_types_changed_ =
-      static_cast<WebKit::WebIconURL::Type>(icon_types_changed_ | icon_type);
-  MessageLoop::current()->PostTask(FROM_HERE,
-      base::Bind(&FaviconHelper::ProcessDidChangeIcon,
-                 weak_ptr_factory_.GetWeakPtr()));
-}
-
-FaviconHelper::~FaviconHelper() {
-}
-
-void FaviconHelper::ProcessDidChangeIcon() {
-  WebKit::WebIconURL::Type icon_types = icon_types_changed_;
-  icon_types_changed_ = WebIconURL::TypeInvalid;
-  WebKit::WebView* web_view = render_view()->GetWebView();
-  if (!web_view) {
-    return;
-  }
-  WebFrame* frame = web_view->mainFrame();
-  if (!frame) {
-    return;
-  }
-  WebVector<WebIconURL> icon_urls = frame->iconURLs(icon_types);
-  std::vector<FaviconURL> urls;
-  for (size_t i = 0; i < icon_urls.size(); i++) {
-    urls.push_back(FaviconURL(icon_urls[i].iconURL(),
-                              ToFaviconType(icon_urls[i].iconType())));
-  }
-  SendUpdateFaviconURL(routing_id(), render_view()->GetPageId(), urls);
-}
-
-void FaviconHelper::OnDownloadFavicon(int id,
-                                      const GURL& image_url,
-                                      bool is_favicon,
-                                      int image_size) {
-  std::vector<SkBitmap> result_images;
-  if (image_url.SchemeIs("data")) {
-    SkBitmap data_image = ImageFromDataUrl(image_url);
-    if (!data_image.empty())
-      result_images.push_back(data_image);
-  } else {
-    if (DownloadFavicon(id, image_url, is_favicon, image_size)) {
-      // Will complete asynchronously via FaviconHelper::DidDownloadFavicon
-      return;
-    }
-  }
-
-  Send(new IconHostMsg_DidDownloadFavicon(routing_id(),
-                                          id,
-                                          image_url,
-                                          image_size,
-                                          result_images));
-}
-
-bool FaviconHelper::DownloadFavicon(int id,
-                                    const GURL& image_url,
-                                    bool is_favicon,
-                                    int image_size) {
-  // Make sure webview was not shut down.
-  if (!render_view()->GetWebView())
-    return false;
-  // Create an image resource fetcher and assign it with a call back object.
-  image_fetchers_.push_back(new MultiResolutionImageResourceFetcher(
-      image_url,
-      render_view()->GetWebView()->mainFrame(),
-      id,
-      is_favicon ? WebURLRequest::TargetIsFavicon :
-                   WebURLRequest::TargetIsImage,
-      base::Bind(&FaviconHelper::DidDownloadFavicon,
-                 base::Unretained(this), image_size)));
-  return true;
-}
-
-void FaviconHelper::DidDownloadFavicon(
-    int requested_size,
-    MultiResolutionImageResourceFetcher* fetcher,
-    const std::vector<SkBitmap>& images) {
-  // Notify requester of image download status.
-  Send(new IconHostMsg_DidDownloadFavicon(routing_id(),
-                                          fetcher->id(),
-                                          fetcher->image_url(),
-                                          requested_size,
-                                          images));
-
-  // Remove the image fetcher from our pending list. We're in the callback from
-  // MultiResolutionImageResourceFetcher, best to delay deletion.
-  ImageResourceFetcherList::iterator iter =
-      std::find(image_fetchers_.begin(), image_fetchers_.end(), fetcher);
-  if (iter != image_fetchers_.end()) {
-    image_fetchers_.weak_erase(iter);
-    MessageLoop::current()->DeleteSoon(FROM_HERE, fetcher);
-  }
-}
-
-SkBitmap FaviconHelper::ImageFromDataUrl(const GURL& url) const {
-  std::string mime_type, char_set, data;
-  if (net::DataURL::Parse(url, &mime_type, &char_set, &data) && !data.empty()) {
-    // Decode the favicon using WebKit's image decoder.
-    webkit_glue::ImageDecoder decoder(
-        gfx::Size(gfx::kFaviconSize, gfx::kFaviconSize));
-    const unsigned char* src_data =
-        reinterpret_cast<const unsigned char*>(&data[0]);
-
-    return decoder.Decode(src_data, data.size());
-  }
-  return SkBitmap();
-}
-
-void FaviconHelper::SendUpdateFaviconURL(int32 routing_id,
-                                         int32 page_id,
-                                         const std::vector<FaviconURL>& urls) {
-  if (!urls.empty())
-    Send(new IconHostMsg_UpdateFaviconURL(routing_id, page_id, urls));
-}
-
-bool FaviconHelper::OnMessageReceived(const IPC::Message& message) {
-  bool handled = true;
-  IPC_BEGIN_MESSAGE_MAP(FaviconHelper, message)
-    IPC_MESSAGE_HANDLER(IconMsg_DownloadFavicon, OnDownloadFavicon)
-    IPC_MESSAGE_UNHANDLED(handled = false)
-  IPC_END_MESSAGE_MAP()
-
-  return handled;
-}
-
-void FaviconHelper::DidStopLoading() {
-  int icon_types = WebIconURL::TypeFavicon;
-  if (TouchEnabled())
-    icon_types |= WebIconURL::TypeTouchPrecomposed | WebIconURL::TypeTouch;
-
-  WebVector<WebIconURL> icon_urls =
-      render_view()->GetWebView()->mainFrame()->iconURLs(icon_types);
-  std::vector<FaviconURL> urls;
-  for (size_t i = 0; i < icon_urls.size(); i++) {
-    WebURL url = icon_urls[i].iconURL();
-    if (!url.isEmpty())
-      urls.push_back(FaviconURL(url, ToFaviconType(icon_urls[i].iconType())));
-  }
-  SendUpdateFaviconURL(routing_id(), render_view()->GetPageId(), urls);
-}
-
-}  // namespace content
diff --git a/content/renderer/favicon_helper.h b/content/renderer/favicon_helper.h
deleted file mode 100644
index 65032ec..0000000
--- a/content/renderer/favicon_helper.h
+++ /dev/null
@@ -1,106 +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 CONTENT_RENDERER_FAVICON_HELPER_H_
-#define CONTENT_RENDERER_FAVICON_HELPER_H_
-
-#include <string>
-#include <vector>
-
-#include "base/memory/linked_ptr.h"
-#include "base/memory/scoped_vector.h"
-#include "base/memory/weak_ptr.h"
-#include "content/public/common/content_constants.h"
-#include "content/public/renderer/render_view_observer.h"
-#include "googleurl/src/gurl.h"
-
-class SkBitmap;
-
-namespace content {
-struct FaviconURL;
-}
-
-namespace webkit_glue {
-class MultiResolutionImageResourceFetcher;
-}
-
-namespace content {
-
-struct FaviconURL;
-
-// This class deals with favicon downloading.
-// There is one FaviconHelper per RenderView, which is owned by the RenderView.
-class FaviconHelper : public RenderViewObserver {
- public:
-  explicit FaviconHelper(RenderView* render_view);
-
-  // Send a message that the favicon has changed.
-  void DidChangeIcon(WebKit::WebFrame* frame,
-                     WebKit::WebIconURL::Type icon_type);
-
- private:
-  virtual ~FaviconHelper();
-
-  // Start processing the icon change. This done async from DidChangeIcon in
-  // case there are several calls to DidChangeIcon in a row.
-  void ProcessDidChangeIcon();
-
-  // Message handler.
-  void OnDownloadFavicon(int id,
-                         const GURL& image_url,
-                         bool is_favicon,
-                         int image_size);
-
-  // Requests to download a favicon image. When done, the RenderView
-  // is notified by way of DidDownloadFavicon. Returns true if the
-  // request was successfully started, false otherwise. id is used to
-  // uniquely identify the request and passed back to the
-  // DidDownloadFavicon method. If the image is a favicon, cookies are
-  // not sent and not accepted during download.
-  // If the image has multiple frames, the
-  // frame whose size is image_size is returned. If the image doesn't
-  // have a frame at the specified size, the first is returned.
-  bool DownloadFavicon(int id,
-                       const GURL& image_url,
-                       bool is_favicon,
-                       int image_size);
-
-  // This callback is triggered when DownloadFavicon completes, either
-  // succesfully or with a failure. See DownloadFavicon for more
-  // details.
-  void DidDownloadFavicon(
-      int requested_size,
-      webkit_glue::MultiResolutionImageResourceFetcher* fetcher,
-      const std::vector<SkBitmap>& images);
-
-  // Decodes a data: URL image or returns an empty image in case of failure.
-  SkBitmap ImageFromDataUrl(const GURL&) const;
-
-  // Send a message to update the favicon URL for a page.
-  void SendUpdateFaviconURL(int32 routing_id,
-                            int32 page_id,
-                            const std::vector<FaviconURL>& urls);
-
-  // RenderViewObserver implementation.
-  virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
-  virtual void DidStopLoading() OVERRIDE;
-
-  typedef ScopedVector<webkit_glue::MultiResolutionImageResourceFetcher>
-    ImageResourceFetcherList;
-
-  // ImageResourceFetchers schedule via DownloadImage.
-  ImageResourceFetcherList image_fetchers_;
-
-  // The set of flags which have been sent to DidChangeIcon but not yet
-  // processed.
-  WebKit::WebIconURL::Type icon_types_changed_;
-
-  base::WeakPtrFactory<FaviconHelper> weak_ptr_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(FaviconHelper);
-};
-
-} // namespace content
-
-#endif  // CONTENT_RENDERER_FAVICON_HELPER_H_
diff --git a/content/renderer/geolocation_dispatcher.cc b/content/renderer/geolocation_dispatcher.cc
index ca9aa53..312761d 100644
--- a/content/renderer/geolocation_dispatcher.cc
+++ b/content/renderer/geolocation_dispatcher.cc
@@ -12,7 +12,6 @@
 #include "third_party/WebKit/Source/WebKit/chromium/public/WebGeolocationClient.h"
 #include "third_party/WebKit/Source/WebKit/chromium/public/WebGeolocationPosition.h"
 #include "third_party/WebKit/Source/WebKit/chromium/public/WebGeolocationError.h"
-#include "third_party/WebKit/Source/WebKit/chromium/public/WebSecurityOrigin.h"
 
 using WebKit::WebGeolocationController;
 using WebKit::WebGeolocationError;
diff --git a/content/renderer/gpu/compositor_output_surface.cc b/content/renderer/gpu/compositor_output_surface.cc
index cc55ffa..8d24043 100644
--- a/content/renderer/gpu/compositor_output_surface.cc
+++ b/content/renderer/gpu/compositor_output_surface.cc
@@ -9,12 +9,13 @@
 #include "cc/output/compositor_frame.h"
 #include "cc/output/compositor_frame_ack.h"
 #include "cc/output/output_surface_client.h"
+#include "content/common/gpu/client/command_buffer_proxy_impl.h"
+#include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h"
 #include "content/common/view_messages.h"
 #include "content/public/common/content_switches.h"
 #include "content/renderer/render_thread_impl.h"
 #include "ipc/ipc_forwarding_message_filter.h"
 #include "ipc/ipc_sync_channel.h"
-#include "ipc/ipc_sync_message_filter.h"
 #include "third_party/WebKit/Source/Platform/chromium/public/WebGraphicsContext3D.h"
 
 #if defined(OS_ANDROID)
@@ -22,8 +23,6 @@
 #include <sys/resource.h>
 #endif
 
-using cc::CompositorFrame;
-using cc::SoftwareOutputDevice;
 using WebKit::WebGraphicsContext3D;
 
 namespace {
@@ -42,7 +41,10 @@
 {
   uint32 messages_to_filter[] = {
     ViewMsg_UpdateVSyncParameters::ID,
-    ViewMsg_SwapCompositorFrameAck::ID
+    ViewMsg_SwapCompositorFrameAck::ID,
+#if defined(OS_ANDROID)
+    ViewMsg_DidVSync::ID
+#endif
   };
 
   return new IPC::ForwardingMessageFilter(
@@ -52,9 +54,9 @@
 
 CompositorOutputSurface::CompositorOutputSurface(
     int32 routing_id,
-    WebGraphicsContext3D* context3D,
+    WebGraphicsContext3DCommandBufferImpl* context3D,
     cc::SoftwareOutputDevice* software_device)
-    : OutputSurface(make_scoped_ptr(context3D),
+    : OutputSurface(scoped_ptr<WebKit::WebGraphicsContext3D>(context3D),
                     make_scoped_ptr(software_device)),
       output_surface_filter_(
           RenderThreadImpl::current()->compositor_output_surface_filter()),
@@ -66,6 +68,8 @@
   capabilities_.has_parent_compositor = command_line->HasSwitch(
       switches::kEnableDelegatedRenderer);
   DetachFromThread();
+  message_sender_ = RenderThreadImpl::current()->sync_message_filter();
+  DCHECK(message_sender_);
 }
 
 CompositorOutputSurface::~CompositorOutputSurface() {
@@ -100,6 +104,30 @@
   Send(new ViewHostMsg_SwapCompositorFrame(routing_id_, *frame));
 }
 
+void CompositorOutputSurface::SwapBuffers(
+    const cc::LatencyInfo& latency_info) {
+  WebGraphicsContext3DCommandBufferImpl* command_buffer =
+      static_cast<WebGraphicsContext3DCommandBufferImpl*>(context3d());
+  CommandBufferProxyImpl* command_buffer_proxy =
+      command_buffer->GetCommandBufferProxy();
+  DCHECK(command_buffer_proxy);
+  context3d()->shallowFlushCHROMIUM();
+  command_buffer_proxy->SetLatencyInfo(latency_info);
+  OutputSurface::SwapBuffers(latency_info);
+}
+
+void CompositorOutputSurface::PostSubBuffer(
+    gfx::Rect rect, const cc::LatencyInfo& latency_info) {
+  WebGraphicsContext3DCommandBufferImpl* command_buffer =
+      static_cast<WebGraphicsContext3DCommandBufferImpl*>(context3d());
+  CommandBufferProxyImpl* command_buffer_proxy =
+      command_buffer->GetCommandBufferProxy();
+  DCHECK(command_buffer_proxy);
+  context3d()->shallowFlushCHROMIUM();
+  command_buffer_proxy->SetLatencyInfo(latency_info);
+  OutputSurface::PostSubBuffer(rect, latency_info);
+}
+
 void CompositorOutputSurface::OnMessageReceived(const IPC::Message& message) {
   DCHECK(CalledOnValidThread());
   if (!client_)
@@ -107,22 +135,36 @@
   IPC_BEGIN_MESSAGE_MAP(CompositorOutputSurface, message)
     IPC_MESSAGE_HANDLER(ViewMsg_UpdateVSyncParameters, OnUpdateVSyncParameters);
     IPC_MESSAGE_HANDLER(ViewMsg_SwapCompositorFrameAck, OnSwapAck);
+#if defined(OS_ANDROID)
+    IPC_MESSAGE_HANDLER(ViewMsg_DidVSync, OnDidVSync);
+#endif
   IPC_END_MESSAGE_MAP()
 }
 
 void CompositorOutputSurface::OnUpdateVSyncParameters(
     base::TimeTicks timebase, base::TimeDelta interval) {
   DCHECK(CalledOnValidThread());
-  DCHECK(client_);
   client_->OnVSyncParametersChanged(timebase, interval);
 }
 
+#if defined(OS_ANDROID)
+void CompositorOutputSurface::EnableVSyncNotification(bool enable) {
+  DCHECK(CalledOnValidThread());
+  Send(new ViewHostMsg_SetVSyncNotificationEnabled(routing_id_, enable));
+}
+
+void CompositorOutputSurface::OnDidVSync(base::TimeTicks frame_time) {
+  DCHECK(CalledOnValidThread());
+  client_->DidVSync(frame_time);
+}
+#endif  // defined(OS_ANDROID)
+
 void CompositorOutputSurface::OnSwapAck(const cc::CompositorFrameAck& ack) {
   client_->OnSendFrameToParentCompositorAck(ack);
 }
 
 bool CompositorOutputSurface::Send(IPC::Message* message) {
-  return ChildThread::current()->sync_message_filter()->Send(message);
+  return message_sender_->Send(message);
 }
 
 namespace {
diff --git a/content/renderer/gpu/compositor_output_surface.h b/content/renderer/gpu/compositor_output_surface.h
index 255c618..e62990c 100644
--- a/content/renderer/gpu/compositor_output_surface.h
+++ b/content/renderer/gpu/compositor_output_surface.h
@@ -13,6 +13,7 @@
 #include "base/threading/platform_thread.h"
 #include "base/time.h"
 #include "cc/output/output_surface.h"
+#include "ipc/ipc_sync_message_filter.h"
 
 namespace base {
 class TaskRunner;
@@ -24,11 +25,14 @@
 }
 
 namespace cc {
+class CompositorFrame;
 class CompositorFrameAck;
 }
 
 namespace content {
 
+class WebGraphicsContext3DCommandBufferImpl;
+
 // This class can be created only on the main thread, but then becomes pinned
 // to a fixed thread when bindToClient is called.
 class CompositorOutputSurface
@@ -39,13 +43,18 @@
       base::TaskRunner* target_task_runner);
 
   CompositorOutputSurface(int32 routing_id,
-                          WebKit::WebGraphicsContext3D* context3d,
+                          WebGraphicsContext3DCommandBufferImpl* context3d,
                           cc::SoftwareOutputDevice* software);
   virtual ~CompositorOutputSurface();
 
   // cc::OutputSurface implementation.
   virtual bool BindToClient(cc::OutputSurfaceClient* client) OVERRIDE;
   virtual void SendFrameToParentCompositor(cc::CompositorFrame*) OVERRIDE;
+  virtual void PostSubBuffer(gfx::Rect rect, const cc::LatencyInfo&) OVERRIDE;
+  virtual void SwapBuffers(const cc::LatencyInfo&) OVERRIDE;
+#if defined(OS_ANDROID)
+  virtual void EnableVSyncNotification(bool enable) OVERRIDE;
+#endif
 
   // TODO(epenner): This seems out of place here and would be a better fit
   // int CompositorThread after it is fully refactored (http://crbug/170828)
@@ -78,10 +87,14 @@
   void OnMessageReceived(const IPC::Message& message);
   void OnUpdateVSyncParameters(
       base::TimeTicks timebase, base::TimeDelta interval);
+#if defined(OS_ANDROID)
+  void OnDidVSync(base::TimeTicks frame_time);
+#endif
   bool Send(IPC::Message* message);
 
   scoped_refptr<IPC::ForwardingMessageFilter> output_surface_filter_;
   scoped_refptr<CompositorOutputSurfaceProxy> output_surface_proxy_;
+  scoped_refptr<IPC::SyncMessageFilter> message_sender_;
   int routing_id_;
   bool prefers_smoothness_;
   base::PlatformThreadId main_thread_id_;
diff --git a/content/renderer/gpu/compositor_software_output_device.cc b/content/renderer/gpu/compositor_software_output_device.cc
new file mode 100644
index 0000000..cd22bed
--- /dev/null
+++ b/content/renderer/gpu/compositor_software_output_device.cc
@@ -0,0 +1,149 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/gpu/compositor_software_output_device.h"
+
+#include "base/logging.h"
+#include "cc/output/software_frame_data.h"
+#include "content/renderer/render_process.h"
+#include "third_party/skia/include/core/SkCanvas.h"
+#include "third_party/skia/include/core/SkDevice.h"
+#include "third_party/skia/include/core/SkPixelRef.h"
+#include "ui/gfx/skia_util.h"
+#include "ui/surface/transport_dib.h"
+
+namespace content {
+
+CompositorSoftwareOutputDevice::DIB::DIB(size_t size) {
+  RenderProcess* render_process = RenderProcess::current();
+  dib_ = render_process->CreateTransportDIB(size);
+  CHECK(dib_);
+  bool success = dib_->Map();
+  CHECK(success);
+}
+
+CompositorSoftwareOutputDevice::DIB::~DIB() {
+  RenderProcess* render_process = RenderProcess::current();
+  render_process->FreeTransportDIB(dib_);
+}
+
+CompositorSoftwareOutputDevice::CompositorSoftwareOutputDevice()
+    : front_buffer_(-1),
+      num_free_buffers_(0) {
+  DetachFromThread();
+}
+
+CompositorSoftwareOutputDevice::~CompositorSoftwareOutputDevice() {
+  DCHECK(CalledOnValidThread());
+}
+
+CompositorSoftwareOutputDevice::DIB*
+CompositorSoftwareOutputDevice::CreateDIB() {
+  const size_t size =  4 * viewport_size_.GetArea();
+  return new DIB(size);
+}
+
+void CompositorSoftwareOutputDevice::Resize(gfx::Size viewport_size) {
+  DCHECK(CalledOnValidThread());
+
+  if (viewport_size_ == viewport_size)
+    return;
+
+  // Keep non-ACKed dibs open.
+  int first_non_free = front_buffer_ + num_free_buffers_ + 1;
+  int num_non_free = dibs_.size() - num_free_buffers_;
+  for (int i = 0; i < num_non_free; ++i) {
+    int index = (first_non_free + i) % dibs_.size();
+    awaiting_ack_.push_back(dibs_[index]);
+    dibs_[index] = NULL;
+  }
+
+  dibs_.clear();
+  front_buffer_ = -1;
+  num_free_buffers_ = 0;
+  viewport_size_ = viewport_size;
+}
+
+SkCanvas* CompositorSoftwareOutputDevice::BeginPaint(gfx::Rect damage_rect) {
+  DCHECK(CalledOnValidThread());
+
+  gfx::Rect last_damage_rect = damage_rect_;
+  damage_rect_ = damage_rect;
+
+  int last_buffer = front_buffer_;
+  if (num_free_buffers_ == 0) {
+    dibs_.insert(dibs_.begin() + (front_buffer_ + 1), CreateDIB());
+    last_damage_rect = gfx::Rect(viewport_size_);
+  } else {
+    --num_free_buffers_;
+  }
+  front_buffer_ = (front_buffer_ + 1) % dibs_.size();
+
+  TransportDIB* front_dib = dibs_[front_buffer_]->dib();
+  DCHECK(front_dib);
+  DCHECK(front_dib->memory());
+
+  // Set up a canvas for the current front buffer.
+  bitmap_.setConfig(SkBitmap::kARGB_8888_Config,
+                    viewport_size_.width(),
+                    viewport_size_.height());
+  bitmap_.setPixels(front_dib->memory());
+  device_ = skia::AdoptRef(new SkDevice(bitmap_));
+  canvas_ = skia::AdoptRef(new SkCanvas(device_.get()));
+
+  // Copy over previous damage.
+  if (last_buffer != -1) {
+    TransportDIB* last_dib = dibs_[last_buffer]->dib();
+    SkBitmap back_bitmap;
+    back_bitmap.setConfig(SkBitmap::kARGB_8888_Config,
+                          viewport_size_.width(),
+                          viewport_size_.height());
+    back_bitmap.setPixels(last_dib->memory());
+
+    SkRegion region(RectToSkIRect(last_damage_rect));
+    region.op(RectToSkIRect(damage_rect), SkRegion::kDifference_Op);
+    for (SkRegion::Iterator it(region); !it.done(); it.next()) {
+      const SkIRect& src_rect = it.rect();
+      SkRect dst_rect = SkRect::Make(src_rect);
+      canvas_->drawBitmapRect(back_bitmap, &src_rect, dst_rect, NULL);
+    }
+  }
+
+  return canvas_.get();
+}
+
+void CompositorSoftwareOutputDevice::EndPaint(
+    cc::SoftwareFrameData* frame_data) {
+  DCHECK(CalledOnValidThread());
+
+  if (frame_data) {
+    frame_data->size = viewport_size_;
+    frame_data->damage_rect = damage_rect_;
+    frame_data->dib_id = dibs_[front_buffer_]->dib()->id();
+  }
+}
+
+void CompositorSoftwareOutputDevice::ReclaimDIB(const TransportDIB::Id& id) {
+  DCHECK(CalledOnValidThread());
+
+  if (!TransportDIB::is_valid_id(id))
+    return;
+
+  // The reclaimed dib id might not be among the currently
+  // active dibs if we got a resize event in the mean time.
+  ScopedVector<DIB>::iterator it =
+      std::find_if(dibs_.begin(), dibs_.end(), CompareById(id));
+  if (it != dibs_.end()) {
+    ++num_free_buffers_;
+    DCHECK_LE(static_cast<size_t>(num_free_buffers_), dibs_.size());
+    return;
+  } else {
+    it = std::find_if(awaiting_ack_.begin(), awaiting_ack_.end(),
+                      CompareById(id));
+    DCHECK(it != awaiting_ack_.end());
+    awaiting_ack_.erase(it);
+  }
+}
+
+}  // namespace content
diff --git a/content/renderer/gpu/compositor_software_output_device.h b/content/renderer/gpu/compositor_software_output_device.h
new file mode 100644
index 0000000..b82ffe2
--- /dev/null
+++ b/content/renderer/gpu/compositor_software_output_device.h
@@ -0,0 +1,70 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_RENDERER_GPU_COMPOSITOR_SOFTWARE_OUTPUT_DEVICE_H_
+#define CONTENT_RENDERER_GPU_COMPOSITOR_SOFTWARE_OUTPUT_DEVICE_H_
+
+#include "base/memory/scoped_vector.h"
+#include "base/threading/non_thread_safe.h"
+#include "cc/output/software_output_device.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+
+namespace content {
+
+// This class can be created only on the main thread, but then becomes pinned
+// to a fixed thread when BindToClient is called.
+class CompositorSoftwareOutputDevice
+    : NON_EXPORTED_BASE(public cc::SoftwareOutputDevice),
+      NON_EXPORTED_BASE(public base::NonThreadSafe) {
+public:
+  CompositorSoftwareOutputDevice();
+  virtual ~CompositorSoftwareOutputDevice();
+
+  virtual void Resize(gfx::Size size) OVERRIDE;
+
+  virtual SkCanvas* BeginPaint(gfx::Rect damage_rect) OVERRIDE;
+  virtual void EndPaint(cc::SoftwareFrameData* frame_data) OVERRIDE;
+
+  virtual void ReclaimDIB(const TransportDIB::Id& id) OVERRIDE;
+
+private:
+  class DIB {
+   public:
+    explicit DIB(size_t size);
+    ~DIB();
+
+    TransportDIB* dib() const {
+      return dib_;
+    }
+
+   private:
+    TransportDIB* dib_;
+
+    DISALLOW_COPY_AND_ASSIGN(DIB);
+  };
+
+  class CompareById {
+   public:
+    CompareById(const TransportDIB::Id& id) : id_(id) {}
+
+    bool operator()(const DIB* dib) const {
+      return dib->dib() && dib->dib()->id() == id_;
+    }
+
+   private:
+    TransportDIB::Id id_;
+  };
+
+  DIB* CreateDIB();
+
+  int front_buffer_;
+  int num_free_buffers_;
+  ScopedVector<DIB> dibs_;
+  ScopedVector<DIB> awaiting_ack_;
+  SkBitmap bitmap_;
+};
+
+}  // namespace content
+
+#endif  // CONTENT_RENDERER_GPU_COMPOSITOR_SOFTWARE_OUTPUT_DEVICE_H_
diff --git a/content/renderer/gpu/compositor_software_output_device_gl_adapter.cc b/content/renderer/gpu/compositor_software_output_device_gl_adapter.cc
deleted file mode 100644
index 1c3793b..0000000
--- a/content/renderer/gpu/compositor_software_output_device_gl_adapter.cc
+++ /dev/null
@@ -1,148 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/renderer/gpu/compositor_software_output_device_gl_adapter.h"
-
-#include "base/debug/trace_event.h"
-#include "third_party/skia/include/core/SkBitmap.h"
-#include "third_party/skia/include/core/SkCanvas.h"
-#include "third_party/skia/include/core/SkDevice.h"
-#include "third_party/skia/include/core/SkPixelRef.h"
-
-#include <GLES2/gl2.h>
-
-namespace content {
-
-CompositorSoftwareOutputDeviceGLAdapter::
-    CompositorSoftwareOutputDeviceGLAdapter(
-    WebKit::WebGraphicsContext3D* context3d)
-    : program_(0),
-      vertex_shader_(0),
-      fragment_shader_(0),
-      vertex_buffer_(0),
-      texture_id_(0),
-      context3d_(context3d) {
-  CHECK(context3d);
-}
-
-CompositorSoftwareOutputDeviceGLAdapter::
-    ~CompositorSoftwareOutputDeviceGLAdapter() {
-  if (!device_)
-    return;
-
-  context3d_->makeContextCurrent();
-  context3d_->deleteShader(vertex_shader_);
-  context3d_->deleteShader(fragment_shader_);
-  context3d_->deleteProgram(program_);
-  context3d_->deleteBuffer(vertex_buffer_);
-  context3d_->deleteTexture(texture_id_);
-}
-
-void CompositorSoftwareOutputDeviceGLAdapter::Resize(
-    gfx::Size viewport_size) {
-  if (!device_)
-    InitShaders();
-
-  cc::SoftwareOutputDevice::Resize(viewport_size);
-
-  context3d_->makeContextCurrent();
-  context3d_->ensureBackbufferCHROMIUM();
-  context3d_->viewport(0, 0, viewport_size.width(), viewport_size.height());
-  context3d_->reshape(viewport_size.width(), viewport_size.height());
-}
-
-void CompositorSoftwareOutputDeviceGLAdapter::EndPaint(
-    cc::SoftwareFrameData* frame_data) {
-  DCHECK(device_);
-  DCHECK(frame_data == NULL);
-
-  TRACE_EVENT0("renderer", "CompositorSoftwareOutputDeviceGLAdapter::EndPaint");
-  const SkBitmap& bitmap = device_->accessBitmap(false);
-
-  context3d_->makeContextCurrent();
-  context3d_->ensureBackbufferCHROMIUM();
-  context3d_->clear(GL_COLOR_BUFFER_BIT);
-  context3d_->bindTexture(GL_TEXTURE_2D, texture_id_);
-  context3d_->texImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
-      viewport_size_.width(), viewport_size_.height(),
-      0, GL_RGBA, GL_UNSIGNED_BYTE, bitmap.pixelRef()->pixels());
-  context3d_->drawArrays(GL_TRIANGLE_STRIP, 0, 4);
-  context3d_->prepareTexture();
-}
-
-void CompositorSoftwareOutputDeviceGLAdapter::InitShaders() {
-  // Vertex shader that flips the y axis.
-  static const char g_vertex_shader[] =
-    "attribute vec4 a_Position;"
-    "attribute vec2 a_texCoord;"
-    "varying vec2 v_texCoord;"
-    "void main() {"
-    "  gl_Position = a_Position;"
-    "  gl_Position.y = -gl_Position.y;"
-    "  v_texCoord = a_texCoord;"
-    "}";
-
-  // Pixel shader that swizzles RGBA -> BGRA.
-  static const char g_fragment_shader[] =
-    "precision mediump float;"
-    "varying vec2 v_texCoord;"
-    "uniform sampler2D s_texture;"
-    "void main() {"
-    "  gl_FragColor = texture2D(s_texture, v_texCoord).bgra;"
-    "}";
-
-  const GLfloat attribs[] = {
-    -1.0f, -1.0f,
-    1.0f, -1.0f,
-    -1.0f, 1.0f,
-    1.0f, 1.0f,
-    0.0f, 0.0f,
-    1.0f, 0.0f,
-    0.0f, 1.0f,
-    1.0f, 1.0f
-  };
-
-  context3d_->makeContextCurrent();
-
-  vertex_shader_ = context3d_->createShader(GL_VERTEX_SHADER);
-  context3d_->shaderSource(vertex_shader_, g_vertex_shader);
-  context3d_->compileShader(vertex_shader_);
-
-  fragment_shader_ = context3d_->createShader(GL_FRAGMENT_SHADER);
-  context3d_->shaderSource(fragment_shader_, g_fragment_shader);
-  context3d_->compileShader(fragment_shader_);
-
-  program_ = context3d_->createProgram();
-  context3d_->attachShader(program_, vertex_shader_);
-  context3d_->attachShader(program_, fragment_shader_);
-
-  vertex_buffer_ = context3d_->createBuffer();
-  context3d_->bindBuffer(GL_ARRAY_BUFFER, vertex_buffer_);
-  context3d_->bufferData(GL_ARRAY_BUFFER, 16 * sizeof(float), attribs,
-                         GL_STATIC_DRAW);
-  context3d_->enableVertexAttribArray(0);
-  context3d_->vertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
-  context3d_->bindAttribLocation(program_, 0, "a_Position");
-  context3d_->enableVertexAttribArray(1);
-  context3d_->vertexAttribPointer(
-      1, 2, GL_FLOAT, GL_FALSE, 0, 8 * sizeof(GLfloat));
-  context3d_->bindAttribLocation(program_, 1, "a_texCoord");
-
-  context3d_->linkProgram(program_);
-  context3d_->useProgram(program_);
-
-  int texture_uniform = context3d_->getUniformLocation(program_, "s_texture");
-  context3d_->uniform1i(texture_uniform, 0);
-  context3d_->disable(GL_SCISSOR_TEST);
-  context3d_->clearColor(0, 0, 1, 1);
-
-  texture_id_ = context3d_->createTexture();
-  context3d_->bindTexture(GL_TEXTURE_2D, texture_id_);
-  context3d_->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-  context3d_->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-  context3d_->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-  context3d_->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-}
-
-}  // namespace content
diff --git a/content/renderer/gpu/compositor_software_output_device_gl_adapter.h b/content/renderer/gpu/compositor_software_output_device_gl_adapter.h
deleted file mode 100644
index 66a1bed..0000000
--- a/content/renderer/gpu/compositor_software_output_device_gl_adapter.h
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_RENDERER_GPU_COMPOSITOR_SOFTWARE_OUTPUT_DEVICE_GL_ADAPTER_H_
-#define CONTENT_RENDERER_GPU_COMPOSITOR_SOFTWARE_OUTPUT_DEVICE_GL_ADAPTER_H_
-
-#include "base/memory/scoped_ptr.h"
-#include "base/threading/non_thread_safe.h"
-#include "cc/output/software_output_device.h"
-#include "third_party/WebKit/Source/Platform/chromium/public/WebGraphicsContext3D.h"
-
-namespace content {
-
-// This class can be created only on the main thread, but then becomes pinned
-// to a fixed thread when bindToClient is called.
-class CompositorSoftwareOutputDeviceGLAdapter
-    : NON_EXPORTED_BASE(public cc::SoftwareOutputDevice),
-      NON_EXPORTED_BASE(public base::NonThreadSafe) {
- public:
-  CompositorSoftwareOutputDeviceGLAdapter(
-      WebKit::WebGraphicsContext3D* context3d);
-  virtual ~CompositorSoftwareOutputDeviceGLAdapter();
-
-  virtual void Resize(gfx::Size size) OVERRIDE;
-  virtual void EndPaint(cc::SoftwareFrameData* frame_data) OVERRIDE;
-
- private:
-  void InitShaders();
-
-  unsigned program_;
-  unsigned vertex_shader_;
-  unsigned fragment_shader_;
-  unsigned vertex_buffer_;
-  unsigned texture_id_;
-  scoped_ptr<WebKit::WebGraphicsContext3D> context3d_;
-};
-
-}  // namespace content
-
-#endif  // CONTENT_RENDERER_GPU_COMPOSITOR_SOFTWARE_OUTPUT_DEVICE_GL_ADAPTER_H_
diff --git a/content/renderer/gpu/gpu_benchmarking_extension.cc b/content/renderer/gpu/gpu_benchmarking_extension.cc
index 8238b42..9d864de 100644
--- a/content/renderer/gpu/gpu_benchmarking_extension.cc
+++ b/content/renderer/gpu/gpu_benchmarking_extension.cc
@@ -14,6 +14,7 @@
 #include "content/common/gpu/gpu_rendering_stats.h"
 #include "content/public/renderer/render_thread.h"
 #include "content/renderer/all_rendering_benchmarks.h"
+#include "content/renderer/gpu/render_widget_compositor.h"
 #include "content/renderer/render_view_impl.h"
 #include "content/renderer/rendering_benchmark.h"
 #include "third_party/skia/include/core/SkGraphics.h"
@@ -22,6 +23,7 @@
 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
 #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
 #include "third_party/WebKit/Source/WebKit/chromium/public/WebViewBenchmarkSupport.h"
+#include "ui/gfx/codec/png_codec.h"
 #include "v8/include/v8.h"
 #include "webkit/compositor_bindings/web_rendering_stats_impl.h"
 
@@ -35,6 +37,15 @@
 
 const char kGpuBenchmarkingExtensionName[] = "v8/GpuBenchmarking";
 
+static bool PNGEncodeBitmapToStream(SkWStream* stream, const SkBitmap& bm) {
+    std::vector<unsigned char> vector;
+    if (gfx::PNGCodec::EncodeBGRASkBitmap(bm, true, &vector)) {
+        if (stream->write(&vector.front() , vector.size()))
+            return true;
+    }
+    return false;
+}
+
 namespace {
 
 // Always called on the main render thread.
@@ -73,7 +84,7 @@
     DCHECK(!filepath.empty());
     SkFILEWStream file(filepath.c_str());
     DCHECK(file.isValid());
-    picture_.serialize(&file);
+    picture_.serialize(&file, &PNGEncodeBitmapToStream);
   }
 
  private:
@@ -123,6 +134,10 @@
           "if (typeof(chrome.gpuBenchmarking) == 'undefined') {"
           "  chrome.gpuBenchmarking = {};"
           "};"
+          "chrome.gpuBenchmarking.setNeedsDisplayOnAllLayers = function() {"
+          "  native function SetNeedsDisplayOnAllLayers();"
+          "  return SetNeedsDisplayOnAllLayers();"
+          "};"
           "chrome.gpuBenchmarking.renderingStats = function() {"
           "  native function GetRenderingStats();"
           "  return GetRenderingStats();"
@@ -158,6 +173,8 @@
 
   virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction(
       v8::Handle<v8::String> name) OVERRIDE {
+    if (name->Equals(v8::String::New("SetNeedsDisplayOnAllLayers")))
+      return v8::FunctionTemplate::New(SetNeedsDisplayOnAllLayers);
     if (name->Equals(v8::String::New("GetRenderingStats")))
       return v8::FunctionTemplate::New(GetRenderingStats);
     if (name->Equals(v8::String::New("PrintToSkPicture")))
@@ -172,6 +189,29 @@
     return v8::Handle<v8::FunctionTemplate>();
   }
 
+  static v8::Handle<v8::Value> SetNeedsDisplayOnAllLayers(
+      const v8::Arguments& args) {
+    WebFrame* web_frame = WebFrame::frameForCurrentContext();
+    if (!web_frame)
+      return v8::Undefined();
+
+    WebView* web_view = web_frame->view();
+    if (!web_view)
+      return v8::Undefined();
+
+    RenderViewImpl* render_view_impl = RenderViewImpl::FromWebView(web_view);
+    if (!render_view_impl)
+      return v8::Undefined();
+
+    RenderWidgetCompositor* compositor = render_view_impl->compositor();
+    if (!compositor)
+      return v8::Undefined();
+
+    compositor->SetNeedsDisplayOnAllLayers();
+
+    return v8::Undefined();
+  }
+
   static v8::Handle<v8::Value> GetRenderingStats(const v8::Arguments& args) {
 
     WebFrame* web_frame = WebFrame::frameForCurrentContext();
@@ -277,11 +317,9 @@
     v8::Local<v8::Function> callback_local =
         v8::Local<v8::Function>(v8::Function::Cast(*args[1]));
     v8::Isolate* isolate = args.GetIsolate();
-    v8::Persistent<v8::Function> callback =
-        v8::Persistent<v8::Function>::New(isolate, callback_local);
-    v8::Persistent<v8::Context> context =
-        v8::Persistent<v8::Context>::New(isolate,
-                                         web_frame->mainWorldScriptContext());
+    v8::Persistent<v8::Function> callback(isolate, callback_local);
+    v8::Persistent<v8::Context> context(isolate,
+                                        web_frame->mainWorldScriptContext());
 
     int pixels_to_scroll = args[2]->IntegerValue();
 
@@ -332,7 +370,7 @@
       name_filter = "";
     } else {
       char filter[256];
-      args[0]->ToString()->WriteAscii(filter, 0, sizeof(filter)-1);
+      args[0]->ToString()->WriteUtf8(filter, sizeof(filter)-1);
       name_filter = std::string(filter);
     }
 
@@ -438,11 +476,9 @@
     v8::Local<v8::Function> callback_local =
         v8::Local<v8::Function>(v8::Function::Cast(*args[0]));
     v8::Isolate* isolate = args.GetIsolate();
-    v8::Persistent<v8::Function> callback =
-        v8::Persistent<v8::Function>::New(isolate, callback_local);
-    v8::Persistent<v8::Context> context =
-        v8::Persistent<v8::Context>::New(isolate,
-                                         web_frame->mainWorldScriptContext());
+    v8::Persistent<v8::Function> callback(isolate, callback_local);
+    v8::Persistent<v8::Context> context(isolate,
+                                        web_frame->mainWorldScriptContext());
 
     render_view_impl->GetWindowSnapshot(
         base::Bind(&OnSnapshotCompleted, callback, context));
diff --git a/content/renderer/gpu/input_event_filter.cc b/content/renderer/gpu/input_event_filter.cc
index 79ab8b7..96a7034 100644
--- a/content/renderer/gpu/input_event_filter.cc
+++ b/content/renderer/gpu/input_event_filter.cc
@@ -6,7 +6,7 @@
 #include "base/debug/trace_event.h"
 #include "base/location.h"
 #include "base/message_loop_proxy.h"
-#include "content/common/view_messages.h"
+#include "content/common/input_messages.h"
 #include "content/renderer/gpu/input_event_filter.h"
 
 using WebKit::WebInputEvent;
@@ -74,8 +74,17 @@
   sender_ = NULL;
 }
 
+// This function returns true if the IPC message is one that the compositor
+// thread can handle *or* one that needs to preserve relative order with
+// messages that the compositor thread can handle. Returning true for a message
+// type means that the message will go through an extra copy and thread hop, so
+// use with care.
+static bool RequiresThreadBounce(const IPC::Message& message) {
+  return IPC_MESSAGE_ID_CLASS(message.type()) == InputMsgStart;
+}
+
 bool InputEventFilter::OnMessageReceived(const IPC::Message& message) {
-  if (message.type() != ViewMsg_HandleInputEvent::ID)
+  if (!RequiresThreadBounce(message))
     return false;
 
   {
@@ -93,7 +102,7 @@
 // static
 const WebInputEvent* InputEventFilter::CrackMessage(
     const IPC::Message& message) {
-  DCHECK(message.type() == ViewMsg_HandleInputEvent::ID);
+  DCHECK(message.type() == InputMsg_HandleInputEvent::ID);
 
   PickleIterator iter(message);
   const WebInputEvent* event = NULL;
@@ -111,6 +120,14 @@
 void InputEventFilter::ForwardToHandler(const IPC::Message& message) {
   DCHECK(target_loop_->BelongsToCurrentThread());
 
+  if (message.type() != InputMsg_HandleInputEvent::ID) {
+    main_loop_->PostTask(
+        FROM_HERE,
+        base::Bind(&InputEventFilter::ForwardToMainListener,
+                   this, message));
+    return;
+  }
+
   // Save this message for later, in case we need to bounce it back up to the
   // main listener.
   //
@@ -143,7 +160,8 @@
     return;  // Filter was removed.
 
   sender_->Send(
-      new ViewHostMsg_HandleInputEvent_ACK(routing_id, event_type, ack_result));
+      new InputHostMsg_HandleInputEvent_ACK(
+          routing_id, event_type, ack_result));
 }
 
 }  // namespace content
diff --git a/content/renderer/gpu/input_event_filter.h b/content/renderer/gpu/input_event_filter.h
index 855e844..9e94819 100644
--- a/content/renderer/gpu/input_event_filter.h
+++ b/content/renderer/gpu/input_event_filter.h
@@ -15,7 +15,7 @@
 #include "ipc/ipc_channel_proxy.h"
 #include "third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h"
 
-// This class can be used to intercept ViewMsg_HandleInputEvent messages
+// This class can be used to intercept InputMsg_HandleInputEvent messages
 // and have them be delivered to a target thread.  Input events are filtered
 // based on routing_id (see AddRoute and RemoveRoute).
 //
@@ -38,11 +38,12 @@
   // must be called on the target thread.
   //
   // If DidNotHandleInputEvent is called with send_to_widget set to true, then
-  // the original ViewMsg_HandleInputEvent message will be delivered to
+  // the original InputMsg_HandleInputEvent message will be delivered to
   // |main_listener| on the main thread.  (The "main thread" in this context is
   // the thread where the InputEventFilter was constructed.)  If send_to_widget
-  // is true, then a ViewHostMsg_HandleInputEvent_ACK will not be generated,
-  // leaving that responsibility up to the eventual handler on the main thread.
+  // is true, then a InputHostMsg_HandleInputEvent_ACK will not be
+  // generated, leaving that responsibility up to the eventual handler on the
+  // main thread.
   //
   InputEventFilter(IPC::Listener* main_listener,
                    const scoped_refptr<base::MessageLoopProxy>& target_loop,
@@ -62,7 +63,7 @@
   virtual void OnChannelClosing() OVERRIDE;
   virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
 
-  // Expects a ViewMsg_HandleInputEvent message.
+  // Expects a InputMsg_HandleInputEvent message.
   static const WebKit::WebInputEvent* CrackMessage(const IPC::Message& message);
 
  private:
diff --git a/content/renderer/gpu/input_event_filter_unittest.cc b/content/renderer/gpu/input_event_filter_unittest.cc
index 32b7bc1..24064db 100644
--- a/content/renderer/gpu/input_event_filter_unittest.cc
+++ b/content/renderer/gpu/input_event_filter_unittest.cc
@@ -8,6 +8,7 @@
 
 #include "base/bind.h"
 #include "base/message_loop.h"
+#include "content/common/input_messages.h"
 #include "content/common/view_messages.h"
 #include "content/renderer/gpu/input_event_filter.h"
 #include "ipc/ipc_test_sink.h"
@@ -103,87 +104,107 @@
   event->y = y;
 }
 
+void AddMessagesToFilter(IPC::ChannelProxy::MessageFilter* message_filter,
+                         const std::vector<IPC::Message>& events) {
+  for (size_t i = 0; i < events.size(); ++i) {
+    message_filter->OnMessageReceived(events[i]);
+  }
+
+  base::MessageLoop::current()->RunUntilIdle();
+}
+
 void AddEventsToFilter(IPC::ChannelProxy::MessageFilter* message_filter,
                        const WebMouseEvent events[],
                        size_t count) {
+  std::vector<IPC::Message> messages;
   for (size_t i = 0; i < count; ++i) {
-    ViewMsg_HandleInputEvent message(kTestRoutingID, &events[i], false);
-    message_filter->OnMessageReceived(message);
+    messages.push_back(
+        InputMsg_HandleInputEvent(kTestRoutingID, &events[i], false));
   }
 
-  MessageLoop::current()->RunUntilIdle();
+  AddMessagesToFilter(message_filter, messages);
 }
 
 }  // namespace
 
-TEST(InputEventFilterTest, Basic) {
-  MessageLoop message_loop;
+class InputEventFilterTest : public testing::Test {
+ public:
+  virtual void SetUp() OVERRIDE {
+    filter_ = new InputEventFilter(
+        &message_recorder_,
+        message_loop_.message_loop_proxy(),
+        base::Bind(&InputEventRecorder::HandleInputEvent,
+            base::Unretained(&event_recorder_)));
+    event_recorder_.set_filter(filter_);
+
+    filter_->OnFilterAdded(&ipc_sink_);
+  }
+
+
+ protected:
+  base::MessageLoop message_loop_;
 
   // Used to record IPCs sent by the filter to the RenderWidgetHost.
-  IPC::TestSink ipc_sink;
+  IPC::TestSink ipc_sink_;
 
   // Used to record IPCs forwarded by the filter to the main thread.
-  IPCMessageRecorder message_recorder;
+  IPCMessageRecorder message_recorder_;
 
   // Used to record WebInputEvents delivered to the handler.
-  InputEventRecorder event_recorder;
+  InputEventRecorder event_recorder_;
 
-  scoped_refptr<InputEventFilter> filter =
-      new InputEventFilter(&message_recorder,
-                           message_loop.message_loop_proxy(),
-                           base::Bind(&InputEventRecorder::HandleInputEvent,
-                                      base::Unretained(&event_recorder)));
-  event_recorder.set_filter(filter);
+  scoped_refptr<InputEventFilter> filter_;
+};
 
-  filter->OnFilterAdded(&ipc_sink);
-
+TEST_F(InputEventFilterTest, Basic) {
   WebMouseEvent kEvents[3];
   InitMouseEvent(&kEvents[0], WebInputEvent::MouseDown, 10, 10);
   InitMouseEvent(&kEvents[1], WebInputEvent::MouseMove, 20, 20);
   InitMouseEvent(&kEvents[2], WebInputEvent::MouseUp, 30, 30);
 
-  AddEventsToFilter(filter, kEvents, arraysize(kEvents));
-  EXPECT_EQ(0U, ipc_sink.message_count());
-  EXPECT_EQ(0U, event_recorder.record_count());
-  EXPECT_EQ(0U, message_recorder.message_count());
+  AddEventsToFilter(filter_, kEvents, arraysize(kEvents));
+  EXPECT_EQ(0U, ipc_sink_.message_count());
+  EXPECT_EQ(0U, event_recorder_.record_count());
+  EXPECT_EQ(0U, message_recorder_.message_count());
 
-  filter->AddRoute(kTestRoutingID);
+  filter_->AddRoute(kTestRoutingID);
 
-  AddEventsToFilter(filter, kEvents, arraysize(kEvents));
-  ASSERT_EQ(arraysize(kEvents), ipc_sink.message_count());
-  ASSERT_EQ(arraysize(kEvents), event_recorder.record_count());
-  EXPECT_EQ(0U, message_recorder.message_count());
+  AddEventsToFilter(filter_, kEvents, arraysize(kEvents));
+  ASSERT_EQ(arraysize(kEvents), ipc_sink_.message_count());
+  ASSERT_EQ(arraysize(kEvents), event_recorder_.record_count());
+  EXPECT_EQ(0U, message_recorder_.message_count());
 
   for (size_t i = 0; i < arraysize(kEvents); ++i) {
-    const IPC::Message* message = ipc_sink.GetMessageAt(i);
+    const IPC::Message* message = ipc_sink_.GetMessageAt(i);
     EXPECT_EQ(kTestRoutingID, message->routing_id());
-    EXPECT_EQ(ViewHostMsg_HandleInputEvent_ACK::ID, message->type());
+    EXPECT_EQ(InputHostMsg_HandleInputEvent_ACK::ID, message->type());
 
     WebInputEvent::Type event_type = WebInputEvent::Undefined;
     InputEventAckState ack_result = INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
-    EXPECT_TRUE(ViewHostMsg_HandleInputEvent_ACK::Read(message, &event_type,
-                                                       &ack_result));
+    EXPECT_TRUE(InputHostMsg_HandleInputEvent_ACK::Read(message,
+                                                            &event_type,
+                                                            &ack_result));
     EXPECT_EQ(kEvents[i].type, event_type);
     EXPECT_EQ(ack_result, INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
 
-    const WebInputEvent* event = event_recorder.record_at(i);
+    const WebInputEvent* event = event_recorder_.record_at(i);
     ASSERT_TRUE(event);
 
     EXPECT_EQ(kEvents[i].size, event->size);
     EXPECT_TRUE(memcmp(&kEvents[i], event, event->size) == 0);
   }
 
-  event_recorder.set_send_to_widget(true);
+  event_recorder_.set_send_to_widget(true);
 
-  AddEventsToFilter(filter, kEvents, arraysize(kEvents));
-  EXPECT_EQ(arraysize(kEvents), ipc_sink.message_count());
-  EXPECT_EQ(2 * arraysize(kEvents), event_recorder.record_count());
-  EXPECT_EQ(arraysize(kEvents), message_recorder.message_count());
+  AddEventsToFilter(filter_, kEvents, arraysize(kEvents));
+  EXPECT_EQ(arraysize(kEvents), ipc_sink_.message_count());
+  EXPECT_EQ(2 * arraysize(kEvents), event_recorder_.record_count());
+  EXPECT_EQ(arraysize(kEvents), message_recorder_.message_count());
 
   for (size_t i = 0; i < arraysize(kEvents); ++i) {
-    const IPC::Message& message = message_recorder.message_at(i);
+    const IPC::Message& message = message_recorder_.message_at(i);
 
-    ASSERT_EQ(ViewMsg_HandleInputEvent::ID, message.type());
+    ASSERT_EQ(InputMsg_HandleInputEvent::ID, message.type());
     const WebInputEvent* event = InputEventFilter::CrackMessage(message);
 
     EXPECT_EQ(kEvents[i].size, event->size);
@@ -192,31 +213,84 @@
 
   // Now reset everything, and test that DidHandleInputEvent is called.
 
-  ipc_sink.ClearMessages();
-  event_recorder.Clear();
-  message_recorder.Clear();
+  ipc_sink_.ClearMessages();
+  event_recorder_.Clear();
+  message_recorder_.Clear();
 
-  event_recorder.set_handle_events(true);
+  event_recorder_.set_handle_events(true);
 
-  AddEventsToFilter(filter, kEvents, arraysize(kEvents));
-  EXPECT_EQ(arraysize(kEvents), ipc_sink.message_count());
-  EXPECT_EQ(arraysize(kEvents), event_recorder.record_count());
-  EXPECT_EQ(0U, message_recorder.message_count());
+  AddEventsToFilter(filter_, kEvents, arraysize(kEvents));
+  EXPECT_EQ(arraysize(kEvents), ipc_sink_.message_count());
+  EXPECT_EQ(arraysize(kEvents), event_recorder_.record_count());
+  EXPECT_EQ(0U, message_recorder_.message_count());
 
   for (size_t i = 0; i < arraysize(kEvents); ++i) {
-    const IPC::Message* message = ipc_sink.GetMessageAt(i);
+    const IPC::Message* message = ipc_sink_.GetMessageAt(i);
     EXPECT_EQ(kTestRoutingID, message->routing_id());
-    EXPECT_EQ(ViewHostMsg_HandleInputEvent_ACK::ID, message->type());
+    EXPECT_EQ(InputHostMsg_HandleInputEvent_ACK::ID, message->type());
 
     WebInputEvent::Type event_type = WebInputEvent::Undefined;
     InputEventAckState ack_result = INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
-    EXPECT_TRUE(ViewHostMsg_HandleInputEvent_ACK::Read(message, &event_type,
-                                                       &ack_result));
+    EXPECT_TRUE(InputHostMsg_HandleInputEvent_ACK::Read(message,
+                                                            &event_type,
+                                                            &ack_result));
     EXPECT_EQ(kEvents[i].type, event_type);
     EXPECT_EQ(ack_result, INPUT_EVENT_ACK_STATE_CONSUMED);
   }
 
-  filter->OnFilterRemoved();
+  filter_->OnFilterRemoved();
+}
+
+TEST_F(InputEventFilterTest, PreserveRelativeOrder) {
+  filter_->AddRoute(kTestRoutingID);
+  event_recorder_.set_send_to_widget(true);
+
+
+  WebMouseEvent mouse_down;
+  mouse_down.type = WebMouseEvent::MouseDown;
+  WebMouseEvent mouse_up;
+  mouse_up.type = WebMouseEvent::MouseUp;
+
+  std::vector<IPC::Message> messages;
+  messages.push_back(InputMsg_HandleInputEvent(kTestRoutingID,
+                                              &mouse_down,
+                                              false));
+  // Control where input events are delivered.
+  messages.push_back(InputMsg_MouseCaptureLost(kTestRoutingID));
+  messages.push_back(InputMsg_SetFocus(kTestRoutingID, true));
+
+  // Editing operations
+  messages.push_back(InputMsg_Undo(kTestRoutingID));
+  messages.push_back(InputMsg_Redo(kTestRoutingID));
+  messages.push_back(InputMsg_Cut(kTestRoutingID));
+  messages.push_back(InputMsg_Copy(kTestRoutingID));
+#if defined(OS_MACOSX)
+  messages.push_back(InputMsg_CopyToFindPboard(kTestRoutingID));
+#endif
+  messages.push_back(InputMsg_Paste(kTestRoutingID));
+  messages.push_back(InputMsg_PasteAndMatchStyle(kTestRoutingID));
+  messages.push_back(InputMsg_Delete(kTestRoutingID));
+  messages.push_back(InputMsg_Replace(kTestRoutingID, string16()));
+  messages.push_back(InputMsg_ReplaceMisspelling(kTestRoutingID,
+                                                     string16()));
+  messages.push_back(InputMsg_Delete(kTestRoutingID));
+  messages.push_back(InputMsg_SelectAll(kTestRoutingID));
+  messages.push_back(InputMsg_Unselect(kTestRoutingID));
+  messages.push_back(InputMsg_SelectRange(kTestRoutingID,
+                                         gfx::Point(), gfx::Point()));
+  messages.push_back(InputMsg_MoveCaret(kTestRoutingID, gfx::Point()));
+
+  messages.push_back(InputMsg_HandleInputEvent(kTestRoutingID,
+                                              &mouse_up,
+                                              false));
+  AddMessagesToFilter(filter_, messages);
+
+  // We should have sent all messages back to the main thread and preserved
+  // their relative order.
+  ASSERT_EQ(message_recorder_.message_count(), messages.size());
+  for (size_t i = 0; i < messages.size(); ++i) {
+    EXPECT_EQ(message_recorder_.message_at(i).type(), messages[i].type()) << i;
+  }
 }
 
 }  // namespace content
diff --git a/content/renderer/gpu/mailbox_output_surface.cc b/content/renderer/gpu/mailbox_output_surface.cc
index 6a35548..936f466 100644
--- a/content/renderer/gpu/mailbox_output_surface.cc
+++ b/content/renderer/gpu/mailbox_output_surface.cc
@@ -15,25 +15,39 @@
 using cc::CompositorFrame;
 using cc::GLFrameData;
 using gpu::Mailbox;
-using WebKit::WebGraphicsContext3D;
 
 namespace content {
 
 MailboxOutputSurface::MailboxOutputSurface(
     int32 routing_id,
-    WebGraphicsContext3D* context3D,
+    WebGraphicsContext3DCommandBufferImpl* context3D,
     cc::SoftwareOutputDevice* software_device)
     : CompositorOutputSurface(routing_id, context3D, software_device),
       fbo_(0),
       is_backbuffer_discarded_(false) {
   pending_textures_.push_back(TransferableFrame());
+  capabilities_.max_frames_pending = 1;
 }
 
 MailboxOutputSurface::~MailboxOutputSurface() {
   DiscardBackbuffer();
+  DCHECK(!pending_textures_.empty());
+  bool cleared_errors = false;
   while (!pending_textures_.empty()) {
-    if (pending_textures_.front().texture_id)
+    TransferableFrame& frame = pending_textures_.front();
+    if (frame.texture_id) {
+      // TODO: crbug.com/230137 - make workaround obsolete with refcounting.
+      if (!cleared_errors) {
+        GLuint error;
+        while ((error = context3d_->getError()) != GL_NO_ERROR)
+          LOG(ERROR) << "Pending GL error during surface tear-down: " << error;
+        cleared_errors = true;
+      }
+      frame.sync_point = 0;
+      ConsumeTexture(frame);  // Don't let the texture leak in the mailbox.
+      context3d_->getError();  // Clear error if mailbox was empty.
       context3d_->deleteTexture(pending_textures_.front().texture_id);
+    }
     pending_textures_.pop_front();
   }
 }
@@ -130,10 +144,7 @@
 
   context3d_->framebufferTexture2D(
       GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
-// TODO(sievers): Remove ifdef (crbug.com/222018)
-#ifndef NDEBUG
   context3d_->bindFramebuffer(GL_FRAMEBUFFER, 0);
-#endif
   context3d_->bindTexture(GL_TEXTURE_2D, current_backing_.texture_id);
   context3d_->produceTextureCHROMIUM(
       GL_TEXTURE_2D, current_backing_.mailbox.name);
@@ -186,15 +197,16 @@
   CompositorOutputSurface::OnSwapAck(ack);
 }
 
-void MailboxOutputSurface::SwapBuffers() {
+void MailboxOutputSurface::SwapBuffers(const cc::LatencyInfo&) {
 }
 
-void MailboxOutputSurface::PostSubBuffer(gfx::Rect rect) {
+void MailboxOutputSurface::PostSubBuffer(gfx::Rect rect,
+                                         const cc::LatencyInfo&) {
   NOTIMPLEMENTED()
       << "Partial swap not supported with composite-to-mailbox yet.";
 
   // The browser only copies damage correctly for two buffers in use.
-  DCHECK(GetNumAcksPending() < 3);
+  DCHECK(GetNumAcksPending() < 2);
 }
 
 void MailboxOutputSurface::ConsumeTexture(const TransferableFrame& frame) {
diff --git a/content/renderer/gpu/mailbox_output_surface.h b/content/renderer/gpu/mailbox_output_surface.h
index 1ad755f..7c159be 100644
--- a/content/renderer/gpu/mailbox_output_surface.h
+++ b/content/renderer/gpu/mailbox_output_surface.h
@@ -24,7 +24,7 @@
 class MailboxOutputSurface : public CompositorOutputSurface {
  public:
   MailboxOutputSurface(int32 routing_id,
-                       WebKit::WebGraphicsContext3D* context3d,
+                       WebGraphicsContext3DCommandBufferImpl* context3d,
                        cc::SoftwareOutputDevice* software);
   virtual ~MailboxOutputSurface();
 
@@ -34,8 +34,8 @@
   virtual void DiscardBackbuffer() OVERRIDE;
   virtual void Reshape(gfx::Size size) OVERRIDE;
   virtual void BindFramebuffer() OVERRIDE;
-  virtual void PostSubBuffer(gfx::Rect rect) OVERRIDE;
-  virtual void SwapBuffers() OVERRIDE;
+  virtual void PostSubBuffer(gfx::Rect rect, const cc::LatencyInfo&) OVERRIDE;
+  virtual void SwapBuffers(const cc::LatencyInfo&) OVERRIDE;
 
  private:
   // CompositorOutputSurface overrides.
diff --git a/content/renderer/gpu/render_widget_compositor.cc b/content/renderer/gpu/render_widget_compositor.cc
index b5f5f9d..6c59463 100644
--- a/content/renderer/gpu/render_widget_compositor.cc
+++ b/content/renderer/gpu/render_widget_compositor.cc
@@ -89,6 +89,9 @@
   settings.accelerate_painting =
       cmd->HasSwitch(switches::kEnableAcceleratedPainting);
   settings.render_vsync_enabled = !cmd->HasSwitch(switches::kDisableGpuVsync);
+  settings.render_vsync_notification_enabled =
+      cmd->HasSwitch(switches::kEnableVsyncNotification);
+  settings.synchronously_disable_vsync = widget->SynchronouslyDisableVSync();
   settings.per_tile_painting_enabled =
       cmd->HasSwitch(cc::switches::kEnablePerTilePainting);
   settings.accelerated_animation_enabled =
@@ -126,10 +129,8 @@
   settings.right_aligned_scheduling_enabled =
       cmd->HasSwitch(cc::switches::kEnableRightAlignedScheduling);
   settings.impl_side_painting = cc::switches::IsImplSidePaintingEnabled();
-  settings.use_cheapness_estimator =
-      !cmd->HasSwitch(cc::switches::kDisableCheapnessEstimator);
   settings.use_color_estimator =
-      cmd->HasSwitch(cc::switches::kUseColorEstimator);
+      !cmd->HasSwitch(cc::switches::kDisableColorEstimator);
   settings.prediction_benchmarking =
       cmd->HasSwitch(cc::switches::kEnablePredictionBenchmarking);
 
@@ -180,6 +181,11 @@
   settings.show_overdraw_in_tracing =
       cmd->HasSwitch(cc::switches::kTraceOverdraw);
 
+#if defined(OS_WIN) || defined(OS_LINUX) || defined(OS_CHROMEOS)
+  settings.use_pinch_zoom_scrollbars =
+      cmd->HasSwitch(cc::switches::kEnablePinchZoomScrollbars);
+#endif
+
   // These flags should be mirrored by UI versions in ui/compositor/.
   settings.initial_debug_state.show_debug_borders =
       cmd->HasSwitch(cc::switches::kShowCompositedLayerBorders);
@@ -237,6 +243,30 @@
                           &settings.low_res_contents_scale_factor);
   }
 
+  if (cmd->HasSwitch(cc::switches::kMaxTilesForInterestArea)) {
+    int max_tiles_for_interest_area;
+    if (GetSwitchValueAsInt(*cmd,
+                            cc::switches::kMaxTilesForInterestArea,
+                            1, std::numeric_limits<int>::max(),
+                            &max_tiles_for_interest_area))
+      settings.max_tiles_for_interest_area = max_tiles_for_interest_area;
+  }
+
+  if (cmd->HasSwitch(cc::switches::kMaxUnusedResourceMemoryUsagePercentage)) {
+    int max_unused_resource_memory_percentage;
+    if (GetSwitchValueAsInt(
+            *cmd,
+            cc::switches::kMaxUnusedResourceMemoryUsagePercentage,
+            0, 100,
+            &max_unused_resource_memory_percentage)) {
+      settings.max_unused_resource_memory_percentage =
+          max_unused_resource_memory_percentage;
+    }
+  }
+
+  settings.strict_layer_property_change_checking =
+      cmd->HasSwitch(cc::switches::kStrictLayerPropertyChangeChecking);
+
 #if defined(OS_ANDROID)
   // TODO(danakj): Move these to the android code.
   settings.can_use_lcd_text = false;
@@ -245,6 +275,7 @@
   settings.solid_color_scrollbars = true;
   settings.solid_color_scrollbar_color = SkColorSetARGB(128, 128, 128, 128);
   settings.solid_color_scrollbar_thickness_dip = 3;
+  settings.highp_threshold_min = 2048;
 #endif
 
   if (!compositor->initialize(settings))
@@ -281,6 +312,10 @@
   layer_tree_host_->Composite(frame_begin_time);
 }
 
+void RenderWidgetCompositor::SetNeedsDisplayOnAllLayers() {
+  layer_tree_host_->SetNeedsDisplayOnAllLayers();
+}
+
 void RenderWidgetCompositor::GetRenderingStats(cc::RenderingStats* stats) {
   layer_tree_host_->CollectRenderingStats(stats);
 }
@@ -289,8 +324,12 @@
   return layer_tree_host_->CapturePicture();
 }
 
-void RenderWidgetCompositor::EnableHidingTopControls(bool enable) {
-  layer_tree_host_->EnableHidingTopControls(enable);
+void RenderWidgetCompositor::UpdateTopControlsState(bool enable_hiding,
+                                                    bool enable_showing,
+                                                    bool animate) {
+  layer_tree_host_->UpdateTopControlsState(enable_hiding,
+                                           enable_showing,
+                                           animate);
 }
 
 void RenderWidgetCompositor::SetOverdrawBottomHeight(
@@ -298,6 +337,10 @@
   layer_tree_host_->SetOverdrawBottomHeight(overdraw_bottom_height);
 }
 
+void RenderWidgetCompositor::SetNeedsRedrawRect(gfx::Rect damage_rect) {
+  layer_tree_host_->SetNeedsRedrawRect(damage_rect);
+}
+
 bool RenderWidgetCompositor::initialize(cc::LayerTreeSettings settings) {
   scoped_ptr<cc::Thread> impl_thread;
   scoped_refptr<base::MessageLoopProxy> compositor_message_loop_proxy =
@@ -327,13 +370,13 @@
 }
 
 void RenderWidgetCompositor::setViewportSize(
-    const WebSize& layout_viewport_size,
+    const WebSize&,
     const WebSize& device_viewport_size) {
-  layer_tree_host_->SetViewportSize(layout_viewport_size, device_viewport_size);
+  layer_tree_host_->SetViewportSize(device_viewport_size);
 }
 
 WebSize RenderWidgetCompositor::layoutViewportSize() const {
-  return layer_tree_host_->layout_viewport_size();
+  return layer_tree_host_->device_viewport_size();
 }
 
 WebSize RenderWidgetCompositor::deviceViewportSize() const {
@@ -479,8 +522,9 @@
     widget_->webwidget()->didExitCompositingMode();
 }
 
-scoped_ptr<cc::InputHandler> RenderWidgetCompositor::CreateInputHandler() {
-  scoped_ptr<cc::InputHandler> ret;
+scoped_ptr<cc::InputHandlerClient>
+RenderWidgetCompositor::CreateInputHandlerClient() {
+  scoped_ptr<cc::InputHandlerClient> ret;
   scoped_ptr<WebKit::WebInputHandler> web_handler(
       widget_->webwidget()->createInputHandler());
   if (web_handler)
diff --git a/content/renderer/gpu/render_widget_compositor.h b/content/renderer/gpu/render_widget_compositor.h
index de68d4a..ecb9f57 100644
--- a/content/renderer/gpu/render_widget_compositor.h
+++ b/content/renderer/gpu/render_widget_compositor.h
@@ -11,6 +11,7 @@
 #include "cc/trees/layer_tree_settings.h"
 #include "skia/ext/refptr.h"
 #include "third_party/WebKit/Source/Platform/chromium/public/WebLayerTreeView.h"
+#include "ui/gfx/rect.h"
 
 class SkPicture;
 
@@ -33,17 +34,21 @@
   void SetSuppressScheduleComposite(bool suppress);
   void Animate(base::TimeTicks time);
   void Composite(base::TimeTicks frame_begin_time);
+  void SetNeedsDisplayOnAllLayers();
   void GetRenderingStats(cc::RenderingStats* stats);
   skia::RefPtr<SkPicture> CapturePicture();
-  void EnableHidingTopControls(bool enable);
+  void UpdateTopControlsState(bool enable_hiding,
+                              bool enable_showing,
+                              bool animate);
   void SetOverdrawBottomHeight(float overdraw_bottom_height);
+  void SetNeedsRedrawRect(gfx::Rect damage_rect);
 
   // WebLayerTreeView implementation.
   virtual void setSurfaceReady();
   virtual void setRootLayer(const WebKit::WebLayer& layer);
   virtual void clearRootLayer();
   virtual void setViewportSize(
-      const WebKit::WebSize& layout_viewport_size,
+      const WebKit::WebSize& unused_deprecated,
       const WebKit::WebSize& device_viewport_size);
   virtual WebKit::WebSize layoutViewportSize() const;
   virtual WebKit::WebSize deviceViewportSize() const;
@@ -84,7 +89,8 @@
                                    float page_scale) OVERRIDE;
   virtual scoped_ptr<cc::OutputSurface> CreateOutputSurface() OVERRIDE;
   virtual void DidRecreateOutputSurface(bool success) OVERRIDE;
-  virtual scoped_ptr<cc::InputHandler> CreateInputHandler() OVERRIDE;
+  virtual scoped_ptr<cc::InputHandlerClient> CreateInputHandlerClient()
+      OVERRIDE;
   virtual void WillCommit() OVERRIDE;
   virtual void DidCommit() OVERRIDE;
   virtual void DidCommitAndDrawFrame() OVERRIDE;
@@ -109,4 +115,3 @@
 }  // namespace content
 
 #endif  // CONTENT_RENDERER_GPU_RENDER_WIDGET_COMPOSITOR_H_
-
diff --git a/content/renderer/gpu/stream_texture_host_android.cc b/content/renderer/gpu/stream_texture_host_android.cc
index a924ddc..f3de1f0 100644
--- a/content/renderer/gpu/stream_texture_host_android.cc
+++ b/content/renderer/gpu/stream_texture_host_android.cc
@@ -16,7 +16,7 @@
       stream_id_(0),
       listener_(NULL),
       channel_(channel),
-      ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) {
+      weak_ptr_factory_(this) {
   DCHECK(channel);
 }
 
@@ -53,7 +53,7 @@
 }
 
 void StreamTextureHost::EstablishPeer(int32 primary_id, int32 secondary_id) {
-  if (channel_.get()) {
+  if (channel_) {
     channel_->Send(new GpuChannelMsg_EstablishStreamTexture(
         stream_id_, primary_id, secondary_id));
   }
diff --git a/content/renderer/hyphenator/hyphenator.cc b/content/renderer/hyphenator/hyphenator.cc
index ae60fd8..564fe46 100644
--- a/content/renderer/hyphenator/hyphenator.cc
+++ b/content/renderer/hyphenator/hyphenator.cc
@@ -24,7 +24,7 @@
 // times. This class incrementally counts the number of converted UTF-16
 // characters to avoid this problem.
 //
-//   scoped_array<size_t> position(new size_t[text.length()]);
+//   scoped_ptr<size_t[]> position(new size_t[text.length()]);
 //   for (size_t i = 0; i < text.length(); ++i)
 //     position[i] = UTF8ToUTF16(text.substr(0, i)).length();
 //
@@ -98,7 +98,7 @@
   std::string word_utf8_;
 
   // Return variables from the hyphen library.
-  scoped_array<char> hyphen_vector_;
+  scoped_ptr<char[]> hyphen_vector_;
   char** rep_;
   int* pos_;
   int* cut_;
diff --git a/content/renderer/idle_user_detector.cc b/content/renderer/idle_user_detector.cc
index 1831fa9..6d5200c 100644
--- a/content/renderer/idle_user_detector.cc
+++ b/content/renderer/idle_user_detector.cc
@@ -5,7 +5,7 @@
 #include "content/renderer/idle_user_detector.h"
 
 #include "base/logging.h"
-#include "content/common/view_messages.h"
+#include "content/common/input_messages.h"
 #include "content/public/renderer/content_renderer_client.h"
 #include "content/renderer/render_thread_impl.h"
 
@@ -20,7 +20,7 @@
 
 bool IdleUserDetector::OnMessageReceived(const IPC::Message& message) {
   IPC_BEGIN_MESSAGE_MAP(IdleUserDetector, message)
-    IPC_MESSAGE_HANDLER(ViewMsg_HandleInputEvent, OnHandleInputEvent)
+    IPC_MESSAGE_HANDLER(InputMsg_HandleInputEvent, OnHandleInputEvent)
   IPC_END_MESSAGE_MAP()
   return false;
 }
diff --git a/content/renderer/image_loading_helper.cc b/content/renderer/image_loading_helper.cc
new file mode 100644
index 0000000..ff6e2bd
--- /dev/null
+++ b/content/renderer/image_loading_helper.cc
@@ -0,0 +1,127 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/image_loading_helper.h"
+
+#include "base/bind.h"
+#include "base/message_loop.h"
+#include "content/common/image_messages.h"
+#include "content/public/common/url_constants.h"
+#include "content/public/renderer/render_view.h"
+#include "net/base/data_url.h"
+#include "third_party/WebKit/Source/Platform/chromium/public/WebURLRequest.h"
+#include "third_party/WebKit/Source/Platform/chromium/public/WebVector.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
+#include "ui/gfx/favicon_size.h"
+#include "ui/gfx/size.h"
+#include "ui/gfx/skbitmap_operations.h"
+#include "webkit/glue/image_decoder.h"
+#include "webkit/glue/multi_resolution_image_resource_fetcher.h"
+#include "webkit/glue/webkit_glue.h"
+
+using WebKit::WebFrame;
+using WebKit::WebVector;
+using WebKit::WebURL;
+using WebKit::WebURLRequest;
+using webkit_glue::MultiResolutionImageResourceFetcher;
+
+namespace content {
+
+ImageLoadingHelper::ImageLoadingHelper(RenderView* render_view)
+    : RenderViewObserver(render_view) {
+}
+
+ImageLoadingHelper::~ImageLoadingHelper() {
+}
+
+void ImageLoadingHelper::OnDownloadImage(int id,
+                                         const GURL& image_url,
+                                         bool is_favicon,
+                                         int image_size) {
+  std::vector<SkBitmap> result_images;
+  if (image_url.SchemeIs(chrome::kDataScheme)) {
+    SkBitmap data_image = ImageFromDataUrl(image_url);
+    if (!data_image.empty())
+      result_images.push_back(data_image);
+  } else {
+    if (DownloadImage(id, image_url, is_favicon, image_size)) {
+      // Will complete asynchronously via ImageLoadingHelper::DidDownloadImage
+      return;
+    }
+  }
+
+  Send(new ImageHostMsg_DidDownloadImage(routing_id(),
+                                         id,
+                                         image_url,
+                                         image_size,
+                                         result_images));
+}
+
+bool ImageLoadingHelper::DownloadImage(int id,
+                                       const GURL& image_url,
+                                       bool is_favicon,
+                                       int image_size) {
+  // Make sure webview was not shut down.
+  if (!render_view()->GetWebView())
+    return false;
+  // Create an image resource fetcher and assign it with a call back object.
+  image_fetchers_.push_back(new MultiResolutionImageResourceFetcher(
+      image_url,
+      render_view()->GetWebView()->mainFrame(),
+      id,
+      is_favicon ? WebURLRequest::TargetIsFavicon :
+                   WebURLRequest::TargetIsImage,
+      base::Bind(&ImageLoadingHelper::DidDownloadImage,
+                 base::Unretained(this), image_size)));
+  return true;
+}
+
+void ImageLoadingHelper::DidDownloadImage(
+    int requested_size,
+    MultiResolutionImageResourceFetcher* fetcher,
+    const std::vector<SkBitmap>& images) {
+  // Notify requester of image download status.
+  Send(new ImageHostMsg_DidDownloadImage(routing_id(),
+                                         fetcher->id(),
+                                         fetcher->image_url(),
+                                         requested_size,
+                                         images));
+
+  // Remove the image fetcher from our pending list. We're in the callback from
+  // MultiResolutionImageResourceFetcher, best to delay deletion.
+  ImageResourceFetcherList::iterator iter =
+      std::find(image_fetchers_.begin(), image_fetchers_.end(), fetcher);
+  if (iter != image_fetchers_.end()) {
+    image_fetchers_.weak_erase(iter);
+    base::MessageLoop::current()->DeleteSoon(FROM_HERE, fetcher);
+  }
+}
+
+SkBitmap ImageLoadingHelper::ImageFromDataUrl(const GURL& url) const {
+  std::string mime_type, char_set, data;
+  if (net::DataURL::Parse(url, &mime_type, &char_set, &data) && !data.empty()) {
+    // Decode the image using WebKit's image decoder.
+    webkit_glue::ImageDecoder decoder(
+        gfx::Size(gfx::kFaviconSize, gfx::kFaviconSize));
+    const unsigned char* src_data =
+        reinterpret_cast<const unsigned char*>(&data[0]);
+
+    return decoder.Decode(src_data, data.size());
+  }
+  return SkBitmap();
+}
+
+bool ImageLoadingHelper::OnMessageReceived(const IPC::Message& message) {
+  bool handled = true;
+  IPC_BEGIN_MESSAGE_MAP(ImageLoadingHelper, message)
+    IPC_MESSAGE_HANDLER(ImageMsg_DownloadImage, OnDownloadImage)
+    IPC_MESSAGE_UNHANDLED(handled = false)
+  IPC_END_MESSAGE_MAP()
+
+  return handled;
+}
+
+}  // namespace content
+
diff --git a/content/renderer/image_loading_helper.h b/content/renderer/image_loading_helper.h
new file mode 100644
index 0000000..6e2302d
--- /dev/null
+++ b/content/renderer/image_loading_helper.h
@@ -0,0 +1,77 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_RENDERER_IMAGE_LOADING_HELPER_H_
+#define CONTENT_RENDERER_IMAGE_LOADING_HELPER_H_
+
+#include <string>
+#include <vector>
+
+#include "base/memory/scoped_vector.h"
+#include "content/public/renderer/render_view_observer.h"
+#include "googleurl/src/gurl.h"
+
+class SkBitmap;
+
+namespace webkit_glue {
+class MultiResolutionImageResourceFetcher;
+}
+
+namespace content {
+
+// This class deals with image downloading.
+// One instance of ImageLoadingHelper is owned by RenderView.
+class ImageLoadingHelper : public RenderViewObserver {
+ public:
+  explicit ImageLoadingHelper(RenderView* render_view);
+
+ private:
+  virtual ~ImageLoadingHelper();
+
+  // Message handler.
+  void OnDownloadImage(int id,
+                       const GURL& image_url,
+                       bool is_favicon,
+                       int image_size);
+
+  // Requests to download an image. When done, the ImageLoadingHelper
+  // is notified by way of DidDownloadImage. Returns true if the
+  // request was successfully started, false otherwise. id is used to
+  // uniquely identify the request and passed back to the
+  // DidDownloadImage method. If the image is a favicon, cookies will not be
+  // sent nor accepted during download. If the image has multiple frames, the
+  // frame whose size is image_size is returned. If the image doesn't
+  // have a frame at the specified size, the first is returned.
+  bool DownloadImage(int id,
+                     const GURL& image_url,
+                     bool is_favicon,
+                     int image_size);
+
+  // This callback is triggered when DownloadImage completes, either
+  // succesfully or with a failure. See DownloadImage for more
+  // details.
+  void DidDownloadImage(
+      int requested_size,
+      webkit_glue::MultiResolutionImageResourceFetcher* fetcher,
+      const std::vector<SkBitmap>& images);
+
+  // Decodes a data: URL image or returns an empty image in case of failure.
+  SkBitmap ImageFromDataUrl(const GURL&) const;
+
+  // RenderViewObserver implementation.
+  virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+
+  typedef ScopedVector<webkit_glue::MultiResolutionImageResourceFetcher>
+      ImageResourceFetcherList;
+
+  // ImageResourceFetchers schedule via DownloadImage.
+  ImageResourceFetcherList image_fetchers_;
+
+  DISALLOW_COPY_AND_ASSIGN(ImageLoadingHelper);
+};
+
+}  // namespace content
+
+#endif  // CONTENT_RENDERER_IMAGE_LOADING_HELPER_H_
+
diff --git a/content/renderer/internal_document_state_data.cc b/content/renderer/internal_document_state_data.cc
new file mode 100644
index 0000000..d5da984
--- /dev/null
+++ b/content/renderer/internal_document_state_data.cc
@@ -0,0 +1,62 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/internal_document_state_data.h"
+
+#include "content/public/common/password_form.h"
+#include "content/public/renderer/document_state.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebDataSource.h"
+#include "webkit/glue/alt_error_page_resource_fetcher.h"
+
+namespace content {
+
+namespace {
+
+// Key InternalDocumentStateData is stored under in DocumentState.
+const char kUserDataKey[] = "InternalDocumentStateData";
+
+}
+
+InternalDocumentStateData::InternalDocumentStateData()
+    : did_first_visually_non_empty_layout_(false),
+      did_first_visually_non_empty_paint_(false),
+      http_status_code_(0),
+      use_error_page_(false),
+      is_overriding_user_agent_(false),
+      must_reset_scroll_and_scale_state_(false),
+      cache_policy_override_set_(false),
+      cache_policy_override_(WebKit::WebURLRequest::UseProtocolCachePolicy),
+      referrer_policy_set_(false),
+      referrer_policy_(WebKit::WebReferrerPolicyDefault) {
+}
+
+// static
+InternalDocumentStateData* InternalDocumentStateData::FromDataSource(
+    WebKit::WebDataSource* ds) {
+  return FromDocumentState(static_cast<DocumentState*>(ds->extraData()));
+}
+
+// static
+InternalDocumentStateData* InternalDocumentStateData::FromDocumentState(
+    DocumentState* ds) {
+  if (!ds)
+    return NULL;
+  InternalDocumentStateData* data = static_cast<InternalDocumentStateData*>(
+      ds->GetUserData(&kUserDataKey));
+  if (!data) {
+    data = new InternalDocumentStateData;
+    ds->SetUserData(&kUserDataKey, data);
+  }
+  return data;
+}
+
+InternalDocumentStateData::~InternalDocumentStateData() {
+}
+
+void InternalDocumentStateData::set_alt_error_page_fetcher(
+    webkit_glue::AltErrorPageResourceFetcher* f) {
+  alt_error_page_fetcher_.reset(f);
+}
+
+}  // namespace content
diff --git a/content/renderer/internal_document_state_data.h b/content/renderer/internal_document_state_data.h
new file mode 100644
index 0000000..08ca357
--- /dev/null
+++ b/content/renderer/internal_document_state_data.h
@@ -0,0 +1,154 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_RENDERER_INTERNAL_DOCUMENT_STATE_DATA_H_
+#define CONTENT_RENDERER_INTERNAL_DOCUMENT_STATE_DATA_H_
+
+#include <string>
+
+#include "base/memory/scoped_ptr.h"
+#include "base/supports_user_data.h"
+#include "googleurl/src/gurl.h"
+#include "third_party/WebKit/Source/Platform/chromium/public/WebReferrerPolicy.h"
+#include "third_party/WebKit/Source/Platform/chromium/public/WebURLRequest.h"
+
+namespace webkit_glue {
+class AltErrorPageResourceFetcher;
+}
+
+namespace WebKit {
+class WebDataSource;
+}
+
+namespace content {
+
+class DocumentState;
+
+// Stores internal state per WebDataSource.
+class InternalDocumentStateData : public base::SupportsUserData::Data {
+ public:
+  InternalDocumentStateData();
+
+  static InternalDocumentStateData* FromDataSource(WebKit::WebDataSource* ds);
+  static InternalDocumentStateData* FromDocumentState(DocumentState* ds);
+
+  // Set to true once RenderViewImpl::didFirstVisuallyNonEmptyLayout() is
+  // invoked.
+  bool did_first_visually_non_empty_layout() const {
+    return did_first_visually_non_empty_layout_;
+  }
+  void set_did_first_visually_non_empty_layout(bool value) {
+    did_first_visually_non_empty_layout_ = value;
+  }
+
+  // Set to true once RenderViewImpl::DidFlushPaint() is inovked after
+  // RenderViewImpl::didFirstVisuallyNonEmptyLayout(). In other words after the
+  // page has painted something.
+  bool did_first_visually_non_empty_paint() const {
+    return did_first_visually_non_empty_paint_;
+  }
+  void set_did_first_visually_non_empty_paint(bool value) {
+    did_first_visually_non_empty_paint_ = value;
+  }
+
+  int http_status_code() const { return http_status_code_; }
+  void set_http_status_code(int http_status_code) {
+    http_status_code_ = http_status_code;
+  }
+
+  const GURL& searchable_form_url() const { return searchable_form_url_; }
+  void set_searchable_form_url(const GURL& url) { searchable_form_url_ = url; }
+  const std::string& searchable_form_encoding() const {
+    return searchable_form_encoding_;
+  }
+  void set_searchable_form_encoding(const std::string& encoding) {
+    searchable_form_encoding_ = encoding;
+  }
+
+  // True if an error page should be used, if the http status code also
+  // indicates an error.
+  bool use_error_page() const { return use_error_page_; }
+  void set_use_error_page(bool use_error_page) {
+    use_error_page_ = use_error_page;
+  }
+
+  // True if the user agent was overridden for this page.
+  bool is_overriding_user_agent() const { return is_overriding_user_agent_; }
+  void set_is_overriding_user_agent(bool state) {
+    is_overriding_user_agent_ = state;
+  }
+
+  // True if we have to reset the scroll and scale state of the page
+  // after the provisional load has been committed.
+  bool must_reset_scroll_and_scale_state() const {
+    return must_reset_scroll_and_scale_state_;
+  }
+  void set_must_reset_scroll_and_scale_state(bool state) {
+    must_reset_scroll_and_scale_state_ = state;
+  }
+
+  // Sets the cache policy. The cache policy is only used if explicitly set and
+  // by default is not set. You can mark a NavigationState as not having a cache
+  // state by way of clear_cache_policy_override.
+  void set_cache_policy_override(
+      WebKit::WebURLRequest::CachePolicy cache_policy) {
+    cache_policy_override_ = cache_policy;
+    cache_policy_override_set_ = true;
+  }
+  WebKit::WebURLRequest::CachePolicy cache_policy_override() const {
+    return cache_policy_override_;
+  }
+  void clear_cache_policy_override() {
+    cache_policy_override_set_ = false;
+    cache_policy_override_ = WebKit::WebURLRequest::UseProtocolCachePolicy;
+  }
+  bool is_cache_policy_override_set() const {
+    return cache_policy_override_set_;
+  }
+
+  // Sets the referrer policy to use. This is only used for browser initiated
+  // navigations, otherwise, the referrer policy is defined by the frame's
+  // document.
+  WebKit::WebReferrerPolicy referrer_policy() const {
+    return referrer_policy_;
+  }
+  void set_referrer_policy(WebKit::WebReferrerPolicy referrer_policy) {
+    referrer_policy_ = referrer_policy;
+    referrer_policy_set_ = true;
+  }
+  void clear_referrer_policy() {
+    referrer_policy_ = WebKit::WebReferrerPolicyDefault;
+    referrer_policy_set_ = false;
+  }
+  bool is_referrer_policy_set() const { return referrer_policy_set_; }
+
+  webkit_glue::AltErrorPageResourceFetcher* alt_error_page_fetcher() const {
+    return alt_error_page_fetcher_.get();
+  }
+  void set_alt_error_page_fetcher(webkit_glue::AltErrorPageResourceFetcher* f);
+
+ protected:
+  virtual ~InternalDocumentStateData();
+
+ private:
+  bool did_first_visually_non_empty_layout_;
+  bool did_first_visually_non_empty_paint_;
+  int http_status_code_;
+  GURL searchable_form_url_;
+  std::string searchable_form_encoding_;
+  bool use_error_page_;
+  bool is_overriding_user_agent_;
+  bool must_reset_scroll_and_scale_state_;
+  bool cache_policy_override_set_;
+  WebKit::WebURLRequest::CachePolicy cache_policy_override_;
+  bool referrer_policy_set_;
+  WebKit::WebReferrerPolicy referrer_policy_;
+  scoped_ptr<webkit_glue::AltErrorPageResourceFetcher> alt_error_page_fetcher_;
+
+  DISALLOW_COPY_AND_ASSIGN(InternalDocumentStateData);
+};
+
+}  // namespace content
+
+#endif  // CONTENT_RENDERER_INTERNAL_DOCUMENT_STATE_DATA_H_
diff --git a/content/renderer/java/java_bridge_dispatcher.cc b/content/renderer/java/java_bridge_dispatcher.cc
index 30039aa..04802df 100644
--- a/content/renderer/java/java_bridge_dispatcher.cc
+++ b/content/renderer/java/java_bridge_dispatcher.cc
@@ -22,7 +22,7 @@
 }
 
 bool JavaBridgeDispatcher::EnsureChannelIsSetUp() {
-  if (channel_.get()) {
+  if (channel_) {
     return true;
   }
 
diff --git a/content/renderer/load_progress_tracker.cc b/content/renderer/load_progress_tracker.cc
index 0e7b07d..93b79ed 100644
--- a/content/renderer/load_progress_tracker.cc
+++ b/content/renderer/load_progress_tracker.cc
@@ -20,7 +20,7 @@
     : render_view_(render_view),
       tracked_frame_(NULL),
       progress_(0.0),
-      ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) {
+      weak_factory_(this) {
 }
 
 LoadProgressTracker::~LoadProgressTracker() {
@@ -68,7 +68,7 @@
   if (weak_factory_.HasWeakPtrs())
     return;
 
-  MessageLoop::current()->PostDelayedTask(
+  base::MessageLoop::current()->PostDelayedTask(
       FROM_HERE,
       base::Bind(&LoadProgressTracker::SendChangeLoadProgress,
                  weak_factory_.GetWeakPtr()),
diff --git a/content/renderer/media/audio_device_factory.cc b/content/renderer/media/audio_device_factory.cc
index fae521e..927a85f 100644
--- a/content/renderer/media/audio_device_factory.cc
+++ b/content/renderer/media/audio_device_factory.cc
@@ -7,8 +7,8 @@
 #include "base/logging.h"
 #include "content/renderer/media/audio_input_message_filter.h"
 #include "content/renderer/media/audio_message_filter.h"
-#include "content/renderer/media/renderer_audio_output_device.h"
 #include "media/audio/audio_input_device.h"
+#include "media/audio/audio_output_device.h"
 
 namespace content {
 
@@ -16,24 +16,33 @@
 AudioDeviceFactory* AudioDeviceFactory::factory_ = NULL;
 
 // static
-scoped_refptr<RendererAudioOutputDevice> AudioDeviceFactory::NewOutputDevice() {
-  RendererAudioOutputDevice* device = NULL;
-  if (factory_)
-    device = factory_->CreateOutputDevice();
+scoped_refptr<media::AudioOutputDevice> AudioDeviceFactory::NewOutputDevice(
+    int render_view_id) {
+  if (factory_) {
+    media::AudioOutputDevice* const device =
+        factory_->CreateOutputDevice(render_view_id);
+    if (device)
+      return device;
+  }
 
-  return device ? device : new RendererAudioOutputDevice(
-      AudioMessageFilter::Get(), AudioMessageFilter::Get()->io_message_loop());
+  AudioMessageFilter* const filter = AudioMessageFilter::Get();
+  return new media::AudioOutputDevice(
+      filter->CreateAudioOutputIPC(render_view_id), filter->io_message_loop());
 }
 
 // static
-scoped_refptr<media::AudioInputDevice> AudioDeviceFactory::NewInputDevice() {
-  media::AudioInputDevice* device = NULL;
-  if (factory_)
-    device = factory_->CreateInputDevice();
+scoped_refptr<media::AudioInputDevice> AudioDeviceFactory::NewInputDevice(
+    int render_view_id) {
+  if (factory_) {
+    media::AudioInputDevice* const device =
+        factory_->CreateInputDevice(render_view_id);
+    if (device)
+      return device;
+  }
 
-  return device ? device : new media::AudioInputDevice(
-      AudioInputMessageFilter::Get(),
-      AudioInputMessageFilter::Get()->io_message_loop());
+  AudioInputMessageFilter* const filter = AudioInputMessageFilter::Get();
+  return new media::AudioInputDevice(
+      filter->CreateAudioInputIPC(render_view_id), filter->io_message_loop());
 }
 
 AudioDeviceFactory::AudioDeviceFactory() {
diff --git a/content/renderer/media/audio_device_factory.h b/content/renderer/media/audio_device_factory.h
index b06ace7..46bf5f9 100644
--- a/content/renderer/media/audio_device_factory.h
+++ b/content/renderer/media/audio_device_factory.h
@@ -10,22 +10,27 @@
 
 namespace media {
 class AudioInputDevice;
+class AudioOutputDevice;
 }
 
 namespace content {
 
-class RendererAudioOutputDevice;
-
-// A factory for creating RendererAudioOutputDevices.  There is a global factory
-// function that can be installed for the purposes of testing to provide
-// a specialized AudioRendererSink class.
+// A factory for creating AudioOutputDevices and AudioInputDevices.  There is a
+// global factory function that can be installed for the purposes of testing to
+// provide specialized implementations.
 class AudioDeviceFactory {
  public:
-  // Creates a RendererAudioOutputDevice using the currently registered factory.
-  static scoped_refptr<RendererAudioOutputDevice> NewOutputDevice();
+  // Creates an AudioOutputDevice using the currently registered factory.
+  // |render_view_id| refers to the render view containing the entity producing
+  // the audio.
+  static scoped_refptr<media::AudioOutputDevice> NewOutputDevice(
+      int render_view_id);
 
-  // Creates an AudioInputDevice using the currently registered factory,
-  static scoped_refptr<media::AudioInputDevice> NewInputDevice();
+  // Creates an AudioInputDevice using the currently registered factory.
+  // |render_view_id| refers to the render view containing the entity consuming
+  // the audio.
+  static scoped_refptr<media::AudioInputDevice> NewInputDevice(
+      int render_view_id);
 
  protected:
   AudioDeviceFactory();
@@ -35,8 +40,8 @@
   // functions to provide alternate audio device implementations.
   // If the return value of either of these function is NULL, we fall back
   // on the default implementation.
-  virtual RendererAudioOutputDevice* CreateOutputDevice() = 0;
-  virtual media::AudioInputDevice* CreateInputDevice() = 0;
+  virtual media::AudioOutputDevice* CreateOutputDevice(int render_view_id) = 0;
+  virtual media::AudioInputDevice* CreateInputDevice(int render_view_id) = 0;
 
  private:
   // The current globally registered factory. This is NULL when we should
diff --git a/content/renderer/media/audio_input_message_filter.cc b/content/renderer/media/audio_input_message_filter.cc
index 038edf3..2b78e2c 100644
--- a/content/renderer/media/audio_input_message_filter.cc
+++ b/content/renderer/media/audio_input_message_filter.cc
@@ -11,24 +11,51 @@
 
 namespace content {
 
-AudioInputMessageFilter* AudioInputMessageFilter::filter_ = NULL;
+namespace {
+const int kStreamIDNotSet = -1;
+}
+
+class AudioInputMessageFilter::AudioInputIPCImpl
+    : public NON_EXPORTED_BASE(media::AudioInputIPC) {
+ public:
+  AudioInputIPCImpl(const scoped_refptr<AudioInputMessageFilter>& filter,
+                    int render_view_id);
+  virtual ~AudioInputIPCImpl();
+
+  // media::AudioInputIPC implementation.
+  virtual void CreateStream(media::AudioInputIPCDelegate* delegate,
+                            int session_id,
+                            const media::AudioParameters& params,
+                            bool automatic_gain_control,
+                            uint32 total_segments) OVERRIDE;
+  virtual void RecordStream() OVERRIDE;
+  virtual void SetVolume(double volume) OVERRIDE;
+  virtual void CloseStream() OVERRIDE;
+
+ private:
+  const scoped_refptr<AudioInputMessageFilter> filter_;
+  const int render_view_id_;
+  int stream_id_;
+};
+
+AudioInputMessageFilter* AudioInputMessageFilter::g_filter = NULL;
 
 AudioInputMessageFilter::AudioInputMessageFilter(
     const scoped_refptr<base::MessageLoopProxy>& io_message_loop)
     : channel_(NULL),
       io_message_loop_(io_message_loop) {
-  DCHECK(!filter_);
-  filter_ = this;
+  DCHECK(!g_filter);
+  g_filter = this;
 }
 
 AudioInputMessageFilter::~AudioInputMessageFilter() {
-  DCHECK_EQ(filter_, this);
-  filter_ = NULL;
+  DCHECK_EQ(g_filter, this);
+  g_filter = NULL;
 }
 
-// static.
+// static
 AudioInputMessageFilter* AudioInputMessageFilter::Get() {
-  return filter_;
+  return g_filter;
 }
 
 void AudioInputMessageFilter::Send(IPC::Message* message) {
@@ -134,43 +161,56 @@
   delegate->OnStateChanged(state);
 }
 
-int AudioInputMessageFilter::AddDelegate(
-    media::AudioInputIPCDelegate* delegate) {
-  DCHECK(io_message_loop_->BelongsToCurrentThread());
-  return delegates_.Add(delegate);
+AudioInputMessageFilter::AudioInputIPCImpl::AudioInputIPCImpl(
+    const scoped_refptr<AudioInputMessageFilter>& filter, int render_view_id)
+    : filter_(filter),
+      render_view_id_(render_view_id),
+      stream_id_(kStreamIDNotSet) {}
+
+AudioInputMessageFilter::AudioInputIPCImpl::~AudioInputIPCImpl() {}
+
+scoped_ptr<media::AudioInputIPC> AudioInputMessageFilter::CreateAudioInputIPC(
+    int render_view_id) {
+  DCHECK_GT(render_view_id, 0);
+  return scoped_ptr<media::AudioInputIPC>(
+      new AudioInputIPCImpl(this, render_view_id));
 }
 
-void AudioInputMessageFilter::RemoveDelegate(int id) {
-  DCHECK(io_message_loop_->BelongsToCurrentThread());
-  delegates_.Remove(id);
+void AudioInputMessageFilter::AudioInputIPCImpl::CreateStream(
+    media::AudioInputIPCDelegate* delegate,
+    int session_id,
+    const media::AudioParameters& params,
+    bool automatic_gain_control,
+    uint32 total_segments) {
+  DCHECK(filter_->io_message_loop_->BelongsToCurrentThread());
+  DCHECK(delegate);
+
+  stream_id_ = filter_->delegates_.Add(delegate);
+
+  AudioInputHostMsg_CreateStream_Config config;
+  config.params = params;
+  config.automatic_gain_control = automatic_gain_control;
+  config.shared_memory_count = total_segments;
+  filter_->Send(new AudioInputHostMsg_CreateStream(
+      stream_id_, render_view_id_, session_id, config));
 }
 
-void AudioInputMessageFilter::CreateStream(int stream_id,
-                                           int session_id,
-                                           const media::AudioParameters& params,
-                                           bool automatic_gain_control,
-                                           uint32 total_segments) {
-  Send(new AudioInputHostMsg_CreateStream(
-      stream_id, session_id, params, automatic_gain_control, total_segments));
-
+void AudioInputMessageFilter::AudioInputIPCImpl::RecordStream() {
+  DCHECK_NE(stream_id_, kStreamIDNotSet);
+  filter_->Send(new AudioInputHostMsg_RecordStream(stream_id_));
 }
 
-void AudioInputMessageFilter::AssociateStreamWithConsumer(int stream_id,
-                                                          int render_view_id) {
-  Send(new AudioInputHostMsg_AssociateStreamWithConsumer(
-      stream_id, render_view_id));
+void AudioInputMessageFilter::AudioInputIPCImpl::SetVolume(double volume) {
+  DCHECK_NE(stream_id_, kStreamIDNotSet);
+  filter_->Send(new AudioInputHostMsg_SetVolume(stream_id_, volume));
 }
 
-void AudioInputMessageFilter::RecordStream(int stream_id) {
-  Send(new AudioInputHostMsg_RecordStream(stream_id));
-}
-
-void AudioInputMessageFilter::CloseStream(int stream_id) {
-  Send(new AudioInputHostMsg_CloseStream(stream_id));
-}
-
-void AudioInputMessageFilter::SetVolume(int stream_id, double volume) {
-  Send(new AudioInputHostMsg_SetVolume(stream_id, volume));
+void AudioInputMessageFilter::AudioInputIPCImpl::CloseStream() {
+  DCHECK(filter_->io_message_loop_->BelongsToCurrentThread());
+  DCHECK_NE(stream_id_, kStreamIDNotSet);
+  filter_->Send(new AudioInputHostMsg_CloseStream(stream_id_));
+  filter_->delegates_.Remove(stream_id_);
+  stream_id_ = kStreamIDNotSet;
 }
 
 }  // namespace content
diff --git a/content/renderer/media/audio_input_message_filter.h b/content/renderer/media/audio_input_message_filter.h
index bd6a0e1..fcba0a7 100644
--- a/content/renderer/media/audio_input_message_filter.h
+++ b/content/renderer/media/audio_input_message_filter.h
@@ -6,6 +6,7 @@
 #define CONTENT_RENDERER_MEDIA_AUDIO_INPUT_MESSAGE_FILTER_H_
 
 #include "base/id_map.h"
+#include "base/memory/scoped_ptr.h"
 #include "base/shared_memory.h"
 #include "base/sync_socket.h"
 #include "content/common/content_export.h"
@@ -23,8 +24,7 @@
 // IO thread (secondary thread of render process), it intercepts audio messages
 // and process them on IO thread since these messages are time critical.
 class CONTENT_EXPORT AudioInputMessageFilter
-    : public IPC::ChannelProxy::MessageFilter,
-      public NON_EXPORTED_BASE(media::AudioInputIPC) {
+    : public IPC::ChannelProxy::MessageFilter {
  public:
   explicit AudioInputMessageFilter(
       const scoped_refptr<base::MessageLoopProxy>& io_message_loop);
@@ -32,29 +32,22 @@
   // Getter for the one AudioInputMessageFilter object.
   static AudioInputMessageFilter* Get();
 
-  // Associates |render_view_id| as the destination of audio for a stream.
-  void AssociateStreamWithConsumer(int stream_id, int render_view_id);
-
-  // Implementation of AudioInputIPC.  All methods must be called on the
-  // provided |io_message_loop|.
-  virtual int AddDelegate(
-      media::AudioInputIPCDelegate* delegate) OVERRIDE;
-  virtual void RemoveDelegate(int id) OVERRIDE;
-  virtual void CreateStream(
-      int stream_id,
-      int session_id,
-      const media::AudioParameters& params,
-      bool automatic_gain_control,
-      uint32 total_segments) OVERRIDE;
-  virtual void RecordStream(int stream_id) OVERRIDE;
-  virtual void CloseStream(int stream_id) OVERRIDE;
-  virtual void SetVolume(int stream_id, double volume) OVERRIDE;
+  // Create an AudioInputIPC to be owned by one delegate.  |render_view_id| is
+  // the render view containing the entity consuming the audio.
+  //
+  // The returned object is not thread-safe, and must be used on
+  // |io_message_loop|.
+  scoped_ptr<media::AudioInputIPC> CreateAudioInputIPC(int render_view_id);
 
   scoped_refptr<base::MessageLoopProxy> io_message_loop() const {
     return io_message_loop_;
   }
 
  private:
+  // Implementation of media::AudioInputIPC which augments IPC calls with
+  // stream_id and the destination render_view_id.
+  class AudioInputIPCImpl;
+
   virtual ~AudioInputMessageFilter();
 
   // Sends an IPC message using |channel_|.
@@ -91,12 +84,12 @@
   // IPC channel for Send(), must only be accesed on |io_message_loop_|.
   IPC::Channel* channel_;
 
-  // The singleton instance for this filter.
-  static AudioInputMessageFilter* filter_;
-
   // Message loop on which IPC calls are driven.
   const scoped_refptr<base::MessageLoopProxy> io_message_loop_;
 
+  // The singleton instance for this filter.
+  static AudioInputMessageFilter* g_filter;
+
   DISALLOW_COPY_AND_ASSIGN(AudioInputMessageFilter);
 };
 
diff --git a/content/renderer/media/audio_message_filter.cc b/content/renderer/media/audio_message_filter.cc
index 11de086..1cb5352 100644
--- a/content/renderer/media/audio_message_filter.cc
+++ b/content/renderer/media/audio_message_filter.cc
@@ -12,60 +12,99 @@
 
 namespace content {
 
-AudioMessageFilter* AudioMessageFilter::filter_ = NULL;
-
-// static
-AudioMessageFilter* AudioMessageFilter::Get() {
-  return filter_;
+namespace {
+const int kStreamIDNotSet = -1;
 }
 
+class AudioMessageFilter::AudioOutputIPCImpl
+    : public NON_EXPORTED_BASE(media::AudioOutputIPC) {
+ public:
+  AudioOutputIPCImpl(const scoped_refptr<AudioMessageFilter>& filter,
+                     int render_view_id);
+  virtual ~AudioOutputIPCImpl();
+
+  // media::AudioOutputIPC implementation.
+  virtual void CreateStream(media::AudioOutputIPCDelegate* delegate,
+                            const media::AudioParameters& params) OVERRIDE;
+  virtual void PlayStream() OVERRIDE;
+  virtual void PauseStream() OVERRIDE;
+  virtual void CloseStream() OVERRIDE;
+  virtual void SetVolume(double volume) OVERRIDE;
+
+ private:
+  const scoped_refptr<AudioMessageFilter> filter_;
+  const int render_view_id_;
+  int stream_id_;
+};
+
+AudioMessageFilter* AudioMessageFilter::g_filter = NULL;
+
 AudioMessageFilter::AudioMessageFilter(
     const scoped_refptr<base::MessageLoopProxy>& io_message_loop)
     : channel_(NULL),
       audio_hardware_config_(NULL),
       io_message_loop_(io_message_loop) {
-  DCHECK(!filter_);
-  filter_ = this;
+  DCHECK(!g_filter);
+  g_filter = this;
 }
 
-int AudioMessageFilter::AddDelegate(media::AudioOutputIPCDelegate* delegate) {
-  DCHECK(io_message_loop_->BelongsToCurrentThread());
-  return delegates_.Add(delegate);
+AudioMessageFilter::~AudioMessageFilter() {
+  DCHECK_EQ(g_filter, this);
+  g_filter = NULL;
 }
 
-void AudioMessageFilter::RemoveDelegate(int id) {
-  DCHECK(io_message_loop_->BelongsToCurrentThread());
-  delegates_.Remove(id);
+// static
+AudioMessageFilter* AudioMessageFilter::Get() {
+  return g_filter;
 }
 
-void AudioMessageFilter::CreateStream(int stream_id,
-                                      const media::AudioParameters& params) {
-  Send(new AudioHostMsg_CreateStream(stream_id, params));
+AudioMessageFilter::AudioOutputIPCImpl::AudioOutputIPCImpl(
+    const scoped_refptr<AudioMessageFilter>& filter, int render_view_id)
+    : filter_(filter),
+      render_view_id_(render_view_id),
+      stream_id_(kStreamIDNotSet) {}
+
+AudioMessageFilter::AudioOutputIPCImpl::~AudioOutputIPCImpl() {}
+
+scoped_ptr<media::AudioOutputIPC> AudioMessageFilter::CreateAudioOutputIPC(
+    int render_view_id) {
+  DCHECK_GT(render_view_id, 0);
+  return scoped_ptr<media::AudioOutputIPC>(
+      new AudioOutputIPCImpl(this, render_view_id));
 }
 
-void AudioMessageFilter::AssociateStreamWithProducer(int stream_id,
-                                                     int render_view_id) {
-  Send(new AudioHostMsg_AssociateStreamWithProducer(stream_id, render_view_id));
+void AudioMessageFilter::AudioOutputIPCImpl::CreateStream(
+    media::AudioOutputIPCDelegate* delegate,
+    const media::AudioParameters& params) {
+  DCHECK(filter_->io_message_loop_->BelongsToCurrentThread());
+  DCHECK(delegate);
+  DCHECK_EQ(stream_id_, kStreamIDNotSet);
+  stream_id_ = filter_->delegates_.Add(delegate);
+  filter_->Send(new AudioHostMsg_CreateStream(
+      stream_id_, render_view_id_, params));
 }
 
-void AudioMessageFilter::PlayStream(int stream_id) {
-  Send(new AudioHostMsg_PlayStream(stream_id));
+void AudioMessageFilter::AudioOutputIPCImpl::PlayStream() {
+  DCHECK_NE(stream_id_, kStreamIDNotSet);
+  filter_->Send(new AudioHostMsg_PlayStream(stream_id_));
 }
 
-void AudioMessageFilter::PauseStream(int stream_id) {
-  Send(new AudioHostMsg_PauseStream(stream_id));
+void AudioMessageFilter::AudioOutputIPCImpl::PauseStream() {
+  DCHECK_NE(stream_id_, kStreamIDNotSet);
+  filter_->Send(new AudioHostMsg_PauseStream(stream_id_));
 }
 
-void AudioMessageFilter::FlushStream(int stream_id) {
-  Send(new AudioHostMsg_FlushStream(stream_id));
+void AudioMessageFilter::AudioOutputIPCImpl::CloseStream() {
+  DCHECK(filter_->io_message_loop_->BelongsToCurrentThread());
+  DCHECK_NE(stream_id_, kStreamIDNotSet);
+  filter_->Send(new AudioHostMsg_CloseStream(stream_id_));
+  filter_->delegates_.Remove(stream_id_);
+  stream_id_ = kStreamIDNotSet;
 }
 
-void AudioMessageFilter::CloseStream(int stream_id) {
-  Send(new AudioHostMsg_CloseStream(stream_id));
-}
-
-void AudioMessageFilter::SetVolume(int stream_id, double volume) {
-  Send(new AudioHostMsg_SetVolume(stream_id, volume));
+void AudioMessageFilter::AudioOutputIPCImpl::SetVolume(double volume) {
+  DCHECK_NE(stream_id_, kStreamIDNotSet);
+  filter_->Send(new AudioHostMsg_SetVolume(stream_id_, volume));
 }
 
 void AudioMessageFilter::Send(IPC::Message* message) {
@@ -117,11 +156,6 @@
   }
 }
 
-AudioMessageFilter::~AudioMessageFilter() {
-  DCHECK_EQ(filter_, this);
-  filter_ = NULL;
-}
-
 void AudioMessageFilter::OnStreamCreated(
     int stream_id,
     base::SharedMemoryHandle handle,
diff --git a/content/renderer/media/audio_message_filter.h b/content/renderer/media/audio_message_filter.h
index 7c352d6..38deb80 100644
--- a/content/renderer/media/audio_message_filter.h
+++ b/content/renderer/media/audio_message_filter.h
@@ -7,6 +7,7 @@
 
 #include "base/gtest_prod_util.h"
 #include "base/id_map.h"
+#include "base/memory/scoped_ptr.h"
 #include "base/shared_memory.h"
 #include "base/sync_socket.h"
 #include "base/synchronization/lock.h"
@@ -26,8 +27,7 @@
 // IO thread (secondary thread of render process) it intercepts audio messages
 // and process them on IO thread since these messages are time critical.
 class CONTENT_EXPORT AudioMessageFilter
-    : public IPC::ChannelProxy::MessageFilter,
-      public NON_EXPORTED_BASE(media::AudioOutputIPC) {
+    : public IPC::ChannelProxy::MessageFilter {
  public:
   explicit AudioMessageFilter(
       const scoped_refptr<base::MessageLoopProxy>& io_message_loop);
@@ -35,27 +35,12 @@
   // Getter for the one AudioMessageFilter object.
   static AudioMessageFilter* Get();
 
-  // Associates |render_view_id| as the source of audio rendered for a stream.
-  void AssociateStreamWithProducer(int stream_id, int render_view_id);
-
-  // media::AudioOutputIPC implementation.
-  virtual int AddDelegate(media::AudioOutputIPCDelegate* delegate) OVERRIDE;
-  virtual void RemoveDelegate(int id) OVERRIDE;
-
-  // Methods below must be called on the provided |io_message_loop|.
-  virtual void CreateStream(int stream_id,
-                            const media::AudioParameters& params) OVERRIDE;
-  virtual void PlayStream(int stream_id) OVERRIDE;
-  virtual void PauseStream(int stream_id) OVERRIDE;
-  virtual void FlushStream(int stream_id) OVERRIDE;
-  virtual void CloseStream(int stream_id) OVERRIDE;
-  virtual void SetVolume(int stream_id, double volume) OVERRIDE;
-
-  // IPC::ChannelProxy::MessageFilter override. Called on |io_message_loop|.
-  virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
-  virtual void OnFilterAdded(IPC::Channel* channel) OVERRIDE;
-  virtual void OnFilterRemoved() OVERRIDE;
-  virtual void OnChannelClosing() OVERRIDE;
+  // Create an AudioOutputIPC to be owned by one delegate.  |render_view_id| is
+  // the render view containing the entity producing the audio.
+  //
+  // The returned object is not thread-safe, and must be used on
+  // |io_message_loop|.
+  scoped_ptr<media::AudioOutputIPC> CreateAudioOutputIPC(int render_view_id);
 
   // When set, AudioMessageFilter will update the AudioHardwareConfig with new
   // configuration values as recieved by OnOutputDeviceChanged().  The provided
@@ -74,9 +59,19 @@
   FRIEND_TEST_ALL_PREFIXES(AudioMessageFilterTest, Basic);
   FRIEND_TEST_ALL_PREFIXES(AudioMessageFilterTest, Delegates);
 
+  // Implementation of media::AudioOutputIPC which augments IPC calls with
+  // stream_id and the source render_view_id.
+  class AudioOutputIPCImpl;
+
   // Sends an IPC message using |channel_|.
   void Send(IPC::Message* message);
 
+  // IPC::ChannelProxy::MessageFilter override. Called on |io_message_loop|.
+  virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+  virtual void OnFilterAdded(IPC::Channel* channel) OVERRIDE;
+  virtual void OnFilterRemoved() OVERRIDE;
+  virtual void OnChannelClosing() OVERRIDE;
+
   // Received when browser process has created an audio output stream.
   void OnStreamCreated(int stream_id, base::SharedMemoryHandle handle,
 #if defined(OS_WIN)
@@ -95,9 +90,6 @@
   void OnOutputDeviceChanged(int stream_id, int new_buffer_size,
                              int new_sample_rate);
 
-  // The singleton instance for this filter.
-  static AudioMessageFilter* filter_;
-
   // IPC channel for Send(); must only be accesed on |io_message_loop_|.
   IPC::Channel* channel_;
 
@@ -113,6 +105,9 @@
   // Message loop on which IPC calls are driven.
   const scoped_refptr<base::MessageLoopProxy> io_message_loop_;
 
+  // The singleton instance for this filter.
+  static AudioMessageFilter* g_filter;
+
   DISALLOW_COPY_AND_ASSIGN(AudioMessageFilter);
 };
 
diff --git a/content/renderer/media/audio_message_filter_unittest.cc b/content/renderer/media/audio_message_filter_unittest.cc
index 4626a64..81db84e 100644
--- a/content/renderer/media/audio_message_filter_unittest.cc
+++ b/content/renderer/media/audio_message_filter_unittest.cc
@@ -11,6 +11,8 @@
 namespace content {
 namespace {
 
+const int kRenderViewId = 1;
+
 class MockAudioDelegate : public media::AudioOutputIPCDelegate {
  public:
   MockAudioDelegate() {
@@ -69,13 +71,17 @@
 }  // namespace
 
 TEST(AudioMessageFilterTest, Basic) {
-  MessageLoop message_loop(MessageLoop::TYPE_IO);
+  base::MessageLoop message_loop(base::MessageLoop::TYPE_IO);
 
   scoped_refptr<AudioMessageFilter> filter(new AudioMessageFilter(
       message_loop.message_loop_proxy()));
 
   MockAudioDelegate delegate;
-  int stream_id = filter->AddDelegate(&delegate);
+  const scoped_ptr<media::AudioOutputIPC> ipc =
+      filter->CreateAudioOutputIPC(kRenderViewId);
+  ipc->CreateStream(&delegate, media::AudioParameters());
+  static const int kStreamId = 1;
+  EXPECT_EQ(&delegate, filter->delegates_.Lookup(kStreamId));
 
   // AudioMsg_NotifyStreamCreated
 #if defined(OS_WIN)
@@ -87,7 +93,7 @@
   EXPECT_FALSE(delegate.created_received());
   filter->OnMessageReceived(
       AudioMsg_NotifyStreamCreated(
-          stream_id, base::SharedMemory::NULLHandle(),
+          kStreamId, base::SharedMemory::NULLHandle(),
           socket_handle, kLength));
   EXPECT_TRUE(delegate.created_received());
   EXPECT_FALSE(base::SharedMemory::IsHandleValid(delegate.handle()));
@@ -98,33 +104,43 @@
   EXPECT_FALSE(delegate.state_changed_received());
   filter->OnMessageReceived(
       AudioMsg_NotifyStreamStateChanged(
-          stream_id, media::AudioOutputIPCDelegate::kPlaying));
+          kStreamId, media::AudioOutputIPCDelegate::kPlaying));
   EXPECT_TRUE(delegate.state_changed_received());
   EXPECT_EQ(media::AudioOutputIPCDelegate::kPlaying, delegate.state());
   delegate.Reset();
 
   message_loop.RunUntilIdle();
-  filter->RemoveDelegate(stream_id);
+
+  ipc->CloseStream();
+  EXPECT_EQ(static_cast<media::AudioOutputIPCDelegate*>(NULL),
+            filter->delegates_.Lookup(kStreamId));
 }
 
 TEST(AudioMessageFilterTest, Delegates) {
-  MessageLoop message_loop(MessageLoop::TYPE_IO);
+  base::MessageLoop message_loop(base::MessageLoop::TYPE_IO);
 
   scoped_refptr<AudioMessageFilter> filter(new AudioMessageFilter(
       message_loop.message_loop_proxy()));
 
   MockAudioDelegate delegate1;
   MockAudioDelegate delegate2;
-
-  int stream_id1 = filter->AddDelegate(&delegate1);
-  int stream_id2 = filter->AddDelegate(&delegate2);
+  const scoped_ptr<media::AudioOutputIPC> ipc1 =
+      filter->CreateAudioOutputIPC(kRenderViewId);
+  const scoped_ptr<media::AudioOutputIPC> ipc2 =
+      filter->CreateAudioOutputIPC(kRenderViewId);
+  ipc1->CreateStream(&delegate1, media::AudioParameters());
+  ipc2->CreateStream(&delegate2, media::AudioParameters());
+  static const int kStreamId1 = 1;
+  static const int kStreamId2 = 2;
+  EXPECT_EQ(&delegate1, filter->delegates_.Lookup(kStreamId1));
+  EXPECT_EQ(&delegate2, filter->delegates_.Lookup(kStreamId2));
 
   // Send an IPC message. Make sure the correct delegate gets called.
   EXPECT_FALSE(delegate1.state_changed_received());
   EXPECT_FALSE(delegate2.state_changed_received());
   filter->OnMessageReceived(
       AudioMsg_NotifyStreamStateChanged(
-          stream_id1, media::AudioOutputIPCDelegate::kPlaying));
+          kStreamId1, media::AudioOutputIPCDelegate::kPlaying));
   EXPECT_TRUE(delegate1.state_changed_received());
   EXPECT_FALSE(delegate2.state_changed_received());
   delegate1.Reset();
@@ -133,15 +149,19 @@
   EXPECT_FALSE(delegate2.state_changed_received());
   filter->OnMessageReceived(
       AudioMsg_NotifyStreamStateChanged(
-          stream_id2, media::AudioOutputIPCDelegate::kPlaying));
+          kStreamId2, media::AudioOutputIPCDelegate::kPlaying));
   EXPECT_FALSE(delegate1.state_changed_received());
   EXPECT_TRUE(delegate2.state_changed_received());
   delegate2.Reset();
 
   message_loop.RunUntilIdle();
 
-  filter->RemoveDelegate(stream_id1);
-  filter->RemoveDelegate(stream_id2);
+  ipc1->CloseStream();
+  ipc2->CloseStream();
+  EXPECT_EQ(static_cast<media::AudioOutputIPCDelegate*>(NULL),
+            filter->delegates_.Lookup(kStreamId1));
+  EXPECT_EQ(static_cast<media::AudioOutputIPCDelegate*>(NULL),
+            filter->delegates_.Lookup(kStreamId2));
 }
 
 }  // namespace content
diff --git a/content/renderer/media/audio_renderer_mixer_manager.cc b/content/renderer/media/audio_renderer_mixer_manager.cc
index 2f2433f..7db67d1 100644
--- a/content/renderer/media/audio_renderer_mixer_manager.cc
+++ b/content/renderer/media/audio_renderer_mixer_manager.cc
@@ -7,7 +7,7 @@
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "content/renderer/media/audio_device_factory.h"
-#include "content/renderer/media/renderer_audio_output_device.h"
+#include "media/audio/audio_output_device.h"
 #include "media/base/audio_hardware_config.h"
 #include "media/base/audio_renderer_mixer.h"
 #include "media/base/audio_renderer_mixer_input.h"
@@ -77,10 +77,9 @@
     mixer = new media::AudioRendererMixer(
         params, output_params, sink_for_testing_);
   } else {
-    scoped_refptr<RendererAudioOutputDevice> device =
-        AudioDeviceFactory::NewOutputDevice();
-    device->SetSourceRenderView(source_render_view_id);
-    mixer = new media::AudioRendererMixer(params, output_params, device);
+    mixer = new media::AudioRendererMixer(
+        params, output_params, AudioDeviceFactory::NewOutputDevice(
+            source_render_view_id));
   }
 
   AudioRendererMixerReference mixer_reference = { mixer, 1 };
diff --git a/content/renderer/media/audio_renderer_mixer_manager.h b/content/renderer/media/audio_renderer_mixer_manager.h
index dd2575b..10901c1 100644
--- a/content/renderer/media/audio_renderer_mixer_manager.h
+++ b/content/renderer/media/audio_renderer_mixer_manager.h
@@ -50,6 +50,17 @@
   // the returned input.
   media::AudioRendererMixerInput* CreateInput(int source_render_view_id);
 
+  // Returns a mixer instance based on AudioParameters; an existing one if one
+  // with the provided AudioParameters exists or a new one if not.
+  media::AudioRendererMixer* GetMixer(int source_render_view_id,
+                                      const media::AudioParameters& params);
+
+  // Remove a mixer instance given a mixer if the only other reference is held
+  // by AudioRendererMixerManager.  Every AudioRendererMixer owner must call
+  // this method when it's done with a mixer.
+  void RemoveMixer(int source_render_view_id,
+                   const media::AudioParameters& params);
+
  private:
   friend class AudioRendererMixerManagerTest;
 
@@ -69,17 +80,6 @@
   // Overrides the AudioRendererSink implementation for unit testing.
   void SetAudioRendererSinkForTesting(media::AudioRendererSink* sink);
 
-  // Returns a mixer instance based on AudioParameters; an existing one if one
-  // with the provided AudioParameters exists or a new one if not.
-  media::AudioRendererMixer* GetMixer(int source_render_view_id,
-                                      const media::AudioParameters& params);
-
-  // Remove a mixer instance given a mixer if the only other reference is held
-  // by AudioRendererMixerManager.  Every AudioRendererMixer owner must call
-  // this method when it's done with a mixer.
-  void RemoveMixer(int source_render_view_id,
-                   const media::AudioParameters& params);
-
   // Active mixers.
   AudioRendererMixerMap mixers_;
   base::Lock mixers_lock_;
diff --git a/content/renderer/media/local_video_capture.cc b/content/renderer/media/local_video_capture.cc
deleted file mode 100644
index f4bc376..0000000
--- a/content/renderer/media/local_video_capture.cc
+++ /dev/null
@@ -1,155 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/renderer/media/local_video_capture.h"
-
-#include "content/renderer/media/video_capture_impl_manager.h"
-#include "media/base/video_util.h"
-#include "media/video/capture/video_capture_proxy.h"
-
-using media::CopyYPlane;
-using media::CopyUPlane;
-using media::CopyVPlane;
-
-namespace content {
-
-LocalVideoCapture::LocalVideoCapture(
-    media::VideoCaptureSessionId video_stream_id,
-    VideoCaptureImplManager* vc_manager,
-    const media::VideoCaptureCapability& capability,
-    const base::Closure& error_cb,
-    const RepaintCB& repaint_cb)
-    : video_stream_id_(video_stream_id),
-      vc_manager_(vc_manager),
-      capability_(capability),
-      error_cb_(error_cb),
-      repaint_cb_(repaint_cb),
-      capture_engine_(NULL),
-      message_loop_proxy_(base::MessageLoopProxy::current()),
-      ALLOW_THIS_IN_INITIALIZER_LIST(
-          handler_proxy_(new media::VideoCaptureHandlerProxy(
-              this, message_loop_proxy_))),
-      state_(VIDEO_CAPTURE_STATE_STOPPED) {
-  DVLOG(3) << "LocalVideoCapture::ctor";
-  DCHECK(vc_manager);
-}
-
-LocalVideoCapture::~LocalVideoCapture() {
-  DVLOG(3) << "LocalVideoCapture::dtor";
-}
-
-void LocalVideoCapture::Start() {
-  DVLOG(3) << "LocalVideoCapture::Start";
-  DCHECK(message_loop_proxy_->BelongsToCurrentThread());
-  DCHECK_EQ(state_, VIDEO_CAPTURE_STATE_STOPPED);
-
-  capture_engine_ = vc_manager_->AddDevice(video_stream_id_, this);
-  state_ = VIDEO_CAPTURE_STATE_STARTED;
-  AddRef();  // Will be balanced in OnRemoved().
-  capture_engine_->StartCapture(handler_proxy_.get(), capability_);
-}
-
-void LocalVideoCapture::Stop() {
-  DVLOG(3) << "LocalVideoCapture::Stop";
-  DCHECK(message_loop_proxy_->BelongsToCurrentThread());
-  if (capture_engine_) {
-    state_ = VIDEO_CAPTURE_STATE_STOPPING;
-    capture_engine_->StopCapture(handler_proxy_.get());
-    capture_engine_ = NULL;
-  }
-}
-
-void LocalVideoCapture::Play() {
-  DVLOG(3) << "LocalVideoCapture::Play";
-  DCHECK(message_loop_proxy_->BelongsToCurrentThread());
-  if (capture_engine_ && state_ == VIDEO_CAPTURE_STATE_PAUSED) {
-    state_ = VIDEO_CAPTURE_STATE_STARTED;
-  }
-}
-
-void LocalVideoCapture::Pause() {
-  DVLOG(3) << "LocalVideoCapture::Pause";
-  DCHECK(message_loop_proxy_->BelongsToCurrentThread());
-  if (capture_engine_ && state_ == VIDEO_CAPTURE_STATE_STARTED) {
-    state_ = VIDEO_CAPTURE_STATE_PAUSED;
-  }
-}
-
-void LocalVideoCapture::OnStarted(media::VideoCapture* capture) {
-  DCHECK(message_loop_proxy_->BelongsToCurrentThread());
-  NOTIMPLEMENTED();
-}
-
-void LocalVideoCapture::OnStopped(media::VideoCapture* capture) {
-  DCHECK(message_loop_proxy_->BelongsToCurrentThread());
-  NOTIMPLEMENTED();
-}
-
-void LocalVideoCapture::OnPaused(media::VideoCapture* capture) {
-  DCHECK(message_loop_proxy_->BelongsToCurrentThread());
-  NOTIMPLEMENTED();
-}
-
-void LocalVideoCapture::OnError(media::VideoCapture* capture,
-                                int error_code) {
-  DVLOG(3) << "LocalVideoCapture::OnError, " << error_code;
-  DCHECK(message_loop_proxy_->BelongsToCurrentThread());
-  error_cb_.Run();
-}
-
-void LocalVideoCapture::OnRemoved(media::VideoCapture* capture) {
-  DVLOG(3) << "LocalVideoCapture::OnRemoved";
-  DCHECK(message_loop_proxy_->BelongsToCurrentThread());
-  // OnRemoved could be triggered by error.
-  capture_engine_ = NULL;
-  vc_manager_->RemoveDevice(video_stream_id_, this);
-  Release();  // Balance the AddRef() in StartCapture().
-}
-
-void LocalVideoCapture::OnDeviceInfoReceived(
-    media::VideoCapture* capture,
-    const media::VideoCaptureParams& device_info) {
-  DVLOG(3) << "LocalVideoCapture::OnDeviceInfoReceived";
-  DCHECK(message_loop_proxy_->BelongsToCurrentThread());
-}
-
-void LocalVideoCapture::OnBufferReady(
-    media::VideoCapture* capture,
-    scoped_refptr<media::VideoCapture::VideoFrameBuffer> buf) {
-  DVLOG(3) << "LocalVideoCapture::OnBufferReady, state:" << state_;
-  DCHECK(message_loop_proxy_->BelongsToCurrentThread());
-  DCHECK(buf);
-
-  if (state_ != VIDEO_CAPTURE_STATE_STARTED) {
-    capture->FeedBuffer(buf);
-    return;
-  }
-
-  gfx::Size natural_size(buf->width, buf->height);
-  scoped_refptr<media::VideoFrame> current_frame =
-      media::VideoFrame::CreateFrame(media::VideoFrame::YV12, natural_size,
-                                     gfx::Rect(natural_size), natural_size,
-                                     buf->timestamp - base::Time());
-  uint8* buffer = buf->memory_pointer;
-
-  // Assume YV12 format.
-  DCHECK_EQ(capability_.color, media::VideoCaptureCapability::kI420);
-  if (capability_.color != media::VideoCaptureCapability::kI420)
-    return;
-
-  int y_width = buf->width;
-  int y_height = buf->height;
-  int uv_width = buf->width / 2;
-  int uv_height = buf->height / 2;
-  CopyYPlane(buffer, y_width, y_height, current_frame);
-  buffer += y_width * y_height;
-  CopyUPlane(buffer, uv_width, uv_height, current_frame);
-  buffer += uv_width * uv_height;
-  CopyVPlane(buffer, uv_width, uv_height, current_frame);
-
-  capture->FeedBuffer(buf);
-  repaint_cb_.Run(current_frame);
-}
-
-}  // namespace content
diff --git a/content/renderer/media/local_video_capture.h b/content/renderer/media/local_video_capture.h
deleted file mode 100644
index 3babc44..0000000
--- a/content/renderer/media/local_video_capture.h
+++ /dev/null
@@ -1,78 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_RENDERER_MEDIA_LOCAL_VIDEO_CAPTURE_H_
-#define CONTENT_RENDERER_MEDIA_LOCAL_VIDEO_CAPTURE_H_
-
-#include "content/common/content_export.h"
-#include "content/common/media/video_capture.h"
-#include "media/video/capture/video_capture.h"
-#include "webkit/media/video_frame_provider.h"
-
-namespace base {
-class MessageLoopProxy;
-}
-
-namespace media {
-class VideoCaptureHandlerProxy;
-}
-
-namespace content {
-class VideoCaptureImplManager;
-
-// This class takes raw frames from video capture engine via VideoCaptureProxy
-// and passes them to media player as a video frame provider.
-// This class lives on main thread.
-class CONTENT_EXPORT LocalVideoCapture
-    : NON_EXPORTED_BASE(public webkit_media::VideoFrameProvider),
-      public media::VideoCapture::EventHandler {
- public:
-  LocalVideoCapture(
-      media::VideoCaptureSessionId video_stream_id,
-      VideoCaptureImplManager* vc_manager,
-      const media::VideoCaptureCapability& capability,
-      const base::Closure& error_cb,
-      const RepaintCB& repaint_cb);
-
-  // webkit_media::VideoFrameProvider implementation.
-  virtual void Start() OVERRIDE;
-  virtual void Stop() OVERRIDE;
-  virtual void Play() OVERRIDE;
-  virtual void Pause() OVERRIDE;
-
-  // VideoCapture::EventHandler implementation.
-  virtual void OnStarted(media::VideoCapture* capture) OVERRIDE;
-  virtual void OnStopped(media::VideoCapture* capture) OVERRIDE;
-  virtual void OnPaused(media::VideoCapture* capture) OVERRIDE;
-  virtual void OnError(media::VideoCapture* capture, int error_code) OVERRIDE;
-  virtual void OnRemoved(media::VideoCapture* capture) OVERRIDE;
-  virtual void OnBufferReady(
-      media::VideoCapture* capture,
-      scoped_refptr<media::VideoCapture::VideoFrameBuffer> buf) OVERRIDE;
-  virtual void OnDeviceInfoReceived(
-      media::VideoCapture* capture,
-      const media::VideoCaptureParams& device_info) OVERRIDE;
-
- protected:
-  virtual ~LocalVideoCapture();
-
- private:
-  friend class LocalVideoCaptureTest;
-
-  media::VideoCaptureSessionId video_stream_id_;
-  scoped_refptr<VideoCaptureImplManager> vc_manager_;
-  media::VideoCaptureCapability capability_;
-  base::Closure error_cb_;
-  RepaintCB repaint_cb_;
-  media::VideoCapture* capture_engine_;
-  scoped_refptr<base::MessageLoopProxy> message_loop_proxy_;
-  scoped_ptr<media::VideoCaptureHandlerProxy> handler_proxy_;
-  VideoCaptureState state_;
-
-  DISALLOW_COPY_AND_ASSIGN(LocalVideoCapture);
-};
-
-}  // namespace content
-
-#endif  // CONTENT_RENDERER_MEDIA_LOCAL_VIDEO_CAPTURE_H_
diff --git a/content/renderer/media/media_stream_center.cc b/content/renderer/media/media_stream_center.cc
index 29f2363..14b0327 100644
--- a/content/renderer/media/media_stream_center.cc
+++ b/content/renderer/media/media_stream_center.cc
@@ -32,7 +32,6 @@
   return extra_data->stream();
 }
 
-
 static webrtc::MediaStreamTrackInterface* GetNativeMediaStreamTrack(
       const WebKit::WebMediaStream& stream,
       const WebKit::WebMediaStreamTrack& component) {
@@ -99,4 +98,22 @@
   rtc_factory_->CreateNativeLocalMediaStream(&stream);
 }
 
+bool MediaStreamCenter::didAddMediaStreamTrack(
+    const WebKit::WebMediaStream& stream,
+    const WebKit::WebMediaStreamTrack& track) {
+  if (!rtc_factory_)
+    return false;
+
+  return rtc_factory_->AddNativeMediaStreamTrack(stream, track);
+}
+
+bool MediaStreamCenter::didRemoveMediaStreamTrack(
+    const WebKit::WebMediaStream& stream,
+    const WebKit::WebMediaStreamTrack& track) {
+  if (!rtc_factory_)
+    return false;
+
+  return rtc_factory_->RemoveNativeMediaStreamTrack(stream, track);
+}
+
 }  // namespace content
diff --git a/content/renderer/media/media_stream_center.h b/content/renderer/media/media_stream_center.h
index bd125b5..de5f2e1 100644
--- a/content/renderer/media/media_stream_center.h
+++ b/content/renderer/media/media_stream_center.h
@@ -42,6 +42,14 @@
   virtual void didCreateMediaStream(
       WebKit::WebMediaStream& stream) OVERRIDE;
 
+  virtual bool didAddMediaStreamTrack(
+      const WebKit::WebMediaStream& stream,
+      const WebKit::WebMediaStreamTrack& track) OVERRIDE;
+
+  virtual bool didRemoveMediaStreamTrack(
+      const WebKit::WebMediaStream& stream,
+      const WebKit::WebMediaStreamTrack& track) OVERRIDE;
+
  private:
   // |rtc_factory_| is a weak pointer and is owned by the RenderThreadImpl.
   // It is valid as long as  RenderThreadImpl exist.
diff --git a/content/renderer/media/media_stream_dependency_factory.cc b/content/renderer/media/media_stream_dependency_factory.cc
index 06943a6..421bfac 100644
--- a/content/renderer/media/media_stream_dependency_factory.cc
+++ b/content/renderer/media/media_stream_dependency_factory.cc
@@ -15,6 +15,7 @@
 #include "content/renderer/media/video_capture_impl_manager.h"
 #include "content/renderer/media/webaudio_capturer_source.h"
 #include "content/renderer/media/webrtc_audio_device_impl.h"
+#include "content/renderer/media/webrtc_local_audio_track.h"
 #include "content/renderer/media/webrtc_uma_histograms.h"
 #include "content/renderer/p2p/ipc_network_manager.h"
 #include "content/renderer/p2p/ipc_socket_factory.h"
@@ -40,14 +41,14 @@
   const char* key;
   const char* value;
 } const kWebAudioConstraints[] = {
-  {webrtc::MediaConstraintsInterface::kEchoCancellation,
-   webrtc::MediaConstraintsInterface::kValueFalse},
-  {webrtc::MediaConstraintsInterface::kAutoGainControl,
-   webrtc::MediaConstraintsInterface::kValueFalse},
-  {webrtc::MediaConstraintsInterface::kNoiseSuppression,
-   webrtc::MediaConstraintsInterface::kValueFalse},
-  {webrtc::MediaConstraintsInterface::kHighpassFilter,
-   webrtc::MediaConstraintsInterface::kValueFalse},
+    {webrtc::MediaConstraintsInterface::kEchoCancellation,
+     webrtc::MediaConstraintsInterface::kValueFalse},
+    {webrtc::MediaConstraintsInterface::kAutoGainControl,
+     webrtc::MediaConstraintsInterface::kValueFalse},
+    {webrtc::MediaConstraintsInterface::kNoiseSuppression,
+     webrtc::MediaConstraintsInterface::kValueFalse},
+    {webrtc::MediaConstraintsInterface::kHighpassFilter,
+     webrtc::MediaConstraintsInterface::kValueFalse},
 };
 
 class WebAudioConstraints : public RTCMediaConstraints {
@@ -65,7 +66,7 @@
     }
   }
 
-  virtual ~WebAudioConstraints() {};
+  virtual ~WebAudioConstraints() {}
 };
 
 class P2PPortAllocatorFactory : public webrtc::PortAllocatorFactoryInterface {
@@ -227,6 +228,7 @@
 }
 
 void MediaStreamDependencyFactory::CreateNativeMediaSources(
+    int render_view_id,
     const WebKit::WebMediaConstraints& audio_constraints,
     const WebKit::WebMediaConstraints& video_constraints,
     WebKit::WebMediaStream* description,
@@ -284,7 +286,7 @@
 
     const StreamDeviceInfo device_info = source_data->device_info();
     if (IsAudioMediaType(device_info.device.type)) {
-      if (!InitializeAudioSource(device_info)) {
+      if (!InitializeAudioSource(render_view_id, device_info)) {
         DLOG(WARNING) << "Unsupported audio source";
         sources_created.Run(description, false);
         return;
@@ -304,82 +306,30 @@
     WebKit::WebMediaStream* description) {
   DVLOG(1) << "MediaStreamDependencyFactory::CreateNativeLocalMediaStream()";
   if (!EnsurePeerConnectionFactory()) {
-      DVLOG(1) << "EnsurePeerConnectionFactory() failed!";
-      return;
+    DVLOG(1) << "EnsurePeerConnectionFactory() failed!";
+    return;
   }
 
   std::string label = UTF16ToUTF8(description->label());
   scoped_refptr<webrtc::MediaStreamInterface> native_stream =
       CreateLocalMediaStream(label);
+  MediaStreamExtraData* extra_data = new MediaStreamExtraData(native_stream,
+                                                              true);
+  description->setExtraData(extra_data);
 
   // Add audio tracks.
   WebKit::WebVector<WebKit::WebMediaStreamTrack> audio_tracks;
-  description->audioSources(audio_tracks);
-
-  bool start_stream = false;
+  description->audioTracks(audio_tracks);
   for (size_t i = 0; i < audio_tracks.size(); ++i) {
-    WebKit::WebMediaStreamSource source = audio_tracks[i].source();
-
-    // See if we're adding a WebAudio MediaStream.
-    if (source.requiresAudioConsumer()) {
-      // TODO(crogers, xians): In reality we should be able to send a unique
-      // audio stream to each PeerConnection separately.  But currently WebRTC
-      // is only able to handle a global audio stream sent to ALL peers.
-
-      // Create a special source where default WebAudio constraints are used.
-      if (!CreateWebAudioSource(&source)) {
-        LOG(ERROR) << "Failed to create WebAudio source";
-        continue;
-      }
-    }
-
-    MediaStreamSourceExtraData* source_data =
-        static_cast<MediaStreamSourceExtraData*>(source.extraData());
-
-    if (!source_data) {
-      // TODO(perkj): Implement support for sources from
-      // remote MediaStreams.
-      NOTIMPLEMENTED();
-      continue;
-    }
-
-    scoped_refptr<webrtc::AudioTrackInterface> audio_track(
-        CreateLocalAudioTrack(UTF16ToUTF8(audio_tracks[i].id()),
-                              source_data->local_audio_source()));
-    native_stream->AddTrack(audio_track);
-    audio_track->set_enabled(audio_tracks[i].isEnabled());
-    start_stream = true;
-  }
-
-  if (start_stream && GetWebRtcAudioDevice()) {
-    WebRtcAudioCapturer* capturer = GetWebRtcAudioDevice()->capturer();
-    capturer->Start();
+    AddNativeMediaStreamTrack(*description, audio_tracks[i]);
   }
 
   // Add video tracks.
   WebKit::WebVector<WebKit::WebMediaStreamTrack> video_tracks;
-  description->videoSources(video_tracks);
+  description->videoTracks(video_tracks);
   for (size_t i = 0; i < video_tracks.size(); ++i) {
-    const WebKit::WebMediaStreamSource& source = video_tracks[i].source();
-    MediaStreamSourceExtraData* source_data =
-        static_cast<MediaStreamSourceExtraData*>(source.extraData());
-    if (!source_data || !source_data->video_source()) {
-      // TODO(perkj): Implement support for sources from remote MediaStreams.
-      NOTIMPLEMENTED();
-      continue;
-    }
-
-    scoped_refptr<webrtc::VideoTrackInterface> video_track(
-        CreateLocalVideoTrack(UTF16ToUTF8(video_tracks[i].id()),
-                              source_data->video_source()));
-
-    native_stream->AddTrack(video_track);
-    video_track->set_enabled(video_tracks[i].isEnabled());
+    AddNativeMediaStreamTrack(*description, video_tracks[i]);
   }
-
-  MediaStreamExtraData* extra_data = new MediaStreamExtraData(native_stream,
-                                                              true);
-  description->setExtraData(extra_data);
 }
 
 void MediaStreamDependencyFactory::CreateNativeLocalMediaStream(
@@ -392,16 +342,128 @@
   extra_data->SetLocalStreamStopCallback(stream_stop);
 }
 
+bool MediaStreamDependencyFactory::AddNativeMediaStreamTrack(
+      const WebKit::WebMediaStream& stream,
+      const WebKit::WebMediaStreamTrack& track) {
+  MediaStreamExtraData* extra_data =
+     static_cast<MediaStreamExtraData*>(stream.extraData());
+  webrtc::MediaStreamInterface* native_stream = extra_data->stream();
+  DCHECK(native_stream);
+
+  WebKit::WebMediaStreamSource source = track.source();
+  MediaStreamSourceExtraData* source_data =
+      static_cast<MediaStreamSourceExtraData*>(source.extraData());
+
+  if (!source_data) {
+    if (source.requiresAudioConsumer()) {
+      // We're adding a WebAudio MediaStream.
+      // TODO(crogers, xians): In reality we should be able to send a unique
+      // audio stream to each PeerConnection separately.
+      // Currently WebRTC is only able to handle a global audio stream sent to
+      // ALL peers. Create a special source where default WebAudio constraints
+      // are used.
+      if (CreateWebAudioSource(&source)) {
+        source_data =
+            static_cast<MediaStreamSourceExtraData*>(source.extraData());
+      } else {
+        LOG(ERROR) << "Failed to create WebAudio source";
+        return false;
+      }
+    } else {
+      // TODO(perkj): Implement support for sources from
+      // remote MediaStreams.
+      NOTIMPLEMENTED();
+      return false;
+    }
+  }
+
+  WebKit::WebMediaStreamSource::Type type = track.source().type();
+  DCHECK(type == WebKit::WebMediaStreamSource::TypeAudio ||
+         type == WebKit::WebMediaStreamSource::TypeVideo);
+
+  std::string track_id = UTF16ToUTF8(track.id());
+  if (source.type() == WebKit::WebMediaStreamSource::TypeAudio) {
+    // TODO(henrika,xians): Refactor how an audio track is created to harmonize
+    // with video tracks.
+    scoped_refptr<webrtc::AudioTrackInterface> audio_track(
+        CreateLocalAudioTrack(track_id, source_data->local_audio_source()));
+    audio_track->set_enabled(track.isEnabled());
+    if (GetWebRtcAudioDevice()) {
+      WebRtcAudioCapturer* capturer = GetWebRtcAudioDevice()->capturer();
+      if (!capturer->is_recording())
+        capturer->Start();
+    }
+    return native_stream->AddTrack(audio_track);
+  } else {
+    scoped_refptr<webrtc::VideoTrackInterface> video_track(
+        CreateLocalVideoTrack(track_id, source_data->video_source()));
+    video_track->set_enabled(track.isEnabled());
+    return native_stream->AddTrack(video_track);
+  }
+}
+
+bool MediaStreamDependencyFactory::AddNativeVideoMediaTrack(
+    const std::string& track_id,
+    WebKit::WebMediaStream* stream,
+    cricket::VideoCapturer* capturer) {
+  if (!stream) {
+    LOG(ERROR) << "AddNativeVideoMediaTrack called with null WebMediaStream.";
+    return false;
+  }
+
+  // Create native track from the source.
+  scoped_refptr<webrtc::VideoTrackInterface> native_track =
+      CreateLocalVideoTrack(track_id, capturer);
+
+  // Add the native track to native stream
+  MediaStreamExtraData* extra_data =
+      static_cast<MediaStreamExtraData*>(stream->extraData());
+  DCHECK(extra_data);
+  webrtc::MediaStreamInterface* native_stream = extra_data->stream();
+  native_stream->AddTrack(native_track);
+
+  // Create a new webkit video track.
+  WebKit::WebMediaStreamTrack webkit_track;
+  WebKit::WebMediaStreamSource webkit_source;
+  WebKit::WebString webkit_track_id(UTF8ToUTF16(track_id));
+  WebKit::WebMediaStreamSource::Type type =
+      WebKit::WebMediaStreamSource::TypeVideo;
+  webkit_source.initialize(webkit_track_id, type, webkit_track_id);
+  webkit_track.initialize(webkit_track_id, webkit_source);
+
+  // Add the track to WebMediaStream.
+  stream->addTrack(webkit_track);
+  return true;
+}
+
+bool MediaStreamDependencyFactory::RemoveNativeMediaStreamTrack(
+    const WebKit::WebMediaStream& stream,
+    const WebKit::WebMediaStreamTrack& track) {
+  MediaStreamExtraData* extra_data =
+      static_cast<MediaStreamExtraData*>(stream.extraData());
+  webrtc::MediaStreamInterface* native_stream = extra_data->stream();
+  DCHECK(native_stream);
+
+  WebKit::WebMediaStreamSource::Type type = track.source().type();
+  DCHECK(type == WebKit::WebMediaStreamSource::TypeAudio ||
+         type == WebKit::WebMediaStreamSource::TypeVideo);
+
+  std::string track_id = UTF16ToUTF8(track.id());
+  return type == WebKit::WebMediaStreamSource::TypeAudio ?
+      native_stream->RemoveTrack(native_stream->FindAudioTrack(track_id)) :
+      native_stream->RemoveTrack(native_stream->FindVideoTrack(track_id));
+}
+
 bool MediaStreamDependencyFactory::CreatePeerConnectionFactory() {
   DVLOG(1) << "MediaStreamDependencyFactory::CreatePeerConnectionFactory()";
-  if (!pc_factory_.get()) {
+  if (!pc_factory_) {
     DCHECK(!audio_device_);
     audio_device_ = new WebRtcAudioDeviceImpl();
     scoped_refptr<webrtc::PeerConnectionFactoryInterface> factory(
         webrtc::CreatePeerConnectionFactory(worker_thread_,
                                             signaling_thread_,
                                             audio_device_));
-    if (factory.get())
+    if (factory)
       pc_factory_ = factory;
     else
       audio_device_ = NULL;
@@ -460,7 +522,8 @@
 }
 
 bool MediaStreamDependencyFactory::InitializeAudioSource(
-  const StreamDeviceInfo& device_info) {
+    int render_view_id,
+    const StreamDeviceInfo& device_info) {
   DVLOG(1) << "MediaStreamDependencyFactory::InitializeAudioSource()";
 
   // TODO(henrika): the current design does not support a unique source
@@ -474,6 +537,7 @@
   // TODO(henrika): refactor \content\public\common\media_stream_request.h
   // to allow dependency of media::ChannelLayout and avoid static_cast.
   if (!capturer->Initialize(
+          render_view_id,
           static_cast<media::ChannelLayout>(device_info.device.channel_layout),
           device_info.device.sample_rate, device_info.session_id))
     return false;
@@ -524,11 +588,31 @@
   return pc_factory_->CreateVideoTrack(id, source).get();
 }
 
+scoped_refptr<webrtc::VideoTrackInterface>
+MediaStreamDependencyFactory::CreateLocalVideoTrack(
+    const std::string& id, cricket::VideoCapturer* capturer) {
+  if (!capturer) {
+    LOG(ERROR) << "CreateLocalVideoTrack called with null VideoCapturer.";
+    return NULL;
+  }
+
+  // Create video source from the |capturer|.
+  scoped_refptr<webrtc::VideoSourceInterface> source =
+      pc_factory_->CreateVideoSource(capturer, NULL).get();
+
+  // Create native track from the source.
+  return pc_factory_->CreateVideoTrack(id, source).get();
+}
+
 scoped_refptr<webrtc::AudioTrackInterface>
 MediaStreamDependencyFactory::CreateLocalAudioTrack(
     const std::string& id,
     webrtc::AudioSourceInterface* source) {
-  return pc_factory_->CreateAudioTrack(id, source).get();
+  // TODO(xians): Merge |source| to the capturer(). We can't do this today
+  // because only one capturer() is supported while one |source| is created
+  // for each audio track.
+  return WebRtcLocalAudioTrack::Create(id, GetWebRtcAudioDevice()->capturer(),
+                                       source);
 }
 
 webrtc::SessionDescriptionInterface*
@@ -577,13 +661,13 @@
 
 void MediaStreamDependencyFactory::CreateIpcNetworkManagerOnWorkerThread(
     base::WaitableEvent* event) {
-  DCHECK_EQ(MessageLoop::current(), chrome_worker_thread_.message_loop());
+  DCHECK_EQ(base::MessageLoop::current(), chrome_worker_thread_.message_loop());
   network_manager_ = new IpcNetworkManager(p2p_socket_dispatcher_);
   event->Signal();
 }
 
 void MediaStreamDependencyFactory::DeleteIpcNetworkManager() {
-  DCHECK_EQ(MessageLoop::current(), chrome_worker_thread_.message_loop());
+  DCHECK_EQ(base::MessageLoop::current(), chrome_worker_thread_.message_loop());
   delete network_manager_;
   network_manager_ = NULL;
 }
@@ -627,7 +711,7 @@
     event.Wait();
   }
 
-  if (!socket_factory_.get()) {
+  if (!socket_factory_) {
     socket_factory_.reset(
         new IpcPacketSocketFactory(p2p_socket_dispatcher_));
   }
diff --git a/content/renderer/media/media_stream_dependency_factory.h b/content/renderer/media/media_stream_dependency_factory.h
index 27e4f4a..a56177a 100644
--- a/content/renderer/media/media_stream_dependency_factory.h
+++ b/content/renderer/media/media_stream_dependency_factory.h
@@ -71,6 +71,7 @@
   // WebMediaStreamSource.
   // |audio_constraints| and |video_constraints| set parameters for the sources.
   void CreateNativeMediaSources(
+      int render_view_id,
       const WebKit::WebMediaConstraints& audio_constraints,
       const WebKit::WebMediaConstraints& video_constraints,
       WebKit::WebMediaStream* description,
@@ -89,6 +90,20 @@
       WebKit::WebMediaStream* description,
       const MediaStreamExtraData::StreamStopCallback& stream_stop);
 
+  // Adds a libjingle representation of a MediaStreamTrack to |stream| based
+  // on the source of |track|.
+  bool AddNativeMediaStreamTrack(const WebKit::WebMediaStream& stream,
+                                 const WebKit::WebMediaStreamTrack& track);
+
+  // Creates and adds libjingle representation of a MediaStreamTrack to |stream|
+  // based on the desired |track_id| and |capturer|.
+  bool AddNativeVideoMediaTrack(const std::string& track_id,
+                                WebKit::WebMediaStream* stream,
+                                cricket::VideoCapturer* capturer);
+
+  bool RemoveNativeMediaStreamTrack(const WebKit::WebMediaStream& stream,
+                                    const WebKit::WebMediaStreamTrack& track);
+
   // Asks the libjingle PeerConnection factory to create a libjingle
   // PeerConnection object.
   // The PeerConnection object is owned by PeerConnectionHandler.
@@ -139,7 +154,8 @@
   // Initializes the source using audio parameters for the selected
   // capture device and specifies which capture device to use as capture
   // source.
-  virtual bool InitializeAudioSource(const StreamDeviceInfo& device_info);
+  virtual bool InitializeAudioSource(int render_view_id,
+                                     const StreamDeviceInfo& device_info);
 
   // Creates a media::AudioCapturerSource with an implementation that is
   // specific for a WebAudio source. The created WebAudioCapturerSource
@@ -157,6 +173,12 @@
       CreateLocalVideoTrack(const std::string& id,
                             webrtc::VideoSourceInterface* source);
 
+  // Asks the PeerConnection factory to create a Local VideoTrack object with
+  // the video source using |capturer|.
+  virtual scoped_refptr<webrtc::VideoTrackInterface>
+      CreateLocalVideoTrack(const std::string& id,
+                            cricket::VideoCapturer* capturer);
+
   virtual bool EnsurePeerConnectionFactory();
   virtual bool PeerConnectionFactoryCreated();
 
diff --git a/content/renderer/media/media_stream_dependency_factory_unittest.cc b/content/renderer/media/media_stream_dependency_factory_unittest.cc
index a44f134..0023bb9 100644
--- a/content/renderer/media/media_stream_dependency_factory_unittest.cc
+++ b/content/renderer/media/media_stream_dependency_factory_unittest.cc
@@ -49,10 +49,19 @@
     dependency_factory_.reset(new MockMediaStreamDependencyFactory());
   }
 
-  WebKit::WebMediaStream CreateWebKitMediaStream(bool audio,
-                                                           bool video) {
+  virtual void TearDown() OVERRIDE {
+    // TODO(tommyw): Remove this once WebKit::MediaStreamSource::Owner has been
+    // implemented to fully avoid a circular dependency.
+    for (size_t i = 0; i < audio_sources_.size(); ++i)
+      audio_sources_[i].setExtraData(NULL);
+
+    for (size_t i = 0; i < video_sources_.size(); ++i)
+      video_sources_[i].setExtraData(NULL);
+  }
+
+  WebKit::WebMediaStream CreateWebKitMediaStream(bool audio, bool video) {
     WebKit::WebVector<WebKit::WebMediaStreamSource> audio_sources(
-                      audio ? static_cast<size_t>(1) : 0);
+        audio ? static_cast<size_t>(1) : 0);
     WebKit::WebVector<WebKit::WebMediaStreamSource> video_sources(
         video ? static_cast<size_t>(1) : 0);
 
@@ -67,7 +76,8 @@
                                   WebKit::WebMediaStreamSource::TypeAudio,
                                   "audio");
       audio_sources[0].setExtraData(
-              new MediaStreamSourceExtraData(info));
+          new MediaStreamSourceExtraData(info, audio_sources[0]));
+      audio_sources_.assign(audio_sources);
     }
     if (video) {
       StreamDeviceInfo info;
@@ -78,7 +88,8 @@
                                   WebKit::WebMediaStreamSource::TypeVideo,
                                   "video");
       video_sources[0].setExtraData(
-              new MediaStreamSourceExtraData(info));
+          new MediaStreamSourceExtraData(info, video_sources[0]));
+      video_sources_.assign(video_sources);
     }
     WebKit::WebMediaStream stream_desc;
     stream_desc.initialize("media stream", audio_sources, video_sources);
@@ -87,9 +98,12 @@
   }
 
   void CreateNativeSources(WebKit::WebMediaStream* descriptor) {
+    static const int kRenderViewId = 1;
+
     MediaSourceCreatedObserver observer;
     WebKit::WebMediaConstraints audio_constraints;
     dependency_factory_->CreateNativeMediaSources(
+        kRenderViewId,
         WebKit::WebMediaConstraints(),
         WebKit::WebMediaConstraints(),
         descriptor,
@@ -108,8 +122,21 @@
     EXPECT_TRUE(observer.description() == descriptor);
   }
 
+  void VerifyMediaStream(const WebKit::WebMediaStream& stream_desc,
+                         size_t num_audio_tracks,
+                         size_t num_video_tracks) {
+    content::MediaStreamExtraData* extra_data =
+        static_cast<content::MediaStreamExtraData*>(stream_desc.extraData());
+    ASSERT_TRUE(extra_data && extra_data->stream());
+    EXPECT_TRUE(extra_data->is_local());
+    EXPECT_EQ(num_audio_tracks, extra_data->stream()->GetAudioTracks().size());
+    EXPECT_EQ(num_video_tracks, extra_data->stream()->GetVideoTracks().size());
+  }
+
  protected:
   scoped_ptr<MockMediaStreamDependencyFactory> dependency_factory_;
+  WebKit::WebVector<WebKit::WebMediaStreamSource> audio_sources_;
+  WebKit::WebVector<WebKit::WebMediaStreamSource> video_sources_;
 };
 
 TEST_F(MediaStreamDependencyFactoryTest, CreateRTCPeerConnectionHandler) {
@@ -124,13 +151,7 @@
   CreateNativeSources(&stream_desc);
 
   dependency_factory_->CreateNativeLocalMediaStream(&stream_desc);
-
-  content::MediaStreamExtraData* extra_data =
-      static_cast<content::MediaStreamExtraData*>(stream_desc.extraData());
-  ASSERT_TRUE(extra_data && extra_data->stream());
-  EXPECT_TRUE(extra_data->is_local());
-  EXPECT_EQ(1u, extra_data->stream()->GetAudioTracks().size());
-  EXPECT_EQ(1u, extra_data->stream()->GetVideoTracks().size());
+  VerifyMediaStream(stream_desc, 1, 1);
 }
 
 // Test that we don't crash if a MediaStream is created in WebKit with unknown
@@ -153,12 +174,35 @@
 
   EXPECT_TRUE(dependency_factory_->EnsurePeerConnectionFactory());
   dependency_factory_->CreateNativeLocalMediaStream(&stream_desc);
-  MediaStreamExtraData* extra_data = static_cast<MediaStreamExtraData*>(
-      stream_desc.extraData());
-  ASSERT_TRUE(extra_data && extra_data->stream());
-  EXPECT_TRUE(extra_data->is_local());
-  EXPECT_EQ(0u, extra_data->stream()->GetVideoTracks().size());
-  EXPECT_EQ(0u, extra_data->stream()->GetAudioTracks().size());
+  VerifyMediaStream(stream_desc, 0, 0);
+}
+
+TEST_F(MediaStreamDependencyFactoryTest, AddAndRemoveNativeTrack) {
+  WebKit::WebMediaStream stream_desc = CreateWebKitMediaStream(true, true);
+  CreateNativeSources(&stream_desc);
+
+  dependency_factory_->CreateNativeLocalMediaStream(&stream_desc);
+  VerifyMediaStream(stream_desc, 1, 1);
+
+  WebKit::WebVector<WebKit::WebMediaStreamTrack> audio_tracks;
+  stream_desc.audioTracks(audio_tracks);
+  EXPECT_TRUE(dependency_factory_->RemoveNativeMediaStreamTrack(
+      stream_desc, audio_tracks[0]));
+  VerifyMediaStream(stream_desc, 0, 1);
+
+  EXPECT_TRUE(dependency_factory_->AddNativeMediaStreamTrack(
+      stream_desc, audio_tracks[0]));
+  VerifyMediaStream(stream_desc, 1, 1);
+
+  WebKit::WebVector<WebKit::WebMediaStreamTrack> video_tracks;
+  stream_desc.videoTracks(video_tracks);
+  EXPECT_TRUE(dependency_factory_->RemoveNativeMediaStreamTrack(
+      stream_desc, video_tracks[0]));
+  VerifyMediaStream(stream_desc, 1, 0);
+
+  EXPECT_TRUE(dependency_factory_->AddNativeMediaStreamTrack(
+      stream_desc, video_tracks[0]));
+  VerifyMediaStream(stream_desc, 1, 1);
 }
 
 }  // namespace content
diff --git a/content/renderer/media/media_stream_dispatcher.cc b/content/renderer/media/media_stream_dispatcher.cc
index d5eafe8..859022a 100644
--- a/content/renderer/media/media_stream_dispatcher.cc
+++ b/content/renderer/media/media_stream_dispatcher.cc
@@ -8,6 +8,7 @@
 #include "base/message_loop_proxy.h"
 #include "content/common/media/media_stream_messages.h"
 #include "content/renderer/media/media_stream_dispatcher_eventhandler.h"
+#include "content/renderer/render_thread_impl.h"
 #include "content/renderer/render_view_impl.h"
 #include "googleurl/src/gurl.h"
 
@@ -130,7 +131,7 @@
        &audio_enumeration_state_ : &video_enumeration_state_);
   state->requests.push_back(EnumerationRequest(event_handler, request_id));
 
-  if (state->cached_devices.get()) {
+  if (state->cached_devices) {
     event_handler->OnDevicesEnumerated(
         request_id, state->cached_devices->devices);
   } else if (state->ipc_id < 0) {
@@ -165,7 +166,7 @@
        it != requests->end(); ++it) {
     if (it->request_id == request_id && it->handler == event_handler) {
       requests->erase(it);
-      if (requests->empty() && state->cached_devices.get()) {
+      if (requests->empty() && state->cached_devices) {
         // No more request and has a label, try to stop the label
         // and invalidate the state.
         Send(new MediaStreamHostMsg_StopGeneratedStream(
@@ -203,6 +204,15 @@
   StopStream(label);
 }
 
+bool MediaStreamDispatcher::Send(IPC::Message* message) {
+  if (!RenderThread::Get()) {
+    delete message;
+    return false;
+  }
+
+  return RenderThread::Get()->Send(message);
+}
+
 bool MediaStreamDispatcher::OnMessageReceived(const IPC::Message& message) {
   bool handled = true;
   IPC_BEGIN_MESSAGE_MAP(MediaStreamDispatcher, message)
diff --git a/content/renderer/media/media_stream_dispatcher.h b/content/renderer/media/media_stream_dispatcher.h
index d5e48ef..e013864 100644
--- a/content/renderer/media/media_stream_dispatcher.h
+++ b/content/renderer/media/media_stream_dispatcher.h
@@ -122,6 +122,9 @@
     EnumerationRequestList requests;
   };
 
+  // RenderViewObserver OVERRIDE.
+  virtual bool Send(IPC::Message* message) OVERRIDE;
+
   // Messages from the browser.
   virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
   void OnStreamGenerated(
diff --git a/content/renderer/media/media_stream_dispatcher_unittest.cc b/content/renderer/media/media_stream_dispatcher_unittest.cc
index d272f43..b9e055e 100644
--- a/content/renderer/media/media_stream_dispatcher_unittest.cc
+++ b/content/renderer/media/media_stream_dispatcher_unittest.cc
@@ -81,7 +81,7 @@
 }  // namespace
 
 TEST(MediaStreamDispatcherTest, BasicStream) {
-  scoped_ptr<MessageLoop> message_loop(new MessageLoop());
+  scoped_ptr<base::MessageLoop> message_loop(new base::MessageLoop());
   scoped_ptr<MediaStreamDispatcher> dispatcher(new MediaStreamDispatcher(NULL));
   scoped_ptr<MockMediaStreamDispatcherEventHandler>
       handler(new MockMediaStreamDispatcherEventHandler);
@@ -157,7 +157,7 @@
 TEST(MediaStreamDispatcherTest, BasicStreamForDevice) {
   static const char kDeviceId[] = "/dev/video0";
 
-  scoped_ptr<MessageLoop> message_loop(new MessageLoop());
+  scoped_ptr<base::MessageLoop> message_loop(new base::MessageLoop());
   scoped_ptr<MediaStreamDispatcher> dispatcher(new MediaStreamDispatcher(NULL));
   scoped_ptr<MockMediaStreamDispatcherEventHandler>
       handler(new MockMediaStreamDispatcherEventHandler);
@@ -228,7 +228,7 @@
 }
 
 TEST(MediaStreamDispatcherTest, BasicVideoDevice) {
-  scoped_ptr<MessageLoop> message_loop(new MessageLoop());
+  scoped_ptr<base::MessageLoop> message_loop(new base::MessageLoop());
   scoped_ptr<MediaStreamDispatcher> dispatcher(new MediaStreamDispatcher(NULL));
   scoped_ptr<MockMediaStreamDispatcherEventHandler>
       handler1(new MockMediaStreamDispatcherEventHandler);
@@ -315,7 +315,7 @@
 }
 
 TEST(MediaStreamDispatcherTest, TestFailure) {
-  scoped_ptr<MessageLoop> message_loop(new MessageLoop());
+  scoped_ptr<base::MessageLoop> message_loop(new base::MessageLoop());
   scoped_ptr<MediaStreamDispatcher> dispatcher(new MediaStreamDispatcher(NULL));
   scoped_ptr<MockMediaStreamDispatcherEventHandler>
       handler(new MockMediaStreamDispatcherEventHandler);
@@ -367,7 +367,7 @@
 }
 
 TEST(MediaStreamDispatcherTest, CancelGenerateStream) {
-  scoped_ptr<MessageLoop> message_loop(new MessageLoop());
+  scoped_ptr<base::MessageLoop> message_loop(new base::MessageLoop());
   scoped_ptr<MediaStreamDispatcher> dispatcher(new MediaStreamDispatcher(NULL));
   scoped_ptr<MockMediaStreamDispatcherEventHandler>
       handler(new MockMediaStreamDispatcherEventHandler);
diff --git a/content/renderer/media/media_stream_impl.cc b/content/renderer/media/media_stream_impl.cc
index 85c8fde..518dc5b 100644
--- a/content/renderer/media/media_stream_impl.cc
+++ b/content/renderer/media/media_stream_impl.cc
@@ -15,7 +15,6 @@
 #include "content/renderer/media/media_stream_extra_data.h"
 #include "content/renderer/media/media_stream_source_extra_data.h"
 #include "content/renderer/media/rtc_video_renderer.h"
-#include "content/renderer/media/video_capture_impl_manager.h"
 #include "content/renderer/media/webrtc_audio_capturer.h"
 #include "content/renderer/media/webrtc_audio_renderer.h"
 #include "content/renderer/media/webrtc_local_audio_renderer.h"
@@ -27,7 +26,6 @@
 #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/WebMediaStreamRegistry.h"
-#include "third_party/WebKit/Source/WebKit/chromium/public/WebSecurityOrigin.h"
 #include "webkit/media/media_stream_audio_renderer.h"
 
 namespace content {
@@ -92,7 +90,7 @@
           type,
           UTF8ToUTF16(devices[i].device.name));
     webkit_sources[i].setExtraData(
-        new content::MediaStreamSourceExtraData(devices[i]));
+        new content::MediaStreamSourceExtraData(devices[i], webkit_sources[i]));
     webkit_sources[i].setDeviceId(UTF8ToUTF16(devices[i].device.id.c_str()));
   }
 }
@@ -111,12 +109,10 @@
 MediaStreamImpl::MediaStreamImpl(
     RenderView* render_view,
     MediaStreamDispatcher* media_stream_dispatcher,
-    VideoCaptureImplManager* vc_manager,
     MediaStreamDependencyFactory* dependency_factory)
     : RenderViewObserver(render_view),
       dependency_factory_(dependency_factory),
-      media_stream_dispatcher_(media_stream_dispatcher),
-      vc_manager_(vc_manager) {
+      media_stream_dispatcher_(media_stream_dispatcher) {
 }
 
 MediaStreamImpl::~MediaStreamImpl() {
@@ -310,11 +306,13 @@
   CreateWebKitSourceVector(label, audio_array,
                            WebKit::WebMediaStreamSource::TypeAudio,
                            audio_source_vector);
+  request_info->audio_sources.assign(audio_source_vector);
   WebKit::WebVector<WebKit::WebMediaStreamSource> video_source_vector(
       video_array.size());
   CreateWebKitSourceVector(label, video_array,
                            WebKit::WebMediaStreamSource::TypeVideo,
                            video_source_vector);
+  request_info->video_sources.assign(video_source_vector);
 
   WebKit::WebUserMediaRequest* request = &(request_info->request);
   WebKit::WebString webkit_label = UTF8ToUTF16(label);
@@ -331,6 +329,7 @@
       WebKit::WebMediaConstraints() : request->videoConstraints();
 
   dependency_factory_->CreateNativeMediaSources(
+      RenderViewObserver::routing_id(),
       audio_constraints, video_constraints, description,
       base::Bind(&MediaStreamImpl::OnCreateNativeSourcesComplete, AsWeakPtr()));
 }
@@ -476,6 +475,11 @@
   NOTREACHED();
 }
 
+void MediaStreamImpl::FrameDetached(WebKit::WebFrame* frame) {
+  // Do same thing as FrameWillClose.
+  FrameWillClose(frame);
+}
+
 void MediaStreamImpl::FrameWillClose(WebKit::WebFrame* frame) {
   // Loop through all UserMediaRequests and find the requests that belong to the
   // frame that is being closed.
@@ -558,13 +562,16 @@
 
   // Create a new WebRtcLocalAudioRenderer instance and connect it to the
   // existing WebRtcAudioCapturer so that the renderer can use it as source.
-  return new WebRtcLocalAudioRenderer(source, audio_track,
-                                      RenderViewObserver::routing_id());
+  return new WebRtcLocalAudioRenderer(
+      static_cast<WebRtcLocalAudioTrack*>(audio_track),
+      RenderViewObserver::routing_id());
 }
 
 MediaStreamSourceExtraData::MediaStreamSourceExtraData(
-    const StreamDeviceInfo& device_info)
-    : device_info_(device_info) {
+    const StreamDeviceInfo& device_info,
+    const WebKit::WebMediaStreamSource& webkit_source)
+    : device_info_(device_info),
+      webkit_source_(webkit_source) {
 }
 
 MediaStreamSourceExtraData::MediaStreamSourceExtraData(
@@ -593,4 +600,35 @@
     stream_stop_callback_.Run(stream_->label());
 }
 
+MediaStreamImpl::UserMediaRequestInfo::UserMediaRequestInfo()
+    : request_id(0), generated(false), frame(NULL), request() {
+}
+
+MediaStreamImpl::UserMediaRequestInfo::UserMediaRequestInfo(
+    int request_id,
+    WebKit::WebFrame* frame,
+    const WebKit::WebUserMediaRequest& request)
+    : request_id(request_id), generated(false), frame(frame),
+      request(request) {
+}
+
+MediaStreamImpl::UserMediaRequestInfo::~UserMediaRequestInfo() {
+  // Release the extra data field of all sources created by
+  // MediaStreamImpl for this request. This breaks the circular reference to
+  // WebKit::MediaStreamSource.
+  // TODO(tommyw): Remove this once WebKit::MediaStreamSource::Owner has been
+  // implemented to fully avoid a circular dependency.
+  for (size_t i = 0; i < audio_sources.size(); ++i) {
+    audio_sources[i].setReadyState(
+        WebKit::WebMediaStreamSource::ReadyStateEnded);
+    audio_sources[i].setExtraData(NULL);
+  }
+
+  for (size_t i = 0; i < video_sources.size(); ++i) {
+    video_sources[i].setReadyState(
+            WebKit::WebMediaStreamSource::ReadyStateEnded);
+    video_sources[i].setExtraData(NULL);
+  }
+}
+
 }  // namespace content
diff --git a/content/renderer/media/media_stream_impl.h b/content/renderer/media/media_stream_impl.h
index 1845ca0..f088fa0 100644
--- a/content/renderer/media/media_stream_impl.h
+++ b/content/renderer/media/media_stream_impl.h
@@ -31,7 +31,6 @@
 namespace content {
 class MediaStreamDependencyFactory;
 class MediaStreamDispatcher;
-class VideoCaptureImplManager;
 class WebRtcAudioRenderer;
 class WebRtcLocalAudioRenderer;
 
@@ -52,7 +51,6 @@
   MediaStreamImpl(
       RenderView* render_view,
       MediaStreamDispatcher* media_stream_dispatcher,
-      VideoCaptureImplManager* vc_manager,
       MediaStreamDependencyFactory* dependency_factory);
   virtual ~MediaStreamImpl();
 
@@ -98,6 +96,7 @@
   virtual void OnDeviceOpenFailed(int request_id) OVERRIDE;
 
   // RenderViewObserver OVERRIDE
+  virtual void FrameDetached(WebKit::WebFrame* frame) OVERRIDE;
   virtual void FrameWillClose(WebKit::WebFrame* frame) OVERRIDE;
 
  protected:
@@ -130,15 +129,11 @@
   // Structure for storing information about a WebKit request to create a
   // MediaStream.
   struct UserMediaRequestInfo {
-    UserMediaRequestInfo()
-        : request_id(0), generated(false), frame(NULL), request() {
-    }
+    UserMediaRequestInfo();
     UserMediaRequestInfo(int request_id,
                          WebKit::WebFrame* frame,
-                         const WebKit::WebUserMediaRequest& request)
-        : request_id(request_id), generated(false), frame(frame),
-          request(request) {
-    }
+                         const WebKit::WebUserMediaRequest& request);
+    ~UserMediaRequestInfo();
     int request_id;
     // True if MediaStreamDispatcher has generated the stream, see
     // OnStreamGenerated.
@@ -146,6 +141,8 @@
     WebKit::WebFrame* frame;  // WebFrame that requested the MediaStream.
     WebKit::WebMediaStream descriptor;
     WebKit::WebUserMediaRequest request;
+    WebKit::WebVector<WebKit::WebMediaStreamSource> audio_sources;
+    WebKit::WebVector<WebKit::WebMediaStreamSource> video_sources;
   };
   typedef ScopedVector<UserMediaRequestInfo> UserMediaRequests;
 
@@ -175,8 +172,6 @@
   // valid for the lifetime of RenderView.
   MediaStreamDispatcher* media_stream_dispatcher_;
 
-  scoped_refptr<VideoCaptureImplManager> vc_manager_;
-
   UserMediaRequests user_media_requests_;
 
   DISALLOW_COPY_AND_ASSIGN(MediaStreamImpl);
diff --git a/content/renderer/media/media_stream_impl_unittest.cc b/content/renderer/media/media_stream_impl_unittest.cc
index 3cf0cc4..d1b2a20 100644
--- a/content/renderer/media/media_stream_impl_unittest.cc
+++ b/content/renderer/media/media_stream_impl_unittest.cc
@@ -28,10 +28,8 @@
   };
 
   MediaStreamImplUnderTest(MediaStreamDispatcher* media_stream_dispatcher,
-                           VideoCaptureImplManager* vc_manager,
                            MediaStreamDependencyFactory* dependency_factory)
-      : MediaStreamImpl(NULL, media_stream_dispatcher, vc_manager,
-                        dependency_factory),
+      : MediaStreamImpl(NULL, media_stream_dispatcher, dependency_factory),
         state_(REQUEST_NOT_STARTED) {
   }
 
@@ -77,11 +75,8 @@
   virtual void SetUp() {
     // Create our test object.
     ms_dispatcher_.reset(new MockMediaStreamDispatcher());
-    scoped_refptr<VideoCaptureImplManager> vc_manager(
-        new VideoCaptureImplManager());
     dependency_factory_.reset(new MockMediaStreamDependencyFactory());
     ms_impl_.reset(new MediaStreamImplUnderTest(ms_dispatcher_.get(),
-                                                vc_manager.get(),
                                                 dependency_factory_.get()));
   }
 
diff --git a/content/renderer/media/media_stream_registry_interface.h b/content/renderer/media/media_stream_registry_interface.h
new file mode 100644
index 0000000..cc309b9
--- /dev/null
+++ b/content/renderer/media/media_stream_registry_interface.h
@@ -0,0 +1,25 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_RENDERER_MEDIA_MEDIA_STREAM_REGISTRY_INTERFACE_H_
+#define CONTENT_RENDERER_MEDIA_MEDIA_STREAM_REGISTRY_INTERFACE_H_
+
+#include <string>
+
+#include "third_party/WebKit/Source/Platform/chromium/public/WebMediaStream.h"
+
+namespace content {
+
+// Interface to get WebMediaStream from its url.
+class MediaStreamRegistryInterface {
+ public:
+  virtual WebKit::WebMediaStream GetMediaStream(const std::string& url) = 0;
+
+ protected:
+  virtual ~MediaStreamRegistryInterface() {}
+};
+
+}  // namespace content
+
+#endif  // CONTENT_RENDERER_MEDIA_MEDIA_STREAM_REGISTRY_INTERFACE_H_
diff --git a/content/renderer/media/media_stream_source_extra_data.h b/content/renderer/media/media_stream_source_extra_data.h
index a5fb9ad..85ed1af 100644
--- a/content/renderer/media/media_stream_source_extra_data.h
+++ b/content/renderer/media/media_stream_source_extra_data.h
@@ -8,6 +8,7 @@
 #include "base/compiler_specific.h"
 #include "content/common/content_export.h"
 #include "content/common/media/media_stream_options.h"
+#include "content/renderer/media/media_stream_source_observer.h"
 #include "media/base/audio_capturer_source.h"
 #include "third_party/libjingle/source/talk/app/webrtc/videosourceinterface.h"
 #include "third_party/WebKit/Source/Platform/chromium/public/WebMediaStreamSource.h"
@@ -17,13 +18,18 @@
 class CONTENT_EXPORT MediaStreamSourceExtraData
     : NON_EXPORTED_BASE(public WebKit::WebMediaStreamSource::ExtraData) {
  public:
-
-  explicit MediaStreamSourceExtraData(
-      const StreamDeviceInfo& device_info);
+  MediaStreamSourceExtraData(
+      const StreamDeviceInfo& device_info,
+      const WebKit::WebMediaStreamSource& webkit_source);
   explicit MediaStreamSourceExtraData(
       media::AudioCapturerSource* source);
   virtual ~MediaStreamSourceExtraData();
 
+  // Returns the WebMediaStreamSource object that owns this object.
+  const WebKit::WebMediaStreamSource& webkit_source() const {
+    return webkit_source_;
+  }
+
   // Return device information about the camera or microphone.
   const StreamDeviceInfo& device_info() const {
     return device_info_;
@@ -31,10 +37,13 @@
 
   void SetVideoSource(webrtc::VideoSourceInterface* source) {
     video_source_ = source;
+    source_observer_.reset(new MediaStreamSourceObserver(source, this));
   }
 
   void SetLocalAudioSource(webrtc::AudioSourceInterface* source) {
     local_audio_source_ = source;
+    // TODO(perkj): Implement a local source observer for audio.
+    // See |source_observer_|.
   }
 
   webrtc::VideoSourceInterface* video_source() { return video_source_; }
@@ -45,6 +54,16 @@
 
  private:
   StreamDeviceInfo device_info_;
+
+  // TODO(tommyw): Remove |webkit_source_| after WebMediaStreamSource::Owner()
+  // is implemented, which let us fetch the
+  // WebMediaStreamSource without increasing the reference count.
+  // |webkit_source_| will create a circular reference to WebMediaStreamSource.
+  // WebMediaStreamSource -> MediaStreamSourceExtraData -> WebMediaStreamSource
+  // Currently, we rely on manually releasing the MediaStreamSourceExtraData
+  // from WebMediaStreamSource like what
+  // MediaStreamImpl::~UserMediaRequestInfo() does.
+  WebKit::WebMediaStreamSource webkit_source_;
   scoped_refptr<webrtc::VideoSourceInterface> video_source_;
   scoped_refptr<media::AudioCapturerSource> audio_source_;
 
@@ -53,6 +72,7 @@
   // TODO(hclam): This should be merged with |audio_source_| such that it
   // carries audio options.
   scoped_refptr<webrtc::AudioSourceInterface> local_audio_source_;
+  scoped_ptr<MediaStreamSourceObserver> source_observer_;
 
   DISALLOW_COPY_AND_ASSIGN(MediaStreamSourceExtraData);
 };
diff --git a/content/renderer/media/media_stream_source_observer.cc b/content/renderer/media/media_stream_source_observer.cc
new file mode 100644
index 0000000..a62c997
--- /dev/null
+++ b/content/renderer/media/media_stream_source_observer.cc
@@ -0,0 +1,63 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/media/media_stream_source_observer.h"
+
+#include "base/logging.h"
+#include "content/renderer/media/media_stream_source_extra_data.h"
+
+namespace content {
+
+MediaStreamSourceObserver::MediaStreamSourceObserver(
+    webrtc::MediaSourceInterface* webrtc_source,
+    MediaStreamSourceExtraData* extra_data)
+     : state_(webrtc_source->state()),
+       webrtc_source_(webrtc_source),
+       extra_data_(extra_data) {
+  webrtc_source_->RegisterObserver(this);
+}
+
+MediaStreamSourceObserver::~MediaStreamSourceObserver() {
+  DCHECK(CalledOnValidThread());
+  if (webrtc_source_)
+    webrtc_source_->UnregisterObserver(this);
+}
+
+void MediaStreamSourceObserver::OnChanged() {
+  DCHECK(CalledOnValidThread());
+  // There should be no more notification after kEnded.
+  DCHECK(webrtc_source_ != NULL);
+
+  webrtc::MediaSourceInterface::SourceState state = webrtc_source_->state();
+  if (state == state_)
+    return;
+  state_ = state;
+  WebKit::WebMediaStreamSource webkit_source(extra_data_->webkit_source());
+
+  switch (state) {
+    case webrtc::MediaSourceInterface::kInitializing:
+      // Ignore the kInitializing state since there is no match in
+      // WebMediaStreamSource::ReadyState.
+      break;
+    case webrtc::MediaSourceInterface::kLive:
+      webkit_source.setReadyState(
+          WebKit::WebMediaStreamSource::ReadyStateLive);
+      break;
+    case webrtc::MediaSourceInterface::kMuted:
+      webkit_source.setReadyState(
+          WebKit::WebMediaStreamSource::ReadyStateMuted);
+      break;
+    case webrtc::MediaSourceInterface::kEnded:
+      webkit_source.setReadyState(
+          WebKit::WebMediaStreamSource::ReadyStateEnded);
+      webrtc_source_->UnregisterObserver(this);
+      webrtc_source_ = NULL;
+      break;
+    default:
+      NOTREACHED();
+      break;
+  }
+}
+
+}  // namespace content
diff --git a/content/renderer/media/media_stream_source_observer.h b/content/renderer/media/media_stream_source_observer.h
new file mode 100644
index 0000000..b8a363d
--- /dev/null
+++ b/content/renderer/media/media_stream_source_observer.h
@@ -0,0 +1,42 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_RENDERER_MEDIA_MEDIA_STREAM_SOURCE_OBSERVER_H_
+#define CONTENT_RENDERER_MEDIA_MEDIA_STREAM_SOURCE_OBSERVER_H_
+
+#include "base/compiler_specific.h"
+#include "base/memory/ref_counted.h"
+#include "base/threading/non_thread_safe.h"
+#include "content/common/content_export.h"
+#include "third_party/libjingle/source/talk/app/webrtc/mediastreaminterface.h"
+#include "third_party/WebKit/Source/Platform/chromium/public/WebMediaStreamSource.h"
+
+namespace content {
+
+class MediaStreamSourceExtraData;
+
+// MediaStreamSourceObserver listens to events on MediaSourceInterface and
+// notify WebKit. It will be owned by MediaStreamSourceExtraData.
+class CONTENT_EXPORT MediaStreamSourceObserver
+    : NON_EXPORTED_BASE(public webrtc::ObserverInterface),
+      NON_EXPORTED_BASE(public base::NonThreadSafe) {
+ public:
+  MediaStreamSourceObserver(webrtc::MediaSourceInterface* webrtc_source,
+                            MediaStreamSourceExtraData* extra_data);
+  virtual ~MediaStreamSourceObserver();
+
+ private:
+  // webrtc::ObserverInterface implementation.
+  virtual void OnChanged() OVERRIDE;
+
+  webrtc::MediaSourceInterface::SourceState state_;
+  scoped_refptr<webrtc::MediaSourceInterface> webrtc_source_;
+  MediaStreamSourceExtraData* extra_data_;
+
+  DISALLOW_COPY_AND_ASSIGN(MediaStreamSourceObserver);
+};
+
+}  // namespace content
+
+#endif  // CONTENT_RENDERER_MEDIA_MEDIA_STREAM_SOURCE_OBSERVER_H_
diff --git a/content/renderer/media/mock_media_stream_dependency_factory.cc b/content/renderer/media/mock_media_stream_dependency_factory.cc
index af3177f..c47ba26 100644
--- a/content/renderer/media/mock_media_stream_dependency_factory.cc
+++ b/content/renderer/media/mock_media_stream_dependency_factory.cc
@@ -5,9 +5,11 @@
 #include "content/renderer/media/mock_media_stream_dependency_factory.h"
 
 #include "base/logging.h"
+#include "base/utf_string_conversions.h"
 #include "content/renderer/media/mock_peer_connection_impl.h"
 #include "third_party/libjingle/source/talk/app/webrtc/mediastreaminterface.h"
 #include "third_party/libjingle/source/talk/base/scoped_ref_ptr.h"
+#include "third_party/libjingle/source/talk/media/base/videocapturer.h"
 
 using webrtc::AudioSourceInterface;
 using webrtc::AudioTrackInterface;
@@ -39,23 +41,40 @@
 class MockMediaStream : public webrtc::MediaStreamInterface {
  public:
   explicit MockMediaStream(const std::string& label)
-      : label_(label) {
+      : label_(label),
+        observer_(NULL) {
   }
   virtual bool AddTrack(AudioTrackInterface* track) OVERRIDE {
     audio_track_vector_.push_back(track);
+    if (observer_)
+      observer_->OnChanged();
     return true;
   }
   virtual bool AddTrack(VideoTrackInterface* track) OVERRIDE {
     video_track_vector_.push_back(track);
+    if (observer_)
+      observer_->OnChanged();
     return true;
   }
   virtual bool RemoveTrack(AudioTrackInterface* track) OVERRIDE {
-    NOTIMPLEMENTED();
-    return false;
+    AudioTrackVector::iterator it = FindTrack(&audio_track_vector_,
+                                              track->id());
+    if (it == audio_track_vector_.end())
+      return false;
+    audio_track_vector_.erase(it);
+    if (observer_)
+      observer_->OnChanged();
+    return true;
   }
   virtual bool RemoveTrack(VideoTrackInterface* track) OVERRIDE {
-    NOTIMPLEMENTED();
-    return false;
+    VideoTrackVector::iterator it = FindTrack(&video_track_vector_,
+                                              track->id());
+    if (it == video_track_vector_.end())
+      return false;
+    video_track_vector_.erase(it);
+    if (observer_)
+      observer_->OnChanged();
+    return true;
   }
   virtual std::string label() const OVERRIDE { return label_; }
   virtual AudioTrackVector GetAudioTracks() OVERRIDE {
@@ -75,10 +94,12 @@
     return it == video_track_vector_.end() ? NULL : *it;
   }
   virtual void RegisterObserver(ObserverInterface* observer) OVERRIDE {
-    NOTIMPLEMENTED();
+    DCHECK(!observer_);
+    observer_ = observer;
   }
   virtual void UnregisterObserver(ObserverInterface* observer) OVERRIDE {
-    NOTIMPLEMENTED();
+    DCHECK(observer_ == observer);
+    observer_ = NULL;
   }
 
  protected:
@@ -88,6 +109,7 @@
   std::string label_;
   AudioTrackVector audio_track_vector_;
   VideoTrackVector video_track_vector_;
+  webrtc::ObserverInterface* observer_;
 };
 
 MockAudioSource::MockAudioSource(
@@ -128,15 +150,17 @@
 }
 
 MockVideoSource::MockVideoSource()
-    : observer_(NULL),
-      state_(MediaSourceInterface::kInitializing) {
+    : state_(MediaSourceInterface::kInitializing) {
 }
 
 MockVideoSource::~MockVideoSource() {}
 
+void MockVideoSource::SetVideoCapturer(cricket::VideoCapturer* capturer) {
+  capturer_.reset(capturer);
+}
+
 cricket::VideoCapturer* MockVideoSource::GetVideoCapturer() {
-  NOTIMPLEMENTED();
-  return NULL;
+  return capturer_.get();
 }
 
 void MockVideoSource::AddSink(cricket::VideoRenderer* output) {
@@ -148,26 +172,37 @@
 }
 
 void MockVideoSource::RegisterObserver(webrtc::ObserverInterface* observer) {
-  observer_ = observer;
+  observers_.push_back(observer);
 }
 
 void MockVideoSource::UnregisterObserver(webrtc::ObserverInterface* observer) {
-  DCHECK(observer_  == observer);
-  observer_ = NULL;
+  for (std::vector<ObserverInterface*>::iterator it = observers_.begin();
+       it != observers_.end(); ++it) {
+    if (*it == observer) {
+      observers_.erase(it);
+      break;
+    }
+  }
+}
+
+void MockVideoSource::FireOnChanged() {
+  std::vector<ObserverInterface*> observers(observers_);
+  for (std::vector<ObserverInterface*>::iterator it = observers.begin();
+       it != observers.end(); ++it) {
+    (*it)->OnChanged();
+  }
 }
 
 void MockVideoSource::SetLive() {
   DCHECK_EQ(MediaSourceInterface::kInitializing, state_);
   state_ = MediaSourceInterface::kLive;
-  if (observer_)
-    observer_->OnChanged();
+  FireOnChanged();
 }
 
 void MockVideoSource::SetEnded() {
   DCHECK_NE(MediaSourceInterface::kEnded, state_);
   state_ = MediaSourceInterface::kEnded;
-  if (observer_)
-    observer_->OnChanged();
+  FireOnChanged();
 }
 
 webrtc::MediaSourceInterface::SourceState MockVideoSource::state() const {
@@ -183,7 +218,9 @@
                                          webrtc::VideoSourceInterface* source)
     : enabled_(false),
       id_(id),
-      source_(source) {
+      state_(MediaStreamTrackInterface::kLive),
+      source_(source),
+      observer_(NULL) {
 }
 
 MockLocalVideoTrack::~MockLocalVideoTrack() {}
@@ -203,7 +240,7 @@
 
 std::string MockLocalVideoTrack::kind() const {
   NOTIMPLEMENTED();
-  return "";
+  return std::string();
 }
 
 std::string MockLocalVideoTrack::id() const { return id_; }
@@ -211,8 +248,7 @@
 bool MockLocalVideoTrack::enabled() const { return enabled_; }
 
 MockLocalVideoTrack::TrackState MockLocalVideoTrack::state() const {
-  NOTIMPLEMENTED();
-  return kInitializing;
+  return state_;
 }
 
 bool MockLocalVideoTrack::set_enabled(bool enable) {
@@ -221,16 +257,19 @@
 }
 
 bool MockLocalVideoTrack::set_state(TrackState new_state) {
-  NOTIMPLEMENTED();
-  return false;
+  state_ = new_state;
+  if (observer_)
+    observer_->OnChanged();
+  return true;
 }
 
 void MockLocalVideoTrack::RegisterObserver(ObserverInterface* observer) {
-  NOTIMPLEMENTED();
+  observer_ = observer;
 }
 
 void MockLocalVideoTrack::UnregisterObserver(ObserverInterface* observer) {
-  NOTIMPLEMENTED();
+  DCHECK(observer_ == observer);
+  observer_ = NULL;
 }
 
 VideoSourceInterface* MockLocalVideoTrack::GetSource() const {
@@ -239,16 +278,15 @@
 
 std::string MockLocalAudioTrack::kind() const {
   NOTIMPLEMENTED();
-  return "";
+  return std::string();
 }
 
 std::string MockLocalAudioTrack::id() const { return id_; }
 
 bool MockLocalAudioTrack::enabled() const { return enabled_; }
 
-MockLocalVideoTrack::TrackState MockLocalAudioTrack::state() const {
-  NOTIMPLEMENTED();
-  return kInitializing;
+MockLocalAudioTrack::TrackState MockLocalAudioTrack::state() const {
+  return state_;
 }
 
 bool MockLocalAudioTrack::set_enabled(bool enable) {
@@ -257,16 +295,19 @@
 }
 
 bool MockLocalAudioTrack::set_state(TrackState new_state) {
-  NOTIMPLEMENTED();
-  return false;
+  state_ = new_state;
+  if (observer_)
+    observer_->OnChanged();
+  return true;
 }
 
 void MockLocalAudioTrack::RegisterObserver(ObserverInterface* observer) {
-  NOTIMPLEMENTED();
+  observer_ = observer;
 }
 
 void MockLocalAudioTrack::UnregisterObserver(ObserverInterface* observer) {
-  NOTIMPLEMENTED();
+  DCHECK(observer_ == observer);
+  observer_ = NULL;
 }
 
 AudioSourceInterface* MockLocalAudioTrack::GetSource() const {
@@ -292,11 +333,11 @@
   }
   virtual std::string session_id() const OVERRIDE {
     NOTIMPLEMENTED();
-    return "";
+    return std::string();
   }
   virtual std::string session_version() const OVERRIDE {
     NOTIMPLEMENTED();
-    return "";
+    return std::string();
   }
   virtual std::string type() const OVERRIDE {
     return type_;
@@ -403,7 +444,8 @@
 }
 
 bool MockMediaStreamDependencyFactory::InitializeAudioSource(
-  const StreamDeviceInfo& device_info) {
+    int render_view_id,
+    const StreamDeviceInfo& device_info) {
   return true;
 }
 
@@ -430,6 +472,19 @@
   return track;
 }
 
+scoped_refptr<webrtc::VideoTrackInterface>
+MockMediaStreamDependencyFactory::CreateLocalVideoTrack(
+    const std::string& id,
+    cricket::VideoCapturer* capturer) {
+  DCHECK(mock_pc_factory_created_);
+
+  scoped_refptr<MockVideoSource> source =
+      new talk_base::RefCountedObject<MockVideoSource>();
+  source->SetVideoCapturer(capturer);
+
+  return new talk_base::RefCountedObject<MockLocalVideoTrack>(id, source);
+}
+
 scoped_refptr<webrtc::AudioTrackInterface>
 MockMediaStreamDependencyFactory::CreateLocalAudioTrack(
     const std::string& id,
diff --git a/content/renderer/media/mock_media_stream_dependency_factory.h b/content/renderer/media/mock_media_stream_dependency_factory.h
index e7c4221..7b44ac2 100644
--- a/content/renderer/media/mock_media_stream_dependency_factory.h
+++ b/content/renderer/media/mock_media_stream_dependency_factory.h
@@ -10,6 +10,7 @@
 
 #include "base/compiler_specific.h"
 #include "content/renderer/media/media_stream_dependency_factory.h"
+#include "third_party/libjingle/source/talk/app/webrtc/mediaconstraintsinterface.h"
 
 namespace content {
 
@@ -29,18 +30,24 @@
   void SetLive();
   // Changes the state of the source to ended and notifies the observer.
   void SetEnded();
+  // Set the video capturer.
+  void SetVideoCapturer(cricket::VideoCapturer* capturer);
 
  protected:
   virtual ~MockVideoSource();
 
  private:
-   webrtc::ObserverInterface* observer_;
-   MediaSourceInterface::SourceState state_;
+  void FireOnChanged();
+
+  std::vector<webrtc::ObserverInterface*> observers_;
+  MediaSourceInterface::SourceState state_;
+  scoped_ptr<cricket::VideoCapturer> capturer_;
 };
 
 class MockAudioSource : public webrtc::AudioSourceInterface {
  public:
-  MockAudioSource(const webrtc::MediaConstraintsInterface* constraints);
+  explicit MockAudioSource(
+      const webrtc::MediaConstraintsInterface* constraints);
 
   virtual void RegisterObserver(webrtc::ObserverInterface* observer) OVERRIDE;
   virtual void UnregisterObserver(webrtc::ObserverInterface* observer) OVERRIDE;
@@ -94,14 +101,18 @@
  private:
   bool enabled_;
   std::string id_;
+  TrackState state_;
   scoped_refptr<webrtc::VideoSourceInterface> source_;
+  webrtc::ObserverInterface* observer_;
 };
 
 class MockLocalAudioTrack : public webrtc::AudioTrackInterface {
  public:
   explicit MockLocalAudioTrack(const std::string& id)
     : enabled_(false),
-      id_(id) {
+      id_(id),
+      state_(MediaStreamTrackInterface::kLive),
+      observer_(NULL) {
   }
   virtual std::string kind() const OVERRIDE;
   virtual std::string id() const OVERRIDE;
@@ -119,6 +130,8 @@
  private:
   bool enabled_;
   std::string id_;
+  TrackState state_;
+  webrtc::ObserverInterface* observer_;
 };
 
 // A mock factory for creating different objects for
@@ -142,7 +155,7 @@
           bool is_screencast,
           const webrtc::MediaConstraintsInterface* constraints) OVERRIDE;
   virtual bool InitializeAudioSource(
-      const StreamDeviceInfo& device_info) OVERRIDE;
+      int render_view_id, const StreamDeviceInfo& device_info) OVERRIDE;
   virtual bool CreateWebAudioSource(
       WebKit::WebMediaStreamSource* source) OVERRIDE;
   virtual scoped_refptr<webrtc::MediaStreamInterface>
@@ -150,6 +163,9 @@
   virtual scoped_refptr<webrtc::VideoTrackInterface>
       CreateLocalVideoTrack(const std::string& id,
                             webrtc::VideoSourceInterface* source) OVERRIDE;
+  virtual scoped_refptr<webrtc::VideoTrackInterface>
+      CreateLocalVideoTrack(const std::string& id,
+                            cricket::VideoCapturer* capturer) OVERRIDE;
   virtual scoped_refptr<webrtc::AudioTrackInterface>
       CreateLocalAudioTrack(const std::string& id,
                             webrtc::AudioSourceInterface* source) OVERRIDE;
diff --git a/content/renderer/media/mock_media_stream_registry.cc b/content/renderer/media/mock_media_stream_registry.cc
new file mode 100644
index 0000000..964be2a
--- /dev/null
+++ b/content/renderer/media/mock_media_stream_registry.cc
@@ -0,0 +1,54 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/media/mock_media_stream_registry.h"
+
+#include <string>
+
+#include "base/utf_string_conversions.h"
+#include "third_party/WebKit/Source/Platform/chromium/public/WebMediaStreamSource.h"
+#include "third_party/WebKit/Source/Platform/chromium/public/WebMediaStreamTrack.h"
+#include "third_party/WebKit/Source/Platform/chromium/public/WebString.h"
+#include "third_party/WebKit/Source/Platform/chromium/public/WebVector.h"
+#include "third_party/libjingle/source/talk/media/base/videocapturer.h"
+
+namespace content {
+
+static const std::string kTestStreamLabel = "stream_label";
+
+MockMediaStreamRegistry::MockMediaStreamRegistry(
+    MockMediaStreamDependencyFactory* factory)
+    : factory_(factory) {
+}
+
+void MockMediaStreamRegistry::Init(const std::string& stream_url) {
+  stream_url_ = stream_url;
+  scoped_refptr<webrtc::MediaStreamInterface> stream(
+      factory_->CreateLocalMediaStream(kTestStreamLabel));
+  WebKit::WebVector<WebKit::WebMediaStreamTrack> webkit_audio_tracks;
+  WebKit::WebVector<WebKit::WebMediaStreamTrack> webkit_video_tracks;
+  WebKit::WebString webkit_stream_label(UTF8ToUTF16(stream->label()));
+  test_stream_.initialize(webkit_stream_label,
+                          webkit_audio_tracks, webkit_video_tracks);
+  test_stream_.setExtraData(new MediaStreamExtraData(stream, false));
+}
+
+bool MockMediaStreamRegistry::AddVideoTrack(const std::string& track_id) {
+  cricket::VideoCapturer* capturer = NULL;
+  return factory_->AddNativeVideoMediaTrack(track_id, &test_stream_, capturer);
+}
+
+WebKit::WebMediaStream MockMediaStreamRegistry::GetMediaStream(
+    const std::string& url) {
+  if (url != stream_url_) {
+    return WebKit::WebMediaStream();
+  }
+  return test_stream_;
+}
+
+const WebKit::WebMediaStream MockMediaStreamRegistry::test_stream() const {
+  return test_stream_;
+}
+
+}  // namespace content
diff --git a/content/renderer/media/mock_media_stream_registry.h b/content/renderer/media/mock_media_stream_registry.h
new file mode 100644
index 0000000..4d77395
--- /dev/null
+++ b/content/renderer/media/mock_media_stream_registry.h
@@ -0,0 +1,33 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_RENDERER_MEDIA_MOCK_MEDIA_STREAM_REGISTRY_H_
+#define CONTENT_RENDERER_MEDIA_MOCK_MEDIA_STREAM_REGISTRY_H_
+
+#include <string>
+
+#include "content/renderer/media/media_stream_registry_interface.h"
+#include "content/renderer/media/mock_media_stream_dependency_factory.h"
+
+namespace content {
+
+class MockMediaStreamRegistry : public MediaStreamRegistryInterface {
+ public:
+  explicit MockMediaStreamRegistry(MockMediaStreamDependencyFactory* factory);
+
+  void Init(const std::string& stream_label);
+  bool AddVideoTrack(const std::string& track_id);
+  virtual WebKit::WebMediaStream GetMediaStream(const std::string& url)
+      OVERRIDE;
+  const WebKit::WebMediaStream test_stream() const;
+
+ private:
+  MockMediaStreamDependencyFactory* factory_;
+  WebKit::WebMediaStream test_stream_;
+  std::string stream_url_;
+};
+
+}  // namespace content
+
+#endif  // CONTENT_RENDERER_MEDIA_MOCK_MEDIA_STREAM_REGISTRY_H_
diff --git a/content/renderer/media/mock_peer_connection_impl.cc b/content/renderer/media/mock_peer_connection_impl.cc
index 597d24f..db36c30 100644
--- a/content/renderer/media/mock_peer_connection_impl.cc
+++ b/content/renderer/media/mock_peer_connection_impl.cc
@@ -244,21 +244,21 @@
   webrtc::StatsReport report;
   report.id = "1234";
   report.type = "ssrc";
-  report.local.timestamp = 42;
-  webrtc::StatsElement::Value value;
+  report.timestamp = 42;
+  webrtc::StatsReport::Value value;
   value.name = "trackname";
   value.value = "trackvalue";
-  report.local.values.push_back(value);
+  report.values.push_back(value);
   reports.push_back(report);
   // If selector is given, we pass back one report.
   // If selector is not given, we pass back two.
   if (!track) {
     report.id = "nontrack";
     report.type = "generic";
-    report.local.timestamp = 44;
+    report.timestamp = 44;
     value.name = "somename";
     value.value = "somevalue";
-    report.local.values.push_back(value);
+    report.values.push_back(value);
     reports.push_back(report);
   }
   // Note that the callback is synchronous, not asynchronous; it will
diff --git a/content/renderer/media/peer_connection_handler_base.cc b/content/renderer/media/peer_connection_handler_base.cc
index 1854a99..24585e0 100644
--- a/content/renderer/media/peer_connection_handler_base.cc
+++ b/content/renderer/media/peer_connection_handler_base.cc
@@ -51,43 +51,6 @@
   DCHECK(native_stream);
 }
 
-WebKit::WebMediaStream
-PeerConnectionHandlerBase::CreateRemoteWebKitMediaStream(
-    webrtc::MediaStreamInterface* stream) {
-  webrtc::AudioTrackVector audio_tracks = stream->GetAudioTracks();
-  webrtc::VideoTrackVector video_tracks = stream->GetVideoTracks();
-  WebKit::WebVector<WebKit::WebMediaStreamSource> audio_source_vector(
-      audio_tracks.size());
-  WebKit::WebVector<WebKit::WebMediaStreamSource> video_source_vector(
-      video_tracks.size());
-
-  // Add audio tracks.
-  size_t i = 0;
-  for (; i < audio_tracks.size(); ++i) {
-    webrtc::AudioTrackInterface* audio_track = audio_tracks[i];
-    DCHECK(audio_track);
-    audio_source_vector[i].initialize(
-        UTF8ToUTF16(audio_track->id()),
-        WebKit::WebMediaStreamSource::TypeAudio,
-        UTF8ToUTF16(audio_track->id()));
-  }
-
-  // Add video tracks.
-  for (i = 0; i < video_tracks.size(); ++i) {
-    webrtc::VideoTrackInterface* video_track = video_tracks[i];
-    DCHECK(video_track);
-    video_source_vector[i].initialize(
-        UTF8ToUTF16(video_track->id()),
-        WebKit::WebMediaStreamSource::TypeVideo,
-        UTF8ToUTF16(video_track->id()));
-  }
-  WebKit::WebMediaStream descriptor;
-  descriptor.initialize(UTF8ToUTF16(stream->label()),
-                        audio_source_vector, video_source_vector);
-  descriptor.setExtraData(new MediaStreamExtraData(stream, false));
-  return descriptor;
-}
-
 webrtc::MediaStreamTrackInterface*
 PeerConnectionHandlerBase::GetNativeMediaStreamTrack(
     const WebKit::WebMediaStream& stream,
diff --git a/content/renderer/media/peer_connection_handler_base.h b/content/renderer/media/peer_connection_handler_base.h
index 824b5c5..f9c5cef 100644
--- a/content/renderer/media/peer_connection_handler_base.h
+++ b/content/renderer/media/peer_connection_handler_base.h
@@ -18,6 +18,7 @@
 
 namespace content {
 class MediaStreamDependencyFactory;
+class RemoteMediaStreamImpl;
 
 // PeerConnectionHandlerBase is the base class of a delegate for the
 // PeerConnection API messages going between WebKit and native
@@ -35,8 +36,6 @@
   bool AddStream(const WebKit::WebMediaStream& stream,
                  const webrtc::MediaConstraintsInterface* constraints);
   void RemoveStream(const WebKit::WebMediaStream& stream);
-  WebKit::WebMediaStream CreateRemoteWebKitMediaStream(
-      webrtc::MediaStreamInterface* stream);
   webrtc::MediaStreamTrackInterface* GetNativeMediaStreamTrack(
       const WebKit::WebMediaStream& stream,
       const WebKit::WebMediaStreamTrack& component);
@@ -50,7 +49,7 @@
   scoped_refptr<webrtc::PeerConnectionInterface> native_peer_connection_;
 
   typedef std::map<webrtc::MediaStreamInterface*,
-                   WebKit::WebMediaStream> RemoteStreamMap;
+      content::RemoteMediaStreamImpl*> RemoteStreamMap;
   RemoteStreamMap remote_streams_;
 
   // The message loop we are created on and on which to make calls to WebKit.
diff --git a/content/renderer/media/peer_connection_tracker.cc b/content/renderer/media/peer_connection_tracker.cc
index 095d85f..3f2f23e 100644
--- a/content/renderer/media/peer_connection_tracker.cc
+++ b/content/renderer/media/peer_connection_tracker.cc
@@ -150,16 +150,19 @@
   return result;
 }
 
-// Builds a DictionaryValue from the StatsElement.
+// Builds a DictionaryValue from the StatsReport.
 // The caller takes the ownership of the returned value.
-static DictionaryValue* GetDictValue(const webrtc::StatsElement& elem) {
-  if (elem.values.empty())
+// Note:
+// The format must be consistent with what webrtc_internals.js expects.
+// If you change it here, you must change webrtc_internals.js as well.
+static DictionaryValue* GetDictValueStats(const webrtc::StatsReport& report) {
+  if (report.values.empty())
     return NULL;
 
   DictionaryValue* dict = new DictionaryValue();
   if (!dict)
     return NULL;
-  dict->SetDouble("timestamp", elem.timestamp);
+  dict->SetDouble("timestamp", report.timestamp);
 
   ListValue* values = new ListValue();
   if (!values) {
@@ -168,9 +171,9 @@
   }
   dict->Set("values", values);
 
-  for (size_t i = 0; i < elem.values.size(); ++i) {
-    values->AppendString(elem.values[i].name);
-    values->AppendString(elem.values[i].value);
+  for (size_t i = 0; i < report.values.size(); ++i) {
+    values->AppendString(report.values[i].name);
+    values->AppendString(report.values[i].value);
   }
   return dict;
 }
@@ -178,21 +181,21 @@
 // Builds a DictionaryValue from the StatsReport.
 // The caller takes the ownership of the returned value.
 static DictionaryValue* GetDictValue(const webrtc::StatsReport& report) {
-  scoped_ptr<DictionaryValue> local, remote, result;
+  scoped_ptr<DictionaryValue> stats, result;
 
-  local.reset(GetDictValue(report.local));
-  remote.reset(GetDictValue(report.remote));
-  if (!local.get() && !remote.get())
+  stats.reset(GetDictValueStats(report));
+  if (!stats)
     return NULL;
 
   result.reset(new DictionaryValue());
-  if (!result.get())
+  if (!result)
     return NULL;
 
-  if (local.get())
-    result->Set("local", local.release());
-  if (remote.get())
-    result->Set("remote", remote.release());
+  // Note:
+  // The format must be consistent with what webrtc_internals.js expects.
+  // If you change it here, you must change webrtc_internals.js as well.
+  if (stats)
+    result->Set("stats", stats.release());
   result->SetString("id", report.id);
   result->SetString("type", report.type);
 
@@ -310,12 +313,12 @@
 
 void PeerConnectionTracker::TrackSetSessionDescription(
     RTCPeerConnectionHandler* pc_handler,
-    const webrtc::SessionDescriptionInterface* desc,
+    const WebKit::WebRTCSessionDescription& desc,
     Source source) {
-  string sdp;
-  desc->ToString(&sdp);
+  string sdp = UTF16ToUTF8(desc.sdp());
+  string type = UTF16ToUTF8(desc.type());
 
-  string value = "type: " + desc->type() + ", sdp: " + sdp;
+  string value = "type: " + type + ", sdp: " + sdp;
   SendPeerConnectionUpdate(
       pc_handler,
       source == SOURCE_LOCAL ? "setLocalDescription" : "setRemoteDescription",
@@ -376,7 +379,7 @@
 }
 
 void PeerConnectionTracker::TrackStop(RTCPeerConnectionHandler* pc_handler) {
-  SendPeerConnectionUpdate(pc_handler, "stop", "");
+  SendPeerConnectionUpdate(pc_handler, "stop", std::string());
 }
 
 void PeerConnectionTracker::TrackSignalingStateChange(
@@ -430,7 +433,7 @@
 
 void PeerConnectionTracker::TrackOnRenegotiationNeeded(
     RTCPeerConnectionHandler* pc_handler) {
-  SendPeerConnectionUpdate(pc_handler, "onRenegotiationNeeded", "");
+  SendPeerConnectionUpdate(pc_handler, "onRenegotiationNeeded", std::string());
 }
 
 void PeerConnectionTracker::TrackCreateDTMFSender(
diff --git a/content/renderer/media/peer_connection_tracker.h b/content/renderer/media/peer_connection_tracker.h
index 9bd93fc..53e5369 100644
--- a/content/renderer/media/peer_connection_tracker.h
+++ b/content/renderer/media/peer_connection_tracker.h
@@ -11,12 +11,14 @@
 #include "content/public/renderer/render_process_observer.h"
 #include "third_party/WebKit/Source/Platform/chromium/public/WebMediaStream.h"
 #include "third_party/WebKit/Source/Platform/chromium/public/WebRTCPeerConnectionHandlerClient.h"
+#include "third_party/WebKit/Source/Platform/chromium/public/WebRTCSessionDescription.h"
 #include "third_party/libjingle/source/talk/app/webrtc/peerconnectioninterface.h"
 
 namespace WebKit {
 class WebFrame;
 class WebRTCICECandidate;
 class WebString;
+class WebRTCSessionDescription;
 }  // namespace WebKit
 
 namespace webrtc {
@@ -84,7 +86,7 @@
   // Sends an update when setLocalDescription or setRemoteDescription is called.
   virtual void TrackSetSessionDescription(
       RTCPeerConnectionHandler* pc_handler,
-      const webrtc::SessionDescriptionInterface* desc, Source source);
+      const WebKit::WebRTCSessionDescription& desc, Source source);
 
   // Sends an update when Ice candidates are updated.
   virtual void TrackUpdateIce(
diff --git a/content/renderer/media/pepper_platform_video_decoder_impl.cc b/content/renderer/media/pepper_platform_video_decoder_impl.cc
index ab444e8..d305ffa 100644
--- a/content/renderer/media/pepper_platform_video_decoder_impl.cc
+++ b/content/renderer/media/pepper_platform_video_decoder_impl.cc
@@ -26,7 +26,7 @@
 
 bool PlatformVideoDecoderImpl::Initialize(media::VideoCodecProfile profile) {
   // TODO(vrk): Support multiple decoders.
-  if (decoder_.get())
+  if (decoder_)
     return true;
 
   RenderThreadImpl* render_thread = RenderThreadImpl::current();
@@ -43,8 +43,8 @@
   DCHECK_EQ(channel->state(), GpuChannelHost::kConnected);
 
   // Send IPC message to initialize decoder in GPU process.
-  decoder_.reset(channel->CreateVideoDecoder(
-      command_buffer_route_id_, profile, this));
+  decoder_ =
+      channel->CreateVideoDecoder(command_buffer_route_id_, profile, this);
   return decoder_.get() != NULL;
 }
 
@@ -76,7 +76,7 @@
 }
 
 void PlatformVideoDecoderImpl::Destroy() {
-  if (decoder_.get())
+  if (decoder_)
     decoder_.release()->Destroy();
   client_ = NULL;
   delete this;
diff --git a/content/renderer/media/remote_media_stream_impl.cc b/content/renderer/media/remote_media_stream_impl.cc
new file mode 100644
index 0000000..4242a92
--- /dev/null
+++ b/content/renderer/media/remote_media_stream_impl.cc
@@ -0,0 +1,217 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/media/remote_media_stream_impl.h"
+
+#include <string>
+
+#include "base/logging.h"
+#include "base/utf_string_conversions.h"
+#include "content/renderer/media/media_stream_extra_data.h"
+#include "third_party/WebKit/Source/Platform/chromium/public/WebString.h"
+
+namespace content {
+
+// RemoteMediaStreamTrackObserver is responsible for listening on change
+// notification on a remote webrtc MediaStreamTrack and notify WebKit.
+class RemoteMediaStreamTrackObserver
+    : NON_EXPORTED_BASE(public webrtc::ObserverInterface),
+      NON_EXPORTED_BASE(public base::NonThreadSafe) {
+ public:
+  RemoteMediaStreamTrackObserver(
+      webrtc::MediaStreamTrackInterface* webrtc_track,
+      const WebKit::WebMediaStreamTrack& webkit_track);
+  virtual ~RemoteMediaStreamTrackObserver();
+
+  webrtc::MediaStreamTrackInterface* observered_track() {
+    return webrtc_track_;
+  }
+  const WebKit::WebMediaStreamTrack& webkit_track() { return webkit_track_; }
+
+ private:
+  // webrtc::ObserverInterface implementation.
+  virtual void OnChanged() OVERRIDE;
+
+  webrtc::MediaStreamTrackInterface::TrackState state_;
+  scoped_refptr<webrtc::MediaStreamTrackInterface> webrtc_track_;
+  WebKit::WebMediaStreamTrack webkit_track_;
+
+  DISALLOW_COPY_AND_ASSIGN(RemoteMediaStreamTrackObserver);
+};
+
+}  // namespace content
+
+namespace {
+
+void InitializeWebkitTrack(webrtc::MediaStreamTrackInterface* track,
+                           WebKit::WebMediaStreamTrack* webkit_track,
+                           WebKit::WebMediaStreamSource::Type type) {
+  WebKit::WebMediaStreamSource webkit_source;
+  WebKit::WebString webkit_track_id(UTF8ToUTF16(track->id()));
+
+  webkit_source.initialize(webkit_track_id, type, webkit_track_id);
+  webkit_track->initialize(webkit_track_id, webkit_source);
+}
+
+content::RemoteMediaStreamTrackObserver* FindTrackObserver(
+    webrtc::MediaStreamTrackInterface* track,
+    const ScopedVector<content::RemoteMediaStreamTrackObserver>& observers) {
+  ScopedVector<content::RemoteMediaStreamTrackObserver>::const_iterator it =
+      observers.begin();
+  for (; it != observers.end(); ++it) {
+    if ((*it)->observered_track() == track)
+      return *it;
+  }
+  return NULL;
+}
+
+} // namespace anonymous
+
+namespace content {
+
+RemoteMediaStreamTrackObserver::RemoteMediaStreamTrackObserver(
+    webrtc::MediaStreamTrackInterface* webrtc_track,
+    const WebKit::WebMediaStreamTrack& webkit_track)
+    : state_(webrtc_track->state()),
+      webrtc_track_(webrtc_track),
+      webkit_track_(webkit_track) {
+  webrtc_track->RegisterObserver(this);
+}
+
+RemoteMediaStreamTrackObserver::~RemoteMediaStreamTrackObserver() {
+  webrtc_track_->UnregisterObserver(this);
+}
+
+void RemoteMediaStreamTrackObserver::OnChanged() {
+  DCHECK(CalledOnValidThread());
+
+  webrtc::MediaStreamTrackInterface::TrackState state = webrtc_track_->state();
+  if (state == state_)
+    return;
+
+  state_ = state;
+  switch (state) {
+    case webrtc::MediaStreamTrackInterface::kInitializing:
+      // Ignore the kInitializing state since there is no match in
+      // WebMediaStreamSource::ReadyState.
+      break;
+    case webrtc::MediaStreamTrackInterface::kLive:
+      webkit_track_.source().setReadyState(
+          WebKit::WebMediaStreamSource::ReadyStateLive);
+      break;
+    case webrtc::MediaStreamTrackInterface::kEnded:
+      webkit_track_.source().setReadyState(
+          WebKit::WebMediaStreamSource::ReadyStateEnded);
+      break;
+    default:
+      NOTREACHED();
+      break;
+  }
+}
+
+RemoteMediaStreamImpl::RemoteMediaStreamImpl(
+    webrtc::MediaStreamInterface* webrtc_stream)
+    : webrtc_stream_(webrtc_stream) {
+  webrtc_stream_->RegisterObserver(this);
+
+  webrtc::AudioTrackVector webrtc_audio_tracks =
+      webrtc_stream_->GetAudioTracks();
+  WebKit::WebVector<WebKit::WebMediaStreamTrack> webkit_audio_tracks(
+      webrtc_audio_tracks.size());
+
+  // Initialize WebKit audio tracks.
+  size_t i = 0;
+  for (; i < webrtc_audio_tracks.size(); ++i) {
+    webrtc::AudioTrackInterface* audio_track = webrtc_audio_tracks[i];
+    DCHECK(audio_track);
+    InitializeWebkitTrack(audio_track,  &webkit_audio_tracks[i],
+                          WebKit::WebMediaStreamSource::TypeAudio);
+    audio_track_observers_.push_back(
+        new RemoteMediaStreamTrackObserver(audio_track,
+                                           webkit_audio_tracks[i]));
+  }
+
+  // Initialize WebKit video tracks.
+  webrtc::VideoTrackVector webrtc_video_tracks =
+        webrtc_stream_->GetVideoTracks();
+  WebKit::WebVector<WebKit::WebMediaStreamTrack> webkit_video_tracks(
+       webrtc_video_tracks.size());
+  for (i = 0; i < webrtc_video_tracks.size(); ++i) {
+    webrtc::VideoTrackInterface* video_track = webrtc_video_tracks[i];
+    DCHECK(video_track);
+    InitializeWebkitTrack(video_track,  &webkit_video_tracks[i],
+                          WebKit::WebMediaStreamSource::TypeVideo);
+    video_track_observers_.push_back(
+        new RemoteMediaStreamTrackObserver(video_track,
+                                           webkit_video_tracks[i]));
+  }
+
+  webkit_stream_.initialize(UTF8ToUTF16(webrtc_stream->label()),
+                            webkit_audio_tracks, webkit_video_tracks);
+  webkit_stream_.setExtraData(new MediaStreamExtraData(webrtc_stream, false));
+}
+
+RemoteMediaStreamImpl::~RemoteMediaStreamImpl() {
+  webrtc_stream_->UnregisterObserver(this);
+}
+
+void RemoteMediaStreamImpl::OnChanged() {
+  // Find removed audio tracks.
+  ScopedVector<RemoteMediaStreamTrackObserver>::iterator audio_it =
+      audio_track_observers_.begin();
+  while (audio_it != audio_track_observers_.end()) {
+    std::string track_id = (*audio_it)->observered_track()->id();
+    if (webrtc_stream_->FindAudioTrack(track_id) == NULL) {
+       webkit_stream_.removeTrack((*audio_it)->webkit_track());
+       audio_it = audio_track_observers_.erase(audio_it);
+    } else {
+      ++audio_it;
+    }
+  }
+
+  // Find removed video tracks.
+  ScopedVector<RemoteMediaStreamTrackObserver>::iterator video_it =
+      video_track_observers_.begin();
+  while (video_it != video_track_observers_.end()) {
+    std::string track_id = (*video_it)->observered_track()->id();
+    if (webrtc_stream_->FindVideoTrack(track_id) == NULL) {
+      webkit_stream_.removeTrack((*video_it)->webkit_track());
+      video_it = video_track_observers_.erase(video_it);
+    } else {
+      ++video_it;
+    }
+  }
+
+  // Find added audio tracks.
+  webrtc::AudioTrackVector webrtc_audio_tracks =
+      webrtc_stream_->GetAudioTracks();
+  for (webrtc::AudioTrackVector::iterator it = webrtc_audio_tracks.begin();
+       it != webrtc_audio_tracks.end(); ++it) {
+    if (!FindTrackObserver(*it, audio_track_observers_)) {
+      WebKit::WebMediaStreamTrack new_track;
+      InitializeWebkitTrack(*it, &new_track,
+                            WebKit::WebMediaStreamSource::TypeAudio);
+      audio_track_observers_.push_back(
+          new RemoteMediaStreamTrackObserver(*it, new_track));
+      webkit_stream_.addTrack(new_track);
+    }
+  }
+
+  // Find added video tracks.
+  webrtc::VideoTrackVector webrtc_video_tracks =
+      webrtc_stream_->GetVideoTracks();
+  for (webrtc::VideoTrackVector::iterator it = webrtc_video_tracks.begin();
+       it != webrtc_video_tracks.end(); ++it) {
+    if (!FindTrackObserver(*it, video_track_observers_)) {
+      WebKit::WebMediaStreamTrack new_track;
+      InitializeWebkitTrack(*it, &new_track,
+                            WebKit::WebMediaStreamSource::TypeVideo);
+      video_track_observers_.push_back(
+          new RemoteMediaStreamTrackObserver(*it, new_track));
+      webkit_stream_.addTrack(new_track);
+    }
+  }
+}
+
+}  // namespace content
diff --git a/content/renderer/media/remote_media_stream_impl.h b/content/renderer/media/remote_media_stream_impl.h
new file mode 100644
index 0000000..361cc70
--- /dev/null
+++ b/content/renderer/media/remote_media_stream_impl.h
@@ -0,0 +1,51 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_RENDERER_MEDIA_REMOTE_MEDIA_STREAM_IMPL_H_
+#define CONTENT_RENDERER_MEDIA_REMOTE_MEDIA_STREAM_IMPL_H_
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_vector.h"
+#include "base/threading/non_thread_safe.h"
+#include "content/common/content_export.h"
+#include "third_party/libjingle/source/talk/app/webrtc/mediastreaminterface.h"
+#include "third_party/WebKit/Source/Platform/chromium/public/WebMediaStream.h"
+#include "third_party/WebKit/Source/Platform/chromium/public/WebMediaStreamSource.h"
+#include "third_party/WebKit/Source/Platform/chromium/public/WebMediaStreamTrack.h"
+
+namespace content {
+
+class RemoteMediaStreamTrackObserver;
+
+// RemoteMediaStreamImpl serves as a container and glue between remote webrtc
+// MediaStreams and WebKit MediaStreams. For each remote MediaStream received
+// on a PeerConnection a RemoteMediaStreamImpl instance is created and
+// owned by RtcPeerConnection.
+class CONTENT_EXPORT RemoteMediaStreamImpl
+    : NON_EXPORTED_BASE(public webrtc::ObserverInterface),
+      NON_EXPORTED_BASE(public base::NonThreadSafe) {
+ public:
+  explicit RemoteMediaStreamImpl(
+      webrtc::MediaStreamInterface* webrtc_stream);
+  virtual ~RemoteMediaStreamImpl();
+
+  const WebKit::WebMediaStream& webkit_stream() { return webkit_stream_; }
+
+ private:
+  // webrtc::ObserverInterface implementation.
+  virtual void OnChanged() OVERRIDE;
+
+  scoped_refptr<webrtc::MediaStreamInterface> webrtc_stream_;
+  ScopedVector<RemoteMediaStreamTrackObserver> audio_track_observers_;
+  ScopedVector<RemoteMediaStreamTrackObserver> video_track_observers_;
+  WebKit::WebMediaStream webkit_stream_;
+
+  DISALLOW_COPY_AND_ASSIGN(RemoteMediaStreamImpl);
+};
+
+}  // namespace content
+
+#endif  // CONTENT_RENDERER_MEDIA_REMOTE_MEDIA_STREAM_IMPL_H_
diff --git a/content/renderer/media/render_media_log.cc b/content/renderer/media/render_media_log.cc
index 23ea4ee..8e4de53 100644
--- a/content/renderer/media/render_media_log.cc
+++ b/content/renderer/media/render_media_log.cc
@@ -5,26 +5,39 @@
 #include "content/renderer/media/render_media_log.h"
 
 #include "base/bind.h"
+#include "base/logging.h"
 #include "base/message_loop_proxy.h"
 #include "content/common/view_messages.h"
 #include "content/renderer/render_thread_impl.h"
 
+using base::Time;
+using base::TimeDelta;
+
 namespace content {
 
 RenderMediaLog::RenderMediaLog()
-    : render_loop_(base::MessageLoopProxy::current()) {
+    : render_loop_(base::MessageLoopProxy::current()),
+      last_ipc_send_time_(Time::Now()) {
   DCHECK(RenderThreadImpl::current()) <<
       "RenderMediaLog must be constructed on the render thread";
 }
 
 void RenderMediaLog::AddEvent(scoped_ptr<media::MediaLogEvent> event) {
-  if (RenderThreadImpl::current()) {
-    RenderThreadImpl::current()->Send(
-        new ViewHostMsg_MediaLogEvent(*event));
-  } else {
+  if (!RenderThreadImpl::current()) {
     render_loop_->PostTask(FROM_HERE, base::Bind(
         &RenderMediaLog::AddEvent, this, base::Passed(&event)));
+    return;
   }
+  queued_media_events_.push_back(*event);
+  // Limit the send rate of high frequency events.
+  Time curr_time = Time::Now();
+  if ((curr_time - last_ipc_send_time_) < TimeDelta::FromSeconds(1))
+    return;
+  last_ipc_send_time_ = curr_time;
+  DVLOG(1) << "media log events array size " << queued_media_events_.size();
+  RenderThreadImpl::current()->Send(
+      new ViewHostMsg_MediaLogEvents(queued_media_events_));
+  queued_media_events_.clear();
 }
 
 RenderMediaLog::~RenderMediaLog() {}
diff --git a/content/renderer/media/render_media_log.h b/content/renderer/media/render_media_log.h
index 4c26cdf..70070b3 100644
--- a/content/renderer/media/render_media_log.h
+++ b/content/renderer/media/render_media_log.h
@@ -5,6 +5,8 @@
 #ifndef CONTENT_RENDERER_MEDIA_RENDER_MEDIA_LOG_H_
 #define CONTENT_RENDERER_MEDIA_RENDER_MEDIA_LOG_H_
 
+#include <vector>
+#include "base/time.h"
 #include "media/base/media_log.h"
 
 namespace base {
@@ -14,7 +16,7 @@
 namespace content {
 
 // RenderMediaLog is an implementation of MediaLog that passes all events to the
-// browser process.
+// browser process, throttling as necessary.
 class RenderMediaLog : public media::MediaLog {
  public:
   RenderMediaLog();
@@ -26,6 +28,8 @@
   virtual ~RenderMediaLog();
 
   scoped_refptr<base::MessageLoopProxy> render_loop_;
+  base::Time last_ipc_send_time_;
+  std::vector<media::MediaLogEvent> queued_media_events_;
 
   DISALLOW_COPY_AND_ASSIGN(RenderMediaLog);
 };
diff --git a/content/renderer/media/renderer_audio_output_device.cc b/content/renderer/media/renderer_audio_output_device.cc
deleted file mode 100644
index 678bbec..0000000
--- a/content/renderer/media/renderer_audio_output_device.cc
+++ /dev/null
@@ -1,66 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/renderer/media/renderer_audio_output_device.h"
-
-#include "base/bind.h"
-#include "base/message_loop_proxy.h"
-#include "content/renderer/media/audio_message_filter.h"
-
-namespace content {
-
-RendererAudioOutputDevice::RendererAudioOutputDevice(
-    AudioMessageFilter* message_filter,
-    const scoped_refptr<base::MessageLoopProxy>& io_loop)
-    : AudioOutputDevice(message_filter, io_loop),
-      source_render_view_id_(MSG_ROUTING_NONE),
-      is_after_stream_created_(false) {
-}
-
-RendererAudioOutputDevice::~RendererAudioOutputDevice() {}
-
-void RendererAudioOutputDevice::Start() {
-  AudioOutputDevice::Start();
-  message_loop()->PostTask(
-      FROM_HERE,
-      base::Bind(&RendererAudioOutputDevice::OnStart, this));
-}
-
-void RendererAudioOutputDevice::Stop() {
-  AudioOutputDevice::Stop();
-  message_loop()->PostTask(
-      FROM_HERE,
-      base::Bind(&RendererAudioOutputDevice::OnStop, this));
-}
-
-void RendererAudioOutputDevice::SetSourceRenderView(int render_view_id) {
-  message_loop()->PostTask(
-      FROM_HERE,
-      base::Bind(&RendererAudioOutputDevice::OnSourceChange, this,
-                 render_view_id));
-}
-
-void RendererAudioOutputDevice::OnStart() {
-  DCHECK(message_loop()->BelongsToCurrentThread());
-  is_after_stream_created_ = true;
-  OnSourceChange(source_render_view_id_);
-}
-
-void RendererAudioOutputDevice::OnStop() {
-  DCHECK(message_loop()->BelongsToCurrentThread());
-  is_after_stream_created_ = false;
-}
-
-void RendererAudioOutputDevice::OnSourceChange(int render_view_id) {
-  DCHECK(message_loop()->BelongsToCurrentThread());
-  source_render_view_id_ = render_view_id;
-  if (is_after_stream_created_ && source_render_view_id_ != MSG_ROUTING_NONE) {
-    AudioMessageFilter* const filter =
-        static_cast<AudioMessageFilter*>(audio_output_ipc());
-    if (filter)
-      filter->AssociateStreamWithProducer(stream_id(), source_render_view_id_);
-  }
-}
-
-}  // namespace content
diff --git a/content/renderer/media/renderer_audio_output_device.h b/content/renderer/media/renderer_audio_output_device.h
deleted file mode 100644
index 601cca5..0000000
--- a/content/renderer/media/renderer_audio_output_device.h
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_RENDERER_MEDIA_RENDERER_AUDIO_OUTPUT_DEVICE_H_
-#define CONTENT_RENDERER_MEDIA_RENDERER_AUDIO_OUTPUT_DEVICE_H_
-
-#include "base/memory/ref_counted.h"
-#include "media/audio/audio_output_device.h"
-
-namespace base {
-class MessageLoopProxy;
-}
-
-namespace content {
-
-class AudioDeviceFactory;
-class AudioMessageFilter;
-
-// Subclass of media::AudioOutputDevice to support additional concepts within
-// the content component.  Use AudioDeviceFactory to instantiate this class.
-class RendererAudioOutputDevice
-    : NON_EXPORTED_BASE(public media::AudioOutputDevice) {
- public:
-  // Set the source of the rendered audio data to the RenderView specified by
-  // |render_view_id|.  Callers should keep in mind that the RenderView which
-  // caused the instantiation of RendererAudioOutputDevice might not necessarily
-  // be same as the RenderView which actually renders the audio data.
-  void SetSourceRenderView(int render_view_id);
-
-  virtual void Start() OVERRIDE;
-  virtual void Stop() OVERRIDE;
-
- protected:
-  friend class AudioDeviceFactory;
-
-  // Creates an uninitialized RendererAudioOutputDevice.  Clients must call
-  // Initialize() before using.
-  RendererAudioOutputDevice(
-      AudioMessageFilter* message_filter,
-      const scoped_refptr<base::MessageLoopProxy>& io_loop);
-
- private:
-  virtual ~RendererAudioOutputDevice();
-
-  void OnStart();
-  void OnStop();
-  void OnSourceChange(int render_view_id);
-
-  int source_render_view_id_;
-  bool is_after_stream_created_;
-
-  DISALLOW_IMPLICIT_CONSTRUCTORS(RendererAudioOutputDevice);
-};
-
-}  // namespace content
-
-#endif  // CONTENT_RENDERER_MEDIA_RENDERER_AUDIO_OUTPUT_DEVICE_H_
diff --git a/content/renderer/media/renderer_gpu_video_decoder_factories.cc b/content/renderer/media/renderer_gpu_video_decoder_factories.cc
index cdd5804..8aff387 100644
--- a/content/renderer/media/renderer_gpu_video_decoder_factories.cc
+++ b/content/renderer/media/renderer_gpu_video_decoder_factories.cc
@@ -8,12 +8,12 @@
 #include <GLES2/gl2ext.h>
 
 #include "base/bind.h"
-#include "base/synchronization/waitable_event.h"
 #include "content/common/child_thread.h"
 #include "content/common/gpu/client/gpu_channel_host.h"
 #include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h"
 #include "gpu/command_buffer/client/gles2_implementation.h"
 #include "gpu/ipc/command_buffer_proxy.h"
+#include "third_party/skia/include/core/SkPixelRef.h"
 
 namespace content {
 
@@ -23,13 +23,15 @@
     const scoped_refptr<base::MessageLoopProxy>& message_loop,
     WebGraphicsContext3DCommandBufferImpl* context)
     : message_loop_(message_loop),
-      gpu_channel_host_(gpu_channel_host) {
+      gpu_channel_host_(gpu_channel_host),
+      aborted_waiter_(true, false),
+      compositor_loop_async_waiter_(false, false),
+      render_thread_async_waiter_(false, false) {
   if (message_loop_->BelongsToCurrentThread()) {
-    AsyncGetContext(context, NULL);
+    AsyncGetContext(context);
     return;
   }
   // Threaded compositor requires us to wait for the context to be acquired.
-  base::WaitableEvent waiter(false, false);
   message_loop_->PostTask(FROM_HERE, base::Bind(
       &RendererGpuVideoDecoderFactories::AsyncGetContext,
       // Unretained to avoid ref/deref'ing |*this|, which is not yet stored in a
@@ -40,14 +42,12 @@
       // thread, and only as the result of a PostTask from the render thread
       // which can only happen after this function returns, so our PostTask will
       // run first.
-      context,
-      &waiter));
-  waiter.Wait();
+      context));
+  compositor_loop_async_waiter_.Wait();
 }
 
 void RendererGpuVideoDecoderFactories::AsyncGetContext(
-    WebGraphicsContext3DCommandBufferImpl* context,
-    base::WaitableEvent* waiter) {
+    WebGraphicsContext3DCommandBufferImpl* context) {
   context_ = context->AsWeakPtr();
   if (context_) {
     if (context_->makeContextCurrent()) {
@@ -56,8 +56,7 @@
       context_->insertEventMarkerEXT("GpuVDAContext3D");
     }
   }
-  if (waiter)
-    waiter->Signal();
+  compositor_loop_async_waiter_.Signal();
 }
 
 media::VideoDecodeAccelerator*
@@ -65,29 +64,37 @@
     media::VideoCodecProfile profile,
     media::VideoDecodeAccelerator::Client* client) {
   DCHECK(!message_loop_->BelongsToCurrentThread());
-  media::VideoDecodeAccelerator* vda = NULL;
-  base::WaitableEvent waiter(false, false);
+  // The VDA is returned in the vda_ member variable by the
+  // AsyncCreateVideoDecodeAccelerator() function.
   message_loop_->PostTask(FROM_HERE, base::Bind(
       &RendererGpuVideoDecoderFactories::AsyncCreateVideoDecodeAccelerator,
-      this, profile, client, &vda, &waiter));
-  waiter.Wait();
-  return vda;
+      this, profile, client));
+
+  base::WaitableEvent* objects[] = {&aborted_waiter_,
+                                    &compositor_loop_async_waiter_};
+  if (base::WaitableEvent::WaitMany(objects, arraysize(objects)) == 0) {
+    // If we are aborting and the VDA is created by the
+    // AsyncCreateVideoDecodeAccelerator() function later we need to ensure
+    // that it is destroyed on the same thread.
+    message_loop_->PostTask(FROM_HERE, base::Bind(
+        &RendererGpuVideoDecoderFactories::AsyncDestroyVideoDecodeAccelerator,
+        this));
+    return NULL;
+  }
+  return vda_.release();
 }
 
 void RendererGpuVideoDecoderFactories::AsyncCreateVideoDecodeAccelerator(
       media::VideoCodecProfile profile,
-      media::VideoDecodeAccelerator::Client* client,
-      media::VideoDecodeAccelerator** vda,
-      base::WaitableEvent* waiter) {
+      media::VideoDecodeAccelerator::Client* client) {
   DCHECK(message_loop_->BelongsToCurrentThread());
+
   if (context_ && context_->GetCommandBufferProxy()) {
-    *vda = gpu_channel_host_->CreateVideoDecoder(
+    vda_ = gpu_channel_host_->CreateVideoDecoder(
         context_->GetCommandBufferProxy()->GetRouteID(),
         profile, client);
-  } else {
-    *vda = NULL;
   }
-  waiter->Signal();
+  compositor_loop_async_waiter_.Signal();
 }
 
 bool RendererGpuVideoDecoderFactories::CreateTextures(
@@ -95,31 +102,33 @@
     std::vector<uint32>* texture_ids,
     uint32 texture_target) {
   DCHECK(!message_loop_->BelongsToCurrentThread());
-  bool success = false;
-  base::WaitableEvent waiter(false, false);
   message_loop_->PostTask(FROM_HERE, base::Bind(
       &RendererGpuVideoDecoderFactories::AsyncCreateTextures, this,
-      count, size, texture_ids, texture_target, &success, &waiter));
-  waiter.Wait();
-  return success;
+      count, size, texture_target));
+
+  base::WaitableEvent* objects[] = {&aborted_waiter_,
+                                    &compositor_loop_async_waiter_};
+  if (base::WaitableEvent::WaitMany(objects, arraysize(objects)) == 0)
+    return false;
+  texture_ids->swap(created_textures_);
+  return true;
 }
 
 void RendererGpuVideoDecoderFactories::AsyncCreateTextures(
-    int32 count, const gfx::Size& size, std::vector<uint32>* texture_ids,
-    uint32 texture_target, bool* success, base::WaitableEvent* waiter) {
+    int32 count, const gfx::Size& size, uint32 texture_target) {
   DCHECK(message_loop_->BelongsToCurrentThread());
   DCHECK(texture_target);
+
   if (!context_) {
-    *success = false;
-    waiter->Signal();
+    compositor_loop_async_waiter_.Signal();
     return;
   }
   gpu::gles2::GLES2Implementation* gles2 = context_->GetImplementation();
-  texture_ids->resize(count);
-  gles2->GenTextures(count, &texture_ids->at(0));
+  created_textures_.resize(count);
+  gles2->GenTextures(count, &created_textures_[0]);
   for (int i = 0; i < count; ++i) {
     gles2->ActiveTexture(GL_TEXTURE0);
-    uint32 texture_id = texture_ids->at(i);
+    uint32 texture_id = created_textures_[i];
     gles2->BindTexture(texture_target, texture_id);
     gles2->TexParameteri(texture_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
     gles2->TexParameteri(texture_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
@@ -135,8 +144,7 @@
   // reused, this should not be unacceptably expensive.
   gles2->Flush();
   DCHECK_EQ(gles2->GetError(), static_cast<GLenum>(GL_NO_ERROR));
-  *success = true;
-  waiter->Signal();
+  compositor_loop_async_waiter_.Signal();
 }
 
 void RendererGpuVideoDecoderFactories::DeleteTexture(uint32 texture_id) {
@@ -149,6 +157,7 @@
   DCHECK(message_loop_->BelongsToCurrentThread());
   if (!context_)
     return;
+
   gpu::gles2::GLES2Implementation* gles2 = context_->GetImplementation();
   gles2->DeleteTextures(1, &texture_id);
   DCHECK_EQ(gles2->GetError(), static_cast<GLenum>(GL_NO_ERROR));
@@ -156,24 +165,34 @@
 
 void RendererGpuVideoDecoderFactories::ReadPixels(
     uint32 texture_id, uint32 texture_target, const gfx::Size& size,
-    void* pixels) {
-  base::WaitableEvent waiter(false, false);
+    const SkBitmap& pixels) {
+  // SkBitmaps use the SkPixelRef object to refcount the underlying pixels.
+  // Multiple SkBitmaps can share a SkPixelRef instance. We use this to
+  // ensure that the underlying pixels in the SkBitmap passed in remain valid
+  // until the AsyncReadPixels() call completes.
+  read_pixels_bitmap_.setPixelRef(pixels.pixelRef());
+
   if (!message_loop_->BelongsToCurrentThread()) {
     message_loop_->PostTask(FROM_HERE, base::Bind(
         &RendererGpuVideoDecoderFactories::AsyncReadPixels, this,
-        texture_id, texture_target, size, pixels, &waiter));
-    waiter.Wait();
+        texture_id, texture_target, size));
+    base::WaitableEvent* objects[] = {&aborted_waiter_,
+                                      &compositor_loop_async_waiter_};
+    if (base::WaitableEvent::WaitMany(objects, arraysize(objects)) == 0)
+      return;
   } else {
-    AsyncReadPixels(texture_id, texture_target, size, pixels, &waiter);
+    AsyncReadPixels(texture_id, texture_target, size);
   }
+  read_pixels_bitmap_.setPixelRef(NULL);
 }
 
 void RendererGpuVideoDecoderFactories::AsyncReadPixels(
-    uint32 texture_id, uint32 texture_target, const gfx::Size& size,
-    void* pixels, base::WaitableEvent* waiter) {
+    uint32 texture_id, uint32 texture_target, const gfx::Size& size) {
   DCHECK(message_loop_->BelongsToCurrentThread());
-  if (!context_)
+  if (!context_) {
+    compositor_loop_async_waiter_.Signal();
     return;
+  }
 
   gpu::gles2::GLES2Implementation* gles2 = context_->GetImplementation();
 
@@ -194,30 +213,35 @@
                               texture_target, tmp_texture, 0);
   gles2->PixelStorei(GL_PACK_ALIGNMENT, 4);
   gles2->ReadPixels(0, 0, size.width(), size.height(), GL_BGRA_EXT,
-                    GL_UNSIGNED_BYTE, pixels);
+      GL_UNSIGNED_BYTE, read_pixels_bitmap_.pixelRef()->pixels());
   gles2->DeleteFramebuffers(1, &fb);
   gles2->DeleteTextures(1, &tmp_texture);
   DCHECK_EQ(gles2->GetError(), static_cast<GLenum>(GL_NO_ERROR));
-  waiter->Signal();
+  compositor_loop_async_waiter_.Signal();
 }
 
 base::SharedMemory* RendererGpuVideoDecoderFactories::CreateSharedMemory(
     size_t size) {
-  DCHECK_NE(MessageLoop::current(), ChildThread::current()->message_loop());
-  base::SharedMemory* shm = NULL;
-  base::WaitableEvent waiter(false, false);
+  DCHECK_NE(base::MessageLoop::current(),
+            ChildThread::current()->message_loop());
   ChildThread::current()->message_loop()->PostTask(FROM_HERE, base::Bind(
       &RendererGpuVideoDecoderFactories::AsyncCreateSharedMemory, this,
-      size, &shm, &waiter));
-  waiter.Wait();
-  return shm;
+      size));
+
+  base::WaitableEvent* objects[] = {&aborted_waiter_,
+                                    &render_thread_async_waiter_};
+  if (base::WaitableEvent::WaitMany(objects, arraysize(objects)) == 0)
+    return NULL;
+  return shared_memory_segment_.release();
 }
 
-void RendererGpuVideoDecoderFactories::AsyncCreateSharedMemory(
-    size_t size, base::SharedMemory** shm, base::WaitableEvent* waiter) {
-  DCHECK_EQ(MessageLoop::current(), ChildThread::current()->message_loop());
-  *shm = ChildThread::current()->AllocateSharedMemory(size);
-  waiter->Signal();
+void RendererGpuVideoDecoderFactories::AsyncCreateSharedMemory(size_t size) {
+  DCHECK_EQ(base::MessageLoop::current(),
+            ChildThread::current()->message_loop());
+
+  shared_memory_segment_.reset(
+      ChildThread::current()->AllocateSharedMemory(size));
+  render_thread_async_waiter_.Signal();
 }
 
 scoped_refptr<base::MessageLoopProxy>
@@ -225,4 +249,18 @@
   return message_loop_;
 }
 
+void RendererGpuVideoDecoderFactories::Abort() {
+  aborted_waiter_.Signal();
+}
+
+bool RendererGpuVideoDecoderFactories::IsAborted() {
+  return aborted_waiter_.IsSignaled();
+}
+
+void RendererGpuVideoDecoderFactories::AsyncDestroyVideoDecodeAccelerator() {
+  // OK to release because Destroy() will delete the VDA instance.
+  if (vda_)
+    vda_.release()->Destroy();
+}
+
 }  // namespace content
diff --git a/content/renderer/media/renderer_gpu_video_decoder_factories.h b/content/renderer/media/renderer_gpu_video_decoder_factories.h
index 5512562..e05dd9a 100644
--- a/content/renderer/media/renderer_gpu_video_decoder_factories.h
+++ b/content/renderer/media/renderer_gpu_video_decoder_factories.h
@@ -5,11 +5,15 @@
 #ifndef CONTENT_RENDERER_MEDIA_RENDERER_GPU_VIDEO_DECODER_FACTORIES_H_
 #define CONTENT_RENDERER_MEDIA_RENDERER_GPU_VIDEO_DECODER_FACTORIES_H_
 
+#include <vector>
+
 #include "base/basictypes.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
+#include "base/synchronization/waitable_event.h"
 #include "content/common/content_export.h"
 #include "media/filters/gpu_video_decoder.h"
+#include "third_party/skia/include/core/SkBitmap.h"
 #include "ui/gfx/size.h"
 
 namespace base {
@@ -48,10 +52,14 @@
                               std::vector<uint32>* texture_ids,
                               uint32 texture_target) OVERRIDE;
   virtual void DeleteTexture(uint32 texture_id) OVERRIDE;
-  virtual void ReadPixels(uint32 texture_id, uint32 texture_target,
-                          const gfx::Size& size, void* pixels) OVERRIDE;
+  virtual void ReadPixels(uint32 texture_id,
+                          uint32 texture_target,
+                          const gfx::Size& size,
+                          const SkBitmap& pixels) OVERRIDE;
   virtual base::SharedMemory* CreateSharedMemory(size_t size) OVERRIDE;
   virtual scoped_refptr<base::MessageLoopProxy> GetMessageLoop() OVERRIDE;
+  virtual void Abort() OVERRIDE;
+  virtual bool IsAborted() OVERRIDE;
 
  protected:
   friend class base::RefCountedThreadSafe<RendererGpuVideoDecoderFactories>;
@@ -60,32 +68,55 @@
  private:
   // Helper for the constructor to acquire the ContentGLContext on the
   // compositor thread (when it is enabled).
-  void AsyncGetContext(WebGraphicsContext3DCommandBufferImpl* context,
-                       base::WaitableEvent* waiter);
+  void AsyncGetContext(WebGraphicsContext3DCommandBufferImpl* context);
 
   // Async versions of the public methods.  They use output parameters instead
   // of return values and each takes a WaitableEvent* param to signal completion
   // (except for DeleteTexture, which is fire-and-forget).
   // AsyncCreateSharedMemory runs on the renderer thread and the rest run on
   // |message_loop_|.
+  // The AsyncCreateVideoDecodeAccelerator returns its output in the vda_
+  // member.
   void AsyncCreateVideoDecodeAccelerator(
       media::VideoCodecProfile profile,
-      media::VideoDecodeAccelerator::Client* client,
-      media::VideoDecodeAccelerator** vda,
-      base::WaitableEvent* waiter);
-  void AsyncCreateTextures(
-      int32 count, const gfx::Size& size, std::vector<uint32>* texture_ids,
-      uint32 texture_target, bool* success, base::WaitableEvent* waiter);
+      media::VideoDecodeAccelerator::Client* client);
+  void AsyncCreateTextures(int32 count, const gfx::Size& size,
+                           uint32 texture_target);
   void AsyncDeleteTexture(uint32 texture_id);
   void AsyncReadPixels(uint32 texture_id, uint32 texture_target,
-                       const gfx::Size& size,
-                       void* pixels, base::WaitableEvent* waiter);
-  void AsyncCreateSharedMemory(
-      size_t size, base::SharedMemory** shm, base::WaitableEvent* waiter);
+                       const gfx::Size& size);
+  void AsyncCreateSharedMemory(size_t size);
+  void AsyncDestroyVideoDecodeAccelerator();
 
   scoped_refptr<base::MessageLoopProxy> message_loop_;
   scoped_refptr<GpuChannelHost> gpu_channel_host_;
   base::WeakPtr<WebGraphicsContext3DCommandBufferImpl> context_;
+
+  // This event is signaled if we have been asked to Abort().
+  base::WaitableEvent aborted_waiter_;
+
+  // This event is signaled by asynchronous tasks posted to the compositor
+  // message loop to indicate their completion.
+  // e.g. AsyncCreateVideoDecodeAccelerator()/AsyncCreateTextures() etc.
+  base::WaitableEvent compositor_loop_async_waiter_;
+
+  // This event is signaled by asynchronous tasks posted to the renderer thread
+  // message loop to indicate their completion. e.g. AsyncCreateSharedMemory.
+  base::WaitableEvent render_thread_async_waiter_;
+
+  // The vda returned by the CreateVideoAcclelerator function.
+  scoped_ptr<media::VideoDecodeAccelerator> vda_;
+
+  // Shared memory segment which is returned by the CreateSharedMemory()
+  // function.
+  scoped_ptr<base::SharedMemory> shared_memory_segment_;
+
+  // Bitmap returned by ReadPixels().
+  SkBitmap read_pixels_bitmap_;
+
+  // Textures returned by the CreateTexture() function.
+  std::vector<uint32> created_textures_;
+
   DISALLOW_IMPLICIT_CONSTRUCTORS(RendererGpuVideoDecoderFactories);
 };
 
diff --git a/content/renderer/media/renderer_webaudiodevice_impl.cc b/content/renderer/media/renderer_webaudiodevice_impl.cc
index ca32103..43a4a61 100644
--- a/content/renderer/media/renderer_webaudiodevice_impl.cc
+++ b/content/renderer/media/renderer_webaudiodevice_impl.cc
@@ -7,8 +7,8 @@
 #include "base/command_line.h"
 #include "base/logging.h"
 #include "content/renderer/media/audio_device_factory.h"
-#include "content/renderer/media/renderer_audio_output_device.h"
 #include "content/renderer/render_view_impl.h"
+#include "media/audio/audio_output_device.h"
 #include "media/base/media_switches.h"
 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
 #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
@@ -38,9 +38,6 @@
   if (output_device_)
     return;  // Already started.
 
-  output_device_ = AudioDeviceFactory::NewOutputDevice();
-  output_device_->Initialize(params_, this);
-
   // Assumption: This method is being invoked within a V8 call stack.  CHECKs
   // will fail in the call to frameForCurrentContext() otherwise.
   //
@@ -52,10 +49,9 @@
   WebView* const web_view = web_frame ? web_frame->view() : NULL;
   RenderViewImpl* const render_view =
       web_view ? RenderViewImpl::FromWebView(web_view) : NULL;
-  if (render_view) {
-    output_device_->SetSourceRenderView(render_view->routing_id());
-  }
-
+  output_device_ = AudioDeviceFactory::NewOutputDevice(
+      render_view ? render_view->routing_id() : MSG_ROUTING_NONE);
+  output_device_->Initialize(params_, this);
   output_device_->Start();
   // Note: Default behavior is to auto-play on start.
 }
diff --git a/content/renderer/media/renderer_webaudiodevice_impl.h b/content/renderer/media/renderer_webaudiodevice_impl.h
index ca19d07..09c35d8 100644
--- a/content/renderer/media/renderer_webaudiodevice_impl.h
+++ b/content/renderer/media/renderer_webaudiodevice_impl.h
@@ -12,9 +12,11 @@
 #include "third_party/WebKit/Source/Platform/chromium/public/WebAudioDevice.h"
 #include "third_party/WebKit/Source/Platform/chromium/public/WebVector.h"
 
-namespace content {
+namespace media {
+class AudioOutputDevice;
+}
 
-class RendererAudioOutputDevice;
+namespace content {
 
 class RendererWebAudioDeviceImpl
     : public WebKit::WebAudioDevice,
@@ -50,7 +52,7 @@
   base::ThreadChecker thread_checker_;
 
   // When non-NULL, we are started.  When NULL, we are stopped.
-  scoped_refptr<RendererAudioOutputDevice> output_device_;
+  scoped_refptr<media::AudioOutputDevice> output_device_;
 
   DISALLOW_COPY_AND_ASSIGN(RendererWebAudioDeviceImpl);
 };
diff --git a/content/renderer/media/rtc_data_channel_handler.cc b/content/renderer/media/rtc_data_channel_handler.cc
index 4b0006a..6fcaa83 100644
--- a/content/renderer/media/rtc_data_channel_handler.cc
+++ b/content/renderer/media/rtc_data_channel_handler.cc
@@ -43,17 +43,15 @@
 
 bool RtcDataChannelHandler::sendStringData(const WebKit::WebString& data) {
   std::string utf8_buffer = UTF16ToUTF8(data);
-  webrtc::DataBuffer buffer;
-  buffer.binary = false;
-  buffer.data.SetData(utf8_buffer.c_str(), utf8_buffer.length());
-  return channel_->Send(buffer);
+  talk_base::Buffer buffer(utf8_buffer.c_str(), utf8_buffer.length());
+  webrtc::DataBuffer data_buffer(buffer, false);
+  return channel_->Send(data_buffer);
 }
 
 bool RtcDataChannelHandler::sendRawData(const char* data, size_t length) {
-  webrtc::DataBuffer buffer;
-  buffer.data.SetData(data, length);
-  buffer.binary = true;
-  return channel_->Send(buffer);
+  talk_base::Buffer buffer(data, length);
+  webrtc::DataBuffer data_buffer(buffer, true);
+  return channel_->Send(data_buffer);
 }
 
 void RtcDataChannelHandler::close() {
diff --git a/content/renderer/media/rtc_media_constraints.h b/content/renderer/media/rtc_media_constraints.h
index 5b654a8..24a92ee 100644
--- a/content/renderer/media/rtc_media_constraints.h
+++ b/content/renderer/media/rtc_media_constraints.h
@@ -6,7 +6,7 @@
 #define CONTENT_RENDERER_MEDIA_RTC_MEDIA_CONSTRAINTS_H_
 
 #include "base/compiler_specific.h"
-#include "third_party/libjingle/source/talk/app/webrtc/mediastreaminterface.h"
+#include "third_party/libjingle/source/talk/app/webrtc/mediaconstraintsinterface.h"
 
 namespace WebKit {
 class WebMediaConstraints;
diff --git a/content/renderer/media/rtc_peer_connection_handler.cc b/content/renderer/media/rtc_peer_connection_handler.cc
index 01838b4..30707ca 100644
--- a/content/renderer/media/rtc_peer_connection_handler.cc
+++ b/content/renderer/media/rtc_peer_connection_handler.cc
@@ -10,9 +10,11 @@
 
 #include "base/logging.h"
 #include "base/memory/scoped_ptr.h"
+#include "base/stl_util.h"
 #include "base/utf_string_conversions.h"
 #include "content/renderer/media/media_stream_dependency_factory.h"
 #include "content/renderer/media/peer_connection_tracker.h"
+#include "content/renderer/media/remote_media_stream_impl.h"
 #include "content/renderer/media/rtc_data_channel_handler.h"
 #include "content/renderer/media/rtc_dtmf_sender_handler.h"
 #include "content/renderer/media/rtc_media_constraints.h"
@@ -129,6 +131,7 @@
     webrtc::PeerConnectionInterface::IceServer server;
     const WebKit::WebRTCICEServer& webkit_server =
         server_configuration.server(i);
+    server.username = UTF16ToUTF8(webkit_server.username());
     server.password = UTF16ToUTF8(webkit_server.credential());
     server.uri = webkit_server.uri().spec();
     servers->push_back(server);
@@ -231,27 +234,21 @@
       const std::vector<webrtc::StatsReport>& reports) OVERRIDE {
     for (std::vector<webrtc::StatsReport>::const_iterator it = reports.begin();
          it != reports.end(); ++it) {
-      // TODO(hta): Remove local/remote from libjingle API.
-      if (it->local.values.size() > 0) {
-        AddElement(it->id, it->type, it->local);
-      }
-      if (it->remote.values.size() > 0) {
-        AddElement(it->id, it->type, it->remote);
+      if (it->values.size() > 0) {
+        AddReport(*it);
       }
     }
     request_->requestSucceeded(response_);
   }
 
  private:
-  void AddElement(const std::string& id,
-                  const std::string& type,
-                  const webrtc::StatsElement& element) {
-    int idx = response_->addReport(WebKit::WebString::fromUTF8(id),
-                                   WebKit::WebString::fromUTF8(type),
-                                   element.timestamp);
-    for (webrtc::StatsElement::Values::const_iterator value_it =
-             element.values.begin();
-         value_it != element.values.end(); ++value_it) {
+  void AddReport(const webrtc::StatsReport& report) {
+    int idx = response_->addReport(WebKit::WebString::fromUTF8(report.id),
+                                   WebKit::WebString::fromUTF8(report.type),
+                                   report.timestamp);
+    for (webrtc::StatsReport::Values::const_iterator value_it =
+         report.values.begin();
+         value_it != report.values.end(); ++value_it) {
       AddStatistic(idx, value_it->name, value_it->value);
     }
   }
@@ -329,6 +326,7 @@
 RTCPeerConnectionHandler::~RTCPeerConnectionHandler() {
   if (peer_connection_tracker_)
     peer_connection_tracker_->UnregisterPeerConnection(this);
+  STLDeleteValues(&remote_streams_);
 }
 
 void RTCPeerConnectionHandler::associateWithFrame(WebKit::WebFrame* frame) {
@@ -424,7 +422,7 @@
   }
   if (peer_connection_tracker_)
     peer_connection_tracker_->TrackSetSessionDescription(
-        this, native_desc, PeerConnectionTracker::SOURCE_LOCAL);
+        this, description, PeerConnectionTracker::SOURCE_LOCAL);
 
   scoped_refptr<SetSessionDescriptionRequest> set_request(
       new talk_base::RefCountedObject<SetSessionDescriptionRequest>(
@@ -449,7 +447,7 @@
   }
   if (peer_connection_tracker_)
     peer_connection_tracker_->TrackSetSessionDescription(
-        this, native_desc, PeerConnectionTracker::SOURCE_REMOTE);
+        this, description, PeerConnectionTracker::SOURCE_REMOTE);
 
   scoped_refptr<SetSessionDescriptionRequest> set_request(
       new talk_base::RefCountedObject<SetSessionDescriptionRequest>(
@@ -496,7 +494,7 @@
           UTF16ToUTF8(candidate.sdpMid()),
           candidate.sdpMLineIndex(),
           UTF16ToUTF8(candidate.candidate())));
-  if (!native_candidate.get()) {
+  if (!native_candidate) {
     LOG(ERROR) << "Could not create native ICE candidate.";
     return false;
   }
@@ -666,17 +664,19 @@
     webrtc::MediaStreamInterface* stream_interface) {
   DCHECK(stream_interface);
   DCHECK(remote_streams_.find(stream_interface) == remote_streams_.end());
-  WebKit::WebMediaStream stream =
-      CreateRemoteWebKitMediaStream(stream_interface);
+
+  RemoteMediaStreamImpl* remote_stream =
+      new RemoteMediaStreamImpl(stream_interface);
+  remote_streams_.insert(
+      std::pair<webrtc::MediaStreamInterface*, RemoteMediaStreamImpl*> (
+          stream_interface, remote_stream));
 
   if (peer_connection_tracker_)
     peer_connection_tracker_->TrackAddStream(
-        this, stream, PeerConnectionTracker::SOURCE_REMOTE);
+        this, remote_stream->webkit_stream(),
+        PeerConnectionTracker::SOURCE_REMOTE);
 
-  remote_streams_.insert(
-      std::pair<webrtc::MediaStreamInterface*,
-                WebKit::WebMediaStream>(stream_interface, stream));
-  client_->didAddRemoteStream(stream);
+  client_->didAddRemoteStream(remote_stream->webkit_stream());
 }
 
 void RTCPeerConnectionHandler::OnRemoveStream(
@@ -687,15 +687,17 @@
     NOTREACHED() << "Stream not found";
     return;
   }
-  WebKit::WebMediaStream stream = it->second;
-  DCHECK(!stream.isNull());
+
+  scoped_ptr<RemoteMediaStreamImpl> remote_stream(it->second);
+  const WebKit::WebMediaStream& webkit_stream = remote_stream->webkit_stream();
+  DCHECK(!webkit_stream.isNull());
   remote_streams_.erase(it);
 
   if (peer_connection_tracker_)
     peer_connection_tracker_->TrackRemoveStream(
-        this, stream, PeerConnectionTracker::SOURCE_REMOTE);
+        this, webkit_stream, PeerConnectionTracker::SOURCE_REMOTE);
 
-  client_->didRemoveRemoteStream(stream);
+  client_->didRemoveRemoteStream(webkit_stream);
 }
 
 void RTCPeerConnectionHandler::OnIceCandidate(
diff --git a/content/renderer/media/rtc_peer_connection_handler_unittest.cc b/content/renderer/media/rtc_peer_connection_handler_unittest.cc
index e3e66df..a303893 100644
--- a/content/renderer/media/rtc_peer_connection_handler_unittest.cc
+++ b/content/renderer/media/rtc_peer_connection_handler_unittest.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include <string>
+#include <vector>
 
 #include "base/memory/scoped_ptr.h"
 #include "base/utf_string_conversions.h"
@@ -38,6 +39,7 @@
 using WebKit::WebRTCPeerConnectionHandlerClient;
 using testing::NiceMock;
 using testing::_;
+using testing::Ref;
 
 namespace content {
 
@@ -125,7 +127,7 @@
  public:
   MOCK_METHOD1(UnregisterPeerConnection,
                void(RTCPeerConnectionHandler* pc_handler));
-  // TODO (jiayl): add coverage for the following methods
+  // TODO(jiayl): add coverage for the following methods
   MOCK_METHOD2(TrackCreateOffer,
                void(RTCPeerConnectionHandler* pc_handler,
                     const RTCMediaConstraints& constraints));
@@ -134,7 +136,7 @@
                     const RTCMediaConstraints& constraints));
   MOCK_METHOD3(TrackSetSessionDescription,
                void(RTCPeerConnectionHandler* pc_handler,
-                    const webrtc::SessionDescriptionInterface* desc,
+                    const WebKit::WebRTCSessionDescription& desc,
                     Source source));
   MOCK_METHOD3(
       TrackUpdateIce,
@@ -175,7 +177,7 @@
   MOCK_METHOD1(TrackOnRenegotiationNeeded,
                void(RTCPeerConnectionHandler* pc_handler));
   MOCK_METHOD2(TrackCreateDTMFSender,
-               void (RTCPeerConnectionHandler* pc_handler,
+               void(RTCPeerConnectionHandler* pc_handler,
                      const WebKit::WebMediaStreamTrack& track));
 };
 
@@ -246,9 +248,10 @@
     WebKit::WebVector<WebKit::WebMediaStreamTrack> video_tracks;
     local_stream.audioSources(video_tracks);
     const std::string video_track_id = UTF16ToUTF8(video_tracks[0].id());
+    webrtc::VideoSourceInterface* source = NULL;
     scoped_refptr<webrtc::VideoTrackInterface> video_track(
         mock_dependency_factory_->CreateLocalVideoTrack(
-            video_track_id, 0));
+            video_track_id, source));
     native_stream->AddTrack(video_track);
 
     local_stream.setExtraData(new MediaStreamExtraData(native_stream, true));
@@ -264,9 +267,10 @@
     scoped_refptr<webrtc::MediaStreamInterface> stream(
         mock_dependency_factory_->CreateLocalMediaStream(stream_label));
     if (!video_track_label.empty()) {
+      webrtc::VideoSourceInterface* source = NULL;
       scoped_refptr<webrtc::VideoTrackInterface> video_track(
           mock_dependency_factory_->CreateLocalVideoTrack(
-              video_track_label, 0));
+              video_track_label, source));
       stream->AddTrack(video_track);
     }
     if (!audio_track_label.empty()) {
@@ -320,17 +324,17 @@
 }
 
 TEST_F(RTCPeerConnectionHandlerTest, setLocalDescription) {
+  WebKit::WebRTCVoidRequest request;
+  WebKit::WebRTCSessionDescription description;
+  description.initialize(kDummySdpType, kDummySdp);
   // PeerConnectionTracker::TrackSetSessionDescription is expected to be called
   // before |mock_peer_connection| is called.
   testing::InSequence sequence;
   EXPECT_CALL(*mock_tracker_.get(),
-              TrackSetSessionDescription(pc_handler_.get(), testing::NotNull(),
+              TrackSetSessionDescription(pc_handler_.get(), Ref(description),
                                          PeerConnectionTracker::SOURCE_LOCAL));
   EXPECT_CALL(*mock_peer_connection_, SetLocalDescription(_, _));
 
-  WebKit::WebRTCVoidRequest request;
-  WebKit::WebRTCSessionDescription description;
-  description.initialize(kDummySdpType, kDummySdp);
   pc_handler_->setLocalDescription(request, description);
   EXPECT_EQ(description.type(), pc_handler_->localDescription().type());
   EXPECT_EQ(description.sdp(), pc_handler_->localDescription().sdp());
@@ -343,17 +347,18 @@
 }
 
 TEST_F(RTCPeerConnectionHandlerTest, setRemoteDescription) {
+  WebKit::WebRTCVoidRequest request;
+  WebKit::WebRTCSessionDescription description;
+  description.initialize(kDummySdpType, kDummySdp);
+
   // PeerConnectionTracker::TrackSetSessionDescription is expected to be called
   // before |mock_peer_connection| is called.
   testing::InSequence sequence;
   EXPECT_CALL(*mock_tracker_.get(),
-              TrackSetSessionDescription(pc_handler_.get(), testing::NotNull(),
+              TrackSetSessionDescription(pc_handler_.get(), Ref(description),
                                          PeerConnectionTracker::SOURCE_REMOTE));
   EXPECT_CALL(*mock_peer_connection_, SetRemoteDescription(_, _));
 
-  WebKit::WebRTCVoidRequest request;
-  WebKit::WebRTCSessionDescription description;
-  description.initialize(kDummySdpType, kDummySdp);
   pc_handler_->setRemoteDescription(request, description);
   EXPECT_EQ(description.type(), pc_handler_->remoteDescription().type());
   EXPECT_EQ(description.sdp(), pc_handler_->remoteDescription().sdp());
@@ -654,6 +659,100 @@
   pc_handler_->OnRemoveStream(remote_stream);
 }
 
+// This test that WebKit is notified about remote track state changes.
+TEST_F(RTCPeerConnectionHandlerTest, RemoteTrackState) {
+  std::string remote_stream_label("remote_stream");
+  scoped_refptr<webrtc::MediaStreamInterface> remote_stream(
+      AddRemoteMockMediaStream(remote_stream_label, "video", "audio"));
+
+  testing::InSequence sequence;
+  EXPECT_CALL(*mock_client_.get(), didAddRemoteStream(
+      testing::Property(&WebKit::WebMediaStream::label,
+                        UTF8ToUTF16(remote_stream_label))));
+  pc_handler_->OnAddStream(remote_stream);
+  const WebKit::WebMediaStream& webkit_stream = mock_client_->remote_stream();
+
+  WebKit::WebVector<WebKit::WebMediaStreamTrack> audio_tracks;
+  webkit_stream.audioTracks(audio_tracks);
+  EXPECT_EQ(WebKit::WebMediaStreamSource::ReadyStateLive,
+            audio_tracks[0].source().readyState());
+
+  WebKit::WebVector<WebKit::WebMediaStreamTrack> video_tracks;
+    webkit_stream.videoTracks(video_tracks);
+  EXPECT_EQ(WebKit::WebMediaStreamSource::ReadyStateLive,
+            video_tracks[0].source().readyState());
+
+  remote_stream->GetAudioTracks()[0]->set_state(
+      webrtc::MediaStreamTrackInterface::kEnded);
+  EXPECT_EQ(WebKit::WebMediaStreamSource::ReadyStateEnded,
+            audio_tracks[0].source().readyState());
+
+  remote_stream->GetVideoTracks()[0]->set_state(
+      webrtc::MediaStreamTrackInterface::kEnded);
+  EXPECT_EQ(WebKit::WebMediaStreamSource::ReadyStateEnded,
+            video_tracks[0].source().readyState());
+}
+
+TEST_F(RTCPeerConnectionHandlerTest, RemoveAndAddAudioTrackFromRemoteStream) {
+  std::string remote_stream_label("remote_stream");
+  scoped_refptr<webrtc::MediaStreamInterface> remote_stream(
+      AddRemoteMockMediaStream(remote_stream_label, "video", "audio"));
+
+  EXPECT_CALL(*mock_client_.get(), didAddRemoteStream(
+      testing::Property(&WebKit::WebMediaStream::label,
+                        UTF8ToUTF16(remote_stream_label))));
+  pc_handler_->OnAddStream(remote_stream);
+  const WebKit::WebMediaStream& webkit_stream = mock_client_->remote_stream();
+
+  WebKit::WebVector<WebKit::WebMediaStreamTrack> audio_tracks;
+  webkit_stream.audioTracks(audio_tracks);
+  EXPECT_EQ(1u, audio_tracks.size());
+
+  // Remove the Webrtc audio track from the Webrtc MediaStream.
+  scoped_refptr<webrtc::AudioTrackInterface> webrtc_track =
+      remote_stream->GetAudioTracks()[0].get();
+  remote_stream->RemoveTrack(webrtc_track);
+  WebKit::WebVector<WebKit::WebMediaStreamTrack> modified_audio_tracks1;
+  webkit_stream.audioTracks(modified_audio_tracks1);
+  EXPECT_EQ(0u, modified_audio_tracks1.size());
+
+  // Add the WebRtc audio track again.
+  remote_stream->AddTrack(webrtc_track);
+  WebKit::WebVector<WebKit::WebMediaStreamTrack> modified_audio_tracks2;
+  webkit_stream.audioTracks(modified_audio_tracks2);
+  EXPECT_EQ(1u, modified_audio_tracks2.size());
+}
+
+TEST_F(RTCPeerConnectionHandlerTest, RemoveAndAddVideoTrackFromRemoteStream) {
+  std::string remote_stream_label("remote_stream");
+  scoped_refptr<webrtc::MediaStreamInterface> remote_stream(
+      AddRemoteMockMediaStream(remote_stream_label, "video", "video"));
+
+  EXPECT_CALL(*mock_client_.get(), didAddRemoteStream(
+      testing::Property(&WebKit::WebMediaStream::label,
+                        UTF8ToUTF16(remote_stream_label))));
+  pc_handler_->OnAddStream(remote_stream);
+  const WebKit::WebMediaStream& webkit_stream = mock_client_->remote_stream();
+
+  WebKit::WebVector<WebKit::WebMediaStreamTrack> video_tracks;
+  webkit_stream.videoTracks(video_tracks);
+  EXPECT_EQ(1u, video_tracks.size());
+
+  // Remove the Webrtc video track from the Webrtc MediaStream.
+  scoped_refptr<webrtc::VideoTrackInterface> webrtc_track =
+      remote_stream->GetVideoTracks()[0].get();
+  remote_stream->RemoveTrack(webrtc_track);
+  WebKit::WebVector<WebKit::WebMediaStreamTrack> modified_video_tracks1;
+  webkit_stream.videoTracks(modified_video_tracks1);
+  EXPECT_EQ(0u, modified_video_tracks1.size());
+
+  // Add the WebRtc video track again.
+  remote_stream->AddTrack(webrtc_track);
+  WebKit::WebVector<WebKit::WebMediaStreamTrack> modified_video_tracks2;
+  webkit_stream.videoTracks(modified_video_tracks2);
+  EXPECT_EQ(1u, modified_video_tracks2.size());
+}
+
 TEST_F(RTCPeerConnectionHandlerTest, OnIceCandidate) {
   testing::InSequence sequence;
   EXPECT_CALL(*mock_tracker_.get(),
diff --git a/content/renderer/media/rtc_video_capture_delegate.cc b/content/renderer/media/rtc_video_capture_delegate.cc
index 33a1917..975cfde 100644
--- a/content/renderer/media/rtc_video_capture_delegate.cc
+++ b/content/renderer/media/rtc_video_capture_delegate.cc
@@ -14,7 +14,8 @@
     : session_id_(id),
       vc_manager_(vc_manager),
       capture_engine_(NULL),
-      got_first_frame_(false) {
+      got_first_frame_(false),
+      error_occured_(false) {
   DVLOG(3) << " RtcVideoCaptureDelegate::ctor";
   capture_engine_ = vc_manager_->AddDevice(session_id_, this);
 }
@@ -32,6 +33,8 @@
   message_loop_proxy_ = base::MessageLoopProxy::current();
   captured_callback_ = captured_callback;
   state_callback_ = state_callback;
+  got_first_frame_ = false;
+  error_occured_ = false;
 
   // Increase the reference count to ensure we are not deleted until
   // The we are unregistered in RtcVideoCaptureDelegate::OnRemoved.
@@ -59,14 +62,20 @@
 
 void RtcVideoCaptureDelegate::OnError(media::VideoCapture* capture,
                                       int error_code) {
+  DVLOG(3) << " RtcVideoCaptureDelegate::OnError";
   message_loop_proxy_->PostTask(
       FROM_HERE,
       base::Bind(&RtcVideoCaptureDelegate::OnErrorOnCaptureThread,
-                 this, capture, error_code));
+                 this, capture));
 }
 
 void RtcVideoCaptureDelegate::OnRemoved(media::VideoCapture* capture) {
   DVLOG(3) << " RtcVideoCaptureDelegate::OnRemoved";
+  message_loop_proxy_->PostTask(
+      FROM_HERE,
+      base::Bind(&RtcVideoCaptureDelegate::OnRemovedOnCaptureThread,
+                 this, capture));
+
   // Balance the AddRef in StartCapture.
   // This means we are no longer registered as an event handler and can safely
   // be deleted.
@@ -104,9 +113,17 @@
 }
 
 void RtcVideoCaptureDelegate::OnErrorOnCaptureThread(
-    media::VideoCapture* capture, int error_code) {
+    media::VideoCapture* capture) {
+  error_occured_ = true;
   if (!state_callback_.is_null())
-    state_callback_.Run(got_first_frame_ ? CAPTURE_STOPPED : CAPTURE_FAILED);
+    state_callback_.Run(CAPTURE_FAILED);
+}
+
+
+void RtcVideoCaptureDelegate::OnRemovedOnCaptureThread(
+    media::VideoCapture* capture) {
+  if (!error_occured_ && !state_callback_.is_null())
+    state_callback_.Run(CAPTURE_STOPPED);
 }
 
 }  // namespace content
diff --git a/content/renderer/media/rtc_video_capture_delegate.h b/content/renderer/media/rtc_video_capture_delegate.h
index 6482250..d8c3198 100644
--- a/content/renderer/media/rtc_video_capture_delegate.h
+++ b/content/renderer/media/rtc_video_capture_delegate.h
@@ -63,7 +63,8 @@
   void OnBufferReadyOnCaptureThread(
       media::VideoCapture* capture,
       scoped_refptr<media::VideoCapture::VideoFrameBuffer> buf);
-  void OnErrorOnCaptureThread(media::VideoCapture* capture, int error_code);
+  void OnErrorOnCaptureThread(media::VideoCapture* capture);
+  void OnRemovedOnCaptureThread(media::VideoCapture* capture);
 
   // The id identifies which video capture device is used for this video
   // capture session.
@@ -74,6 +75,7 @@
 
   // Accessed on the thread where StartCapture is called.
   bool got_first_frame_;
+  bool error_occured_;
 
   // |captured_callback_| is provided to this class in StartCapture and must be
   // valid until StopCapture is called.
@@ -81,7 +83,7 @@
   // |state_callback_| is provided to this class in StartCapture and must be
   // valid until StopCapture is called.
   StateChangeCallback state_callback_;
-  // MessageLoop of the caller of StartCapture.
+  // Message loop of the caller of StartCapture.
   scoped_refptr<base::MessageLoopProxy> message_loop_proxy_;
 };
 
diff --git a/content/renderer/media/rtc_video_capturer.cc b/content/renderer/media/rtc_video_capturer.cc
index d6d665c..b1ebf22 100644
--- a/content/renderer/media/rtc_video_capturer.cc
+++ b/content/renderer/media/rtc_video_capturer.cc
@@ -5,6 +5,7 @@
 #include "content/renderer/media/rtc_video_capturer.h"
 
 #include "base/bind.h"
+#include "base/debug/trace_event.h"
 
 namespace content {
 
@@ -100,11 +101,21 @@
   // cricket::CapturedFrame time is in nanoseconds.
   frame.elapsed_time = (buf.timestamp - start_time_).InMicroseconds() *
       base::Time::kNanosecondsPerMicrosecond;
-  frame.time_stamp = frame.elapsed_time;
+  frame.time_stamp =
+      (buf.timestamp - base::Time::UnixEpoch()).InMicroseconds() *
+      base::Time::kNanosecondsPerMicrosecond;
   frame.data = buf.memory_pointer;
   frame.pixel_height = 1;
   frame.pixel_width = 1;
 
+  TRACE_EVENT_INSTANT2("rtc_video_capturer",
+                       "OnFrameCaptured",
+                       TRACE_EVENT_SCOPE_THREAD,
+                       "elapsed time",
+                       frame.elapsed_time,
+                       "timestamp_ms",
+                       frame.time_stamp / talk_base::kNumNanosecsPerMillisec);
+
   // This signals to libJingle that a new VideoFrame is available.
   // libJingle have no assumptions on what thread this signal come from.
   SignalFrameCaptured(this, &frame);
@@ -113,6 +124,7 @@
 void RtcVideoCapturer::OnStateChange(
     RtcVideoCaptureDelegate::CaptureState state) {
   cricket::CaptureState converted_state = cricket::CS_FAILED;
+  DVLOG(3) << " RtcVideoCapturer::OnStateChange " << state;
   switch (state) {
     case RtcVideoCaptureDelegate::CAPTURE_STOPPED:
       converted_state = cricket::CS_STOPPED;
@@ -121,6 +133,10 @@
       converted_state = cricket::CS_RUNNING;
       break;
     case RtcVideoCaptureDelegate::CAPTURE_FAILED:
+      // TODO(perkj): Update the comments in the the definition of
+      // cricket::CS_FAILED. According to the comments, cricket::CS_FAILED
+      // means that the capturer failed to start. But here and in libjingle it
+      // is also used if an error occur during capturing.
       converted_state = cricket::CS_FAILED;
       break;
     default:
diff --git a/content/renderer/media/rtc_video_renderer.cc b/content/renderer/media/rtc_video_renderer.cc
index 6af00f9..8edef65 100644
--- a/content/renderer/media/rtc_video_renderer.cc
+++ b/content/renderer/media/rtc_video_renderer.cc
@@ -11,7 +11,6 @@
 #include "base/message_loop_proxy.h"
 #include "media/base/video_frame.h"
 #include "media/base/video_util.h"
-#include "third_party/libjingle/source/talk/base/timeutils.h"
 #include "third_party/libjingle/source/talk/media/base/videoframe.h"
 
 using media::CopyYPlane;
@@ -76,6 +75,15 @@
 void RTCVideoRenderer::RenderFrame(const cricket::VideoFrame* frame) {
   base::TimeDelta timestamp = base::TimeDelta::FromMilliseconds(
       frame->GetTimeStamp() / talk_base::kNumNanosecsPerMillisec);
+
+  TRACE_EVENT_INSTANT2("rtc_video_renderer",
+                       "RenderFrame",
+                       TRACE_EVENT_SCOPE_THREAD,
+                       "elapsed time",
+                       frame->GetElapsedTime(),
+                       "timestamp_ms",
+                       timestamp.InMilliseconds());
+
   gfx::Size size(frame->GetWidth(), frame->GetHeight());
   scoped_refptr<media::VideoFrame> video_frame =
       media::VideoFrame::CreateFrame(media::VideoFrame::YV12,
diff --git a/content/renderer/media/stream_texture_factory_impl_android.cc b/content/renderer/media/stream_texture_factory_impl_android.cc
index c77700f..355519f 100644
--- a/content/renderer/media/stream_texture_factory_impl_android.cc
+++ b/content/renderer/media/stream_texture_factory_impl_android.cc
@@ -13,15 +13,10 @@
 #include "content/common/gpu/gpu_messages.h"
 #include "content/renderer/render_thread_impl.h"
 #include "third_party/WebKit/Source/Platform/chromium/public/WebGraphicsContext3D.h"
-#include "third_party/WebKit/Source/WebKit/chromium/public/WebStreamTextureClient.h"
 #include "ui/gfx/size.h"
 
 namespace {
 
-static void DeleteStreamTextureHost(content::StreamTextureHost* host) {
-  delete host;
-}
-
 // Implementation of the StreamTextureProxy class. This class listens to all
 // the stream texture updates and forward them to the
 // cc::VideoFrameProvider::Client.
@@ -29,16 +24,14 @@
                                public content::StreamTextureHost::Listener {
  public:
   explicit StreamTextureProxyImpl(content::StreamTextureHost* host);
-  virtual ~StreamTextureProxyImpl();
+  virtual ~StreamTextureProxyImpl() {}
 
   // webkit_media::StreamTextureProxy implementation:
-  virtual bool Initialize(int stream_id, int width, int height) OVERRIDE;
-  virtual bool IsInitialized() OVERRIDE { return initialized_; }
-#ifndef REMOVE_WEBVIDEOFRAME
-  virtual void SetClient(WebKit::WebStreamTextureClient* client) OVERRIDE;
-#else
+  virtual void BindToCurrentThread(
+      int stream_id, int width, int height) OVERRIDE;
+  virtual bool IsBoundToThread() OVERRIDE { return !!loop_.get(); }
   virtual void SetClient(cc::VideoFrameProvider::Client* client) OVERRIDE;
-#endif
+  virtual void Release() OVERRIDE;
 
   // StreamTextureHost::Listener implementation:
   virtual void OnFrameAvailable() OVERRIDE;
@@ -49,12 +42,7 @@
   scoped_refptr<base::MessageLoopProxy> loop_;
 
   base::Lock client_lock_;
-#ifndef REMOVE_WEBVIDEOFRAME
-  WebKit::WebStreamTextureClient* client_;
-#else
   cc::VideoFrameProvider::Client* client_;
-#endif
-  bool initialized_;
 
   DISALLOW_COPY_AND_ASSIGN(StreamTextureProxyImpl);
 };
@@ -62,57 +50,40 @@
 StreamTextureProxyImpl::StreamTextureProxyImpl(
     content::StreamTextureHost* host)
     : host_(host),
-      client_(NULL),
-      initialized_(false) {
+      client_(NULL) {
   DCHECK(host);
   host->SetListener(this);
 }
 
-StreamTextureProxyImpl::~StreamTextureProxyImpl() {
+void StreamTextureProxyImpl::Release() {
   SetClient(NULL);
-  // The StreamTextureHost instance needs to be deleted on the thread
-  // it receives messages on (where it uses a WeakPtr).
-  if (loop_.get()) {
-    loop_->PostTask(FROM_HERE, base::Bind(&DeleteStreamTextureHost,
-                                          host_.release()));
-  }
+  if (loop_ && loop_ != base::MessageLoopProxy::current())
+    loop_->DeleteSoon(FROM_HERE, this);
+  else
+    delete this;
 }
 
-#ifndef REMOVE_WEBVIDEOFRAME
-void StreamTextureProxyImpl::SetClient(WebKit::WebStreamTextureClient* client) {
-#else
 void StreamTextureProxyImpl::SetClient(cc::VideoFrameProvider::Client* client) {
-#endif
   base::AutoLock lock(client_lock_);
   client_ = client;
 }
 
-bool StreamTextureProxyImpl::Initialize(int stream_id, int width, int height) {
+void StreamTextureProxyImpl::BindToCurrentThread(
+    int stream_id, int width, int height) {
   loop_ = base::MessageLoopProxy::current();
-  initialized_ = true;
-  return host_->Initialize(stream_id, gfx::Size(width, height));
+  host_->Initialize(stream_id, gfx::Size(width, height));
 }
 
 void StreamTextureProxyImpl::OnFrameAvailable() {
   base::AutoLock lock(client_lock_);
-#ifndef REMOVE_WEBVIDEOFRAME
-  if (client_)
-    client_->didReceiveFrame();
-#else
   if (client_)
     client_->DidReceiveFrame();
-#endif
 }
 
 void StreamTextureProxyImpl::OnMatrixChanged(const float matrix[16]) {
   base::AutoLock lock(client_lock_);
-#ifndef REMOVE_WEBVIDEOFRAME
-  if (client_)
-    client_->didUpdateMatrix(matrix);
-#else
   if (client_)
     client_->DidUpdateMatrix(matrix);
-#endif
 }
 
 }  // anonymous namespace
diff --git a/content/renderer/media/video_capture_impl.cc b/content/renderer/media/video_capture_impl.cc
index aa428d8..7ee2a2e 100644
--- a/content/renderer/media/video_capture_impl.cc
+++ b/content/renderer/media/video_capture_impl.cc
@@ -56,6 +56,7 @@
       device_id_(0),
       video_type_(media::VideoCaptureCapability::kI420),
       device_info_available_(false),
+      suspended_(false),
       state_(VIDEO_CAPTURE_STATE_STOPPED) {
   DCHECK(filter);
   memset(&current_params_, 0, sizeof(current_params_));
@@ -138,6 +139,12 @@
                  base::Unretained(this), device_id));
 }
 
+void VideoCaptureImpl::SuspendCapture(bool suspend) {
+  capture_message_loop_proxy_->PostTask(FROM_HERE,
+      base::Bind(&VideoCaptureImpl::DoSuspendCaptureOnCaptureThread,
+                 base::Unretained(this), suspend));
+}
+
 void VideoCaptureImpl::DoDeInitOnCaptureThread(base::Closure task) {
   if (state_ == VIDEO_CAPTURE_STATE_STARTED)
     Send(new VideoCaptureHostMsg_Stop(device_id_));
@@ -275,7 +282,7 @@
     int buffer_id, base::Time timestamp) {
   DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread());
 
-  if (state_ != VIDEO_CAPTURE_STATE_STARTED) {
+  if (state_ != VIDEO_CAPTURE_STATE_STARTED || suspended_) {
     Send(new VideoCaptureHostMsg_BufferReady(device_id_, buffer_id));
     return;
   }
@@ -321,6 +328,15 @@
       clients_.clear();
       state_ = VIDEO_CAPTURE_STATE_ERROR;
       break;
+    case VIDEO_CAPTURE_STATE_ENDED:
+      DVLOG(1) << "OnStateChanged: ended!, device_id = " << device_id_;
+      for (ClientInfo::iterator it = clients_.begin();
+          it != clients_.end(); ++it) {
+        it->first->OnRemoved(this);
+      }
+      clients_.clear();
+      state_ = VIDEO_CAPTURE_STATE_ENDED;
+      break;
     default:
       break;
   }
@@ -354,6 +370,13 @@
   }
 }
 
+void VideoCaptureImpl::DoSuspendCaptureOnCaptureThread(bool suspend) {
+  DVLOG(1) << "DoSuspendCapture: suspend " << (suspend ? "yes" : "no");
+  DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread());
+
+  suspended_ = suspend;
+}
+
 void VideoCaptureImpl::StopDevice() {
   DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread());
 
diff --git a/content/renderer/media/video_capture_impl.h b/content/renderer/media/video_capture_impl.h
index 4bb4c55..e47c35d 100644
--- a/content/renderer/media/video_capture_impl.h
+++ b/content/renderer/media/video_capture_impl.h
@@ -57,6 +57,9 @@
       const media::VideoCaptureParams& device_info) OVERRIDE;
   virtual void OnDelegateAdded(int32 device_id) OVERRIDE;
 
+  // Stop/resume delivering video frames to clients, based on flag |suspend|.
+  virtual void SuspendCapture(bool suspend);
+
  private:
   friend class VideoCaptureImplManager;
   friend class VideoCaptureImplTest;
@@ -85,6 +88,8 @@
       const media::VideoCaptureParams& device_info);
   void DoDelegateAddedOnCaptureThread(int32 device_id);
 
+  void DoSuspendCaptureOnCaptureThread(bool suspend);
+
   void Init();
   void DeInit(base::Closure task);
   void DoDeInitOnCaptureThread(base::Closure task);
@@ -124,6 +129,7 @@
   media::VideoCaptureParams device_info_;
   bool device_info_available_;
 
+  bool suspended_;
   VideoCaptureState state_;
 
   DISALLOW_COPY_AND_ASSIGN(VideoCaptureImpl);
diff --git a/content/renderer/media/video_capture_impl_manager.cc b/content/renderer/media/video_capture_impl_manager.cc
index 806ddf5..b270296 100644
--- a/content/renderer/media/video_capture_impl_manager.cc
+++ b/content/renderer/media/video_capture_impl_manager.cc
@@ -37,6 +37,12 @@
   return it->second->vc;
 }
 
+void VideoCaptureImplManager::SuspendDevices(bool suspend) {
+  base::AutoLock auto_lock(lock_);
+  for (Devices::iterator it = devices_.begin(); it != devices_.end(); ++it)
+    it->second->vc->SuspendCapture(suspend);
+}
+
 void VideoCaptureImplManager::RemoveDevice(
     media::VideoCaptureSessionId id,
     media::VideoCapture::EventHandler* handler) {
diff --git a/content/renderer/media/video_capture_impl_manager.h b/content/renderer/media/video_capture_impl_manager.h
index 0a3baf4..c673960 100644
--- a/content/renderer/media/video_capture_impl_manager.h
+++ b/content/renderer/media/video_capture_impl_manager.h
@@ -42,6 +42,10 @@
   virtual void RemoveDevice(media::VideoCaptureSessionId id,
                             media::VideoCapture::EventHandler* handler);
 
+  // Make all existing VideoCaptureImpl instances stop/resume delivering
+  // video frames to their clients, depends on flag |suspend|.
+  virtual void SuspendDevices(bool suspend);
+
   VideoCaptureMessageFilter* video_capture_message_filter() const {
     return filter_;
   }
diff --git a/content/renderer/media/video_capture_impl_unittest.cc b/content/renderer/media/video_capture_impl_unittest.cc
index 4b181d8..2e2c739 100644
--- a/content/renderer/media/video_capture_impl_unittest.cc
+++ b/content/renderer/media/video_capture_impl_unittest.cc
@@ -103,7 +103,7 @@
   };
 
   VideoCaptureImplTest() {
-    message_loop_.reset(new MessageLoop(MessageLoop::TYPE_IO));
+    message_loop_.reset(new base::MessageLoop(base::MessageLoop::TYPE_IO));
     message_loop_proxy_ =
         base::MessageLoopProxy::current().get();
     child_process_.reset(new ChildProcess());
@@ -123,7 +123,7 @@
   }
 
  protected:
-  scoped_ptr<MessageLoop> message_loop_;
+  scoped_ptr<base::MessageLoop> message_loop_;
   scoped_refptr<base::MessageLoopProxy> message_loop_proxy_;
   scoped_ptr<ChildProcess> child_process_;
   scoped_refptr<MockVideoCaptureMessageFilter> message_filter_;
diff --git a/content/renderer/media/video_capture_message_filter_unittest.cc b/content/renderer/media/video_capture_message_filter_unittest.cc
index a2a4cd6..b0ffbc7 100644
--- a/content/renderer/media/video_capture_message_filter_unittest.cc
+++ b/content/renderer/media/video_capture_message_filter_unittest.cc
@@ -105,7 +105,7 @@
 }  // namespace
 
 TEST(VideoCaptureMessageFilterTest, Basic) {
-  MessageLoop message_loop(MessageLoop::TYPE_IO);
+  base::MessageLoop message_loop(base::MessageLoop::TYPE_IO);
 
   scoped_refptr<VideoCaptureMessageFilter> filter(
       new VideoCaptureMessageFilter());
@@ -169,7 +169,7 @@
 }
 
 TEST(VideoCaptureMessageFilterTest, Delegates) {
-  MessageLoop message_loop(MessageLoop::TYPE_IO);
+  base::MessageLoop message_loop(base::MessageLoop::TYPE_IO);
 
   scoped_refptr<VideoCaptureMessageFilter> filter(
       new VideoCaptureMessageFilter());
diff --git a/content/renderer/media/video_destination_handler.cc b/content/renderer/media/video_destination_handler.cc
new file mode 100644
index 0000000..345525e
--- /dev/null
+++ b/content/renderer/media/video_destination_handler.cc
@@ -0,0 +1,199 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/media/video_destination_handler.h"
+
+#include <string>
+
+#include "base/logging.h"
+#include "content/renderer/media/media_stream_dependency_factory.h"
+#include "content/renderer/media/media_stream_registry_interface.h"
+#include "content/renderer/render_thread_impl.h"
+#include "third_party/WebKit/Source/Platform/chromium/public/WebMediaStreamTrack.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebMediaStreamRegistry.h"
+#include "webkit/plugins/ppapi/ppb_image_data_impl.h"
+
+using cricket::CaptureState;
+using cricket::VideoFormat;
+using webkit::ppapi::PPB_ImageData_Impl;
+using webrtc::VideoTrackInterface;
+using webrtc::VideoTrackVector;
+
+static const cricket::FourCC kEffectColorFormat = cricket::FOURCC_BGRA;
+
+namespace content {
+
+PpFrameWriter::PpFrameWriter()
+    : started_(false) {}
+
+PpFrameWriter::~PpFrameWriter() {}
+
+CaptureState PpFrameWriter::Start(const VideoFormat& capture_format) {
+  base::AutoLock auto_lock(lock_);
+  if (started_) {
+    LOG(ERROR) << "PpFrameWriter::Start - "
+               << "Got a StartCapture when already started!";
+    return cricket::CS_FAILED;
+  }
+  started_ = true;
+  return cricket::CS_STARTING;
+}
+
+void PpFrameWriter::Stop() {
+  base::AutoLock auto_lock(lock_);
+  started_ = false;
+  SignalStateChange(this, cricket::CS_STOPPED);
+}
+
+bool PpFrameWriter::IsRunning() {
+  return started_;
+}
+
+bool PpFrameWriter::GetPreferredFourccs(std::vector<uint32>* fourccs) {
+  if (!fourccs) {
+    LOG(ERROR) << "PpFrameWriter::GetPreferredFourccs - "
+               << "fourccs is NULL.";
+    return false;
+  }
+  // The effects plugin output BGRA.
+  fourccs->push_back(kEffectColorFormat);
+  return true;
+}
+
+bool PpFrameWriter::GetBestCaptureFormat(const VideoFormat& desired,
+                                         VideoFormat* best_format) {
+  if (!best_format) {
+    LOG(ERROR) << "PpFrameWriter::GetBestCaptureFormat - "
+               << "best_format is NULL.";
+    return false;
+  }
+
+  // Use the desired format as the best format.
+  best_format->width = desired.width;
+  best_format->height = desired.height;
+  best_format->fourcc = kEffectColorFormat;
+  best_format->interval = desired.interval;
+  return true;
+}
+
+bool PpFrameWriter::IsScreencast() const {
+  return false;
+}
+
+void PpFrameWriter::PutFrame(PPB_ImageData_Impl* image_data,
+                             int64 time_stamp_ns) {
+  base::AutoLock auto_lock(lock_);
+  // This assumes the handler of the SignalFrameCaptured won't call Start/Stop.
+  // TODO(ronghuawu): Avoid the using of lock. One way is to post this call to
+  // libjingle worker thread, which will require an extra copy of |image_data|.
+  // However if pepper host can hand over the ownership of |image_data|
+  // then we can avoid this extra copy.
+  if (!started_) {
+    LOG(ERROR) << "PpFrameWriter::PutFrame - "
+               << "Called when capturer is not started.";
+    return;
+  }
+  ASSERT(image_data != NULL);
+  webkit::ppapi::ImageDataAutoMapper mapper(image_data);
+  if (!mapper.is_valid()) {
+    LOG(ERROR) << "PpFrameWriter::PutFrame - "
+               << "The image could not be mapped and is unusable.";
+    return;
+  }
+  const SkBitmap* bitmap = image_data->GetMappedBitmap();
+  ASSERT(bitmap != NULL);
+
+  cricket::CapturedFrame frame;
+  frame.elapsed_time = 0;
+  frame.time_stamp = time_stamp_ns;
+  frame.pixel_height = 1;
+  frame.pixel_width = 1;
+  frame.width = bitmap->width();
+  frame.height = bitmap->height();
+  if (image_data->format() == PP_IMAGEDATAFORMAT_BGRA_PREMUL) {
+    frame.fourcc = cricket::FOURCC_BGRA;
+  } else {
+    LOG(ERROR) << "PpFrameWriter::PutFrame - Got RGBA which is not supported.";
+    ASSERT(false);
+    return;
+  }
+  frame.data_size = bitmap->getSize();
+  frame.data = bitmap->getPixels();
+
+  // This signals to libJingle that a new VideoFrame is available.
+  // libJingle have no assumptions on what thread this signal come from.
+  SignalFrameCaptured(this, &frame);
+}
+
+// PpFrameWriterProxy is a helper class to make sure the user won't use
+// PpFrameWriter after it is released (IOW its owner - WebMediaStreamTrack -
+// is released).
+class PpFrameWriterProxy : public FrameWriterInterface {
+ public:
+  PpFrameWriterProxy(VideoTrackInterface* track,
+                     PpFrameWriter* writer)
+      : track_(track),
+        writer_(writer) {
+    ASSERT(writer_ != NULL);
+  }
+
+  virtual ~PpFrameWriterProxy() {}
+
+  virtual void PutFrame(webkit::ppapi::PPB_ImageData_Impl* image_data,
+                        int64 time_stamp_ns) OVERRIDE {
+    writer_->PutFrame(image_data, time_stamp_ns);
+  }
+
+ private:
+  scoped_refptr<VideoTrackInterface> track_;
+  PpFrameWriter* writer_;
+
+  DISALLOW_COPY_AND_ASSIGN(PpFrameWriterProxy);
+};
+
+bool VideoDestinationHandler::Open(
+    MediaStreamDependencyFactory* factory,
+    MediaStreamRegistryInterface* registry,
+    const std::string& url,
+    FrameWriterInterface** frame_writer) {
+  if (!factory) {
+    factory = RenderThreadImpl::current()->GetMediaStreamDependencyFactory();
+    ASSERT(factory != NULL);
+  }
+  WebKit::WebMediaStream stream;
+  if (registry) {
+    stream = registry->GetMediaStream(url);
+  } else {
+    stream =
+        WebKit::WebMediaStreamRegistry::lookupMediaStreamDescriptor(GURL(url));
+  }
+  if (stream.isNull() || !stream.extraData()) {
+    LOG(ERROR) << "VideoDestinationHandler::Open - invalid url: " << url;
+    return false;
+  }
+
+  // Create a new native video track and add it to |stream|.
+  std::string track_id = talk_base::ToString(talk_base::CreateRandomId64());
+  PpFrameWriter* writer = new PpFrameWriter();
+  if (!factory->AddNativeVideoMediaTrack(track_id, &stream, writer)) {
+    delete writer;
+    return false;
+  }
+
+  // Gets a handler to the native video track, which owns the |writer|.
+  MediaStreamExtraData* extra_data =
+      static_cast<MediaStreamExtraData*>(stream.extraData());
+  DCHECK(extra_data);
+  webrtc::MediaStreamInterface* native_stream = extra_data->stream();
+  DCHECK(native_stream);
+  VideoTrackVector video_tracks = native_stream->GetVideoTracks();
+  // Currently one supports one video track per media stream.
+  ASSERT(video_tracks.size() == 1);
+
+  *frame_writer = new PpFrameWriterProxy(video_tracks[0].get(), writer);
+  return true;
+}
+
+}  // namespace content
+
diff --git a/content/renderer/media/video_destination_handler.h b/content/renderer/media/video_destination_handler.h
new file mode 100644
index 0000000..68b1a6c
--- /dev/null
+++ b/content/renderer/media/video_destination_handler.h
@@ -0,0 +1,99 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_RENDERER_MEDIA_VIDEO_DESTINATION_HANDLER_H_
+#define CONTENT_RENDERER_MEDIA_VIDEO_DESTINATION_HANDLER_H_
+
+#include <string>
+#include <vector>
+
+#include "base/compiler_specific.h"
+#include "base/synchronization/lock.h"
+#include "content/common/content_export.h"
+#include "third_party/libjingle/source/talk/media/base/videocapturer.h"
+
+namespace webkit {
+namespace ppapi {
+class PPB_ImageData_Impl;
+}
+}
+
+namespace content {
+
+class MediaStreamDependencyFactory;
+class MediaStreamRegistryInterface;
+
+// Interface used by the effects pepper plugin to output the processed frame
+// to the video track.
+class CONTENT_EXPORT FrameWriterInterface {
+ public:
+  // The ownership of the |image_data| deosn't transfer. So the implementation
+  // of this interface should make a copy of the |image_data| before return.
+  virtual void PutFrame(webkit::ppapi::PPB_ImageData_Impl* image_data,
+                        int64 time_stamp_ns) = 0;
+  virtual ~FrameWriterInterface() {}
+};
+
+// PpFrameWriter implements cricket::VideoCapturer so that it can be used in
+// the native video track's video source. It also implements
+// FrameWriterInterface, which will be used by the effects pepper plugin to
+// inject the processed frame.
+class CONTENT_EXPORT PpFrameWriter
+    : public NON_EXPORTED_BASE(cricket::VideoCapturer),
+      public FrameWriterInterface {
+ public:
+  PpFrameWriter();
+  virtual ~PpFrameWriter();
+
+  // cricket::VideoCapturer implementation.
+  // These methods are accessed from a libJingle worker thread.
+  virtual cricket::CaptureState Start(
+      const cricket::VideoFormat& capture_format) OVERRIDE;
+  virtual void Stop() OVERRIDE;
+  virtual bool IsRunning() OVERRIDE;
+  virtual bool GetPreferredFourccs(std::vector<uint32>* fourccs) OVERRIDE;
+  virtual bool GetBestCaptureFormat(const cricket::VideoFormat& desired,
+                                    cricket::VideoFormat* best_format) OVERRIDE;
+  virtual bool IsScreencast() const OVERRIDE;
+
+  // FrameWriterInterface implementation.
+  // This method will be called by the Pepper host from render thread.
+  virtual void PutFrame(webkit::ppapi::PPB_ImageData_Impl* image_data,
+                        int64 time_stamp_ns) OVERRIDE;
+
+ private:
+  bool started_;
+  // |lock_| is used to protect |started_| which will be accessed from different
+  // threads - libjingle worker thread and render thread.
+  base::Lock lock_;
+
+  DISALLOW_COPY_AND_ASSIGN(PpFrameWriter);
+};
+
+// VideoDestinationHandler is a glue class between the webrtc MediaStream and
+// the effects pepper plugin host.
+class CONTENT_EXPORT VideoDestinationHandler {
+ public:
+  // Instantiates and adds a new video track to the MediaStream specified by
+  // |url|. Returns a handler for delivering frames to the new video track as
+  // |frame_writer|.
+  // If |factory| is NULL the MediaStreamDependencyFactory owned by
+  // RenderThreadImpl::current() will be used.
+  // If |registry| is NULL the global WebKit::WebMediaStreamRegistry will be
+  // used to look up the media stream.
+  // The caller of the function takes the ownership of |frame_writer|.
+  // Returns true on success and false on failure.
+  static bool Open(MediaStreamDependencyFactory* factory,
+                   MediaStreamRegistryInterface* registry,
+                   const std::string& url,
+                   FrameWriterInterface** frame_writer);
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(VideoDestinationHandler);
+};
+
+}  // namespace content
+
+#endif  // CONTENT_RENDERER_MEDIA_VIDEO_DESTINATION_HANDLER_H_
+
diff --git a/content/renderer/media/video_destination_handler_unittest.cc b/content/renderer/media/video_destination_handler_unittest.cc
new file mode 100644
index 0000000..abdad6a
--- /dev/null
+++ b/content/renderer/media/video_destination_handler_unittest.cc
@@ -0,0 +1,127 @@
+// Copyright (c) 2013 The Chromium Authors. 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 "content/renderer/media/media_stream_extra_data.h"
+#include "content/renderer/media/mock_media_stream_dependency_factory.h"
+#include "content/renderer/media/mock_media_stream_registry.h"
+#include "content/renderer/media/video_destination_handler.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/WebKit/Source/Platform/chromium/public/WebMediaStreamTrack.h"
+#include "third_party/WebKit/Source/Platform/chromium/public/WebString.h"
+
+using cricket::CapturedFrame;
+using cricket::CaptureState;
+using cricket::VideoCapturer;
+using cricket::VideoFormat;
+using cricket::VideoFormatPod;
+
+namespace content {
+
+static const std::string kTestStreamUrl = "stream_url";
+static const std::string kUnknownStreamUrl = "unknown_stream_url";
+static const VideoFormatPod kTestFormat = {
+  640, 360, FPS_TO_INTERVAL(30), cricket::FOURCC_ANY
+};
+
+class PpFrameWriterTest
+    : public ::testing::Test,
+      public sigslot::has_slots<> {
+ public:
+  PpFrameWriterTest()
+      : last_capture_state_(cricket::CS_FAILED),
+        captured_frame_count_(0),
+        captured_frame_(NULL) {
+    writer_.SignalStateChange.connect(this, &PpFrameWriterTest::OnStateChange);
+    writer_.SignalFrameCaptured.connect(
+        this, &PpFrameWriterTest::OnFrameCaptured);
+  }
+
+  void OnStateChange(VideoCapturer* capturer, CaptureState state) {
+    last_capture_state_ = state;
+  }
+
+  void OnFrameCaptured(VideoCapturer* capturer, const CapturedFrame* frame) {
+    ++captured_frame_count_;
+    captured_frame_ = const_cast<CapturedFrame*>(frame);
+  }
+
+ protected:
+  PpFrameWriter writer_;
+  CaptureState last_capture_state_;
+  int captured_frame_count_;
+  CapturedFrame* captured_frame_;
+};
+
+class VideoDestinationHandlerTest : public ::testing::Test {
+ public:
+  VideoDestinationHandlerTest() : registry_(&factory_) {
+    factory_.EnsurePeerConnectionFactory();
+    registry_.Init(kTestStreamUrl);
+  }
+
+ protected:
+  MockMediaStreamDependencyFactory factory_;
+  MockMediaStreamRegistry registry_;
+};
+
+TEST_F(PpFrameWriterTest, StartStop) {
+  EXPECT_FALSE(writer_.IsRunning());
+  EXPECT_EQ(cricket::CS_STARTING, writer_.Start(VideoFormat(kTestFormat)));
+  EXPECT_TRUE(writer_.IsRunning());
+  EXPECT_EQ(cricket::CS_FAILED, writer_.Start(VideoFormat(kTestFormat)));
+  writer_.Stop();
+  EXPECT_EQ(cricket::CS_STOPPED, last_capture_state_);
+}
+
+TEST_F(PpFrameWriterTest, GetPreferredFourccs) {
+  std::vector<uint32> fourccs;
+  EXPECT_TRUE(writer_.GetPreferredFourccs(&fourccs));
+  EXPECT_EQ(1u, fourccs.size());
+  EXPECT_EQ(cricket::FOURCC_BGRA, fourccs[0]);
+}
+
+TEST_F(PpFrameWriterTest, GetBestCaptureFormat) {
+  VideoFormat desired(kTestFormat);
+  VideoFormat best_format;
+  EXPECT_FALSE(writer_.GetBestCaptureFormat(desired, NULL));
+  EXPECT_TRUE(writer_.GetBestCaptureFormat(desired, &best_format));
+  EXPECT_EQ(cricket::FOURCC_BGRA, best_format.fourcc);
+
+  desired.fourcc = best_format.fourcc;
+  EXPECT_EQ(desired, best_format);
+}
+
+TEST_F(VideoDestinationHandlerTest, Open) {
+  FrameWriterInterface* frame_writer = NULL;
+  // Unknow url will return false.
+  EXPECT_FALSE(VideoDestinationHandler::Open(&factory_, &registry_,
+                                             kUnknownStreamUrl, &frame_writer));
+  EXPECT_TRUE(VideoDestinationHandler::Open(&factory_, &registry_,
+                                            kTestStreamUrl, &frame_writer));
+  EXPECT_TRUE(frame_writer);
+
+  // Verify the video track has been added.
+  const WebKit::WebMediaStream test_stream = registry_.test_stream();
+  WebKit::WebVector<WebKit::WebMediaStreamTrack> video_tracks;
+  test_stream.videoSources(video_tracks);
+  EXPECT_EQ(1u, video_tracks.size());
+
+  // Verify the native video track has been added.
+  MediaStreamExtraData* extra_data =
+      static_cast<MediaStreamExtraData*>(test_stream.extraData());
+  DCHECK(extra_data);
+  webrtc::MediaStreamInterface* native_stream = extra_data->stream();
+  DCHECK(native_stream);
+  webrtc::VideoTrackVector native_video_tracks =
+      native_stream->GetVideoTracks();
+  EXPECT_EQ(1u, native_video_tracks.size());
+
+  delete frame_writer;
+}
+
+}  // namespace content
diff --git a/content/renderer/media/video_source_handler.cc b/content/renderer/media/video_source_handler.cc
new file mode 100644
index 0000000..c4f875d
--- /dev/null
+++ b/content/renderer/media/video_source_handler.cc
@@ -0,0 +1,142 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/media/video_source_handler.h"
+
+#include <string>
+
+#include "base/logging.h"
+#include "content/renderer/media/media_stream_dependency_factory.h"
+#include "content/renderer/media/media_stream_registry_interface.h"
+#include "content/renderer/render_thread_impl.h"
+#include "third_party/WebKit/Source/Platform/chromium/public/WebMediaStream.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebMediaStreamRegistry.h"
+#include "third_party/libjingle/source/talk/media/base/videoframe.h"
+#include "third_party/libjingle/source/talk/media/base/videorenderer.h"
+
+using cricket::VideoFrame;
+using cricket::VideoRenderer;
+using webrtc::VideoSourceInterface;
+
+namespace content {
+
+// PpFrameReceiver implements cricket::VideoRenderer so that it can be attached
+// to native video track's video source to receive the captured frame.
+// It can be attached to a FrameReaderInterface to output the received frame.
+class PpFrameReceiver : public cricket::VideoRenderer {
+ public:
+  PpFrameReceiver() : reader_(NULL) {}
+  virtual ~PpFrameReceiver() {}
+
+  // Implements VideoRenderer.
+  virtual bool SetSize(int width, int height, int reserved) OVERRIDE {
+    return true;
+  }
+  virtual bool RenderFrame(const cricket::VideoFrame* frame) OVERRIDE {
+    base::AutoLock auto_lock(lock_);
+    if (reader_) {
+      // Make a shallow copy of the frame as the |reader_| may need to queue it.
+      // Both frames will share a single reference-counted frame buffer.
+      reader_->GotFrame(frame->Copy());
+    }
+    return true;
+  }
+
+  void SetReader(FrameReaderInterface* reader) {
+    base::AutoLock auto_lock(lock_);
+    reader_ = reader;
+  }
+
+ private:
+  FrameReaderInterface* reader_;
+  base::Lock lock_;
+
+  DISALLOW_COPY_AND_ASSIGN(PpFrameReceiver);
+};
+
+VideoSourceHandler::VideoSourceHandler(
+    MediaStreamRegistryInterface* registry)
+    : registry_(registry) {
+}
+
+VideoSourceHandler::~VideoSourceHandler() {}
+
+bool VideoSourceHandler::Open(const std::string& url,
+                              FrameReaderInterface* reader) {
+  scoped_refptr<webrtc::VideoSourceInterface> source = GetFirstVideoSource(url);
+  if (!source.get()) {
+    return false;
+  }
+  PpFrameReceiver* receiver = new PpFrameReceiver();
+  receiver->SetReader(reader);
+  source->AddSink(receiver);
+  reader_to_receiver_[reader] = receiver;
+  return true;
+}
+
+bool VideoSourceHandler::Close(const std::string& url,
+                               FrameReaderInterface* reader) {
+  scoped_refptr<webrtc::VideoSourceInterface> source = GetFirstVideoSource(url);
+  if (!source.get()) {
+    LOG(ERROR) << "VideoSourceHandler::Close - Failed to get the video source "
+               << "from MediaStream with url: " << url;
+    return false;
+  }
+  PpFrameReceiver* receiver =
+      static_cast<PpFrameReceiver*>(GetReceiver(reader));
+  receiver->SetReader(NULL);
+  source->RemoveSink(receiver);
+  reader_to_receiver_.erase(reader);
+  return true;
+}
+
+scoped_refptr<VideoSourceInterface> VideoSourceHandler::GetFirstVideoSource(
+    const std::string& url) {
+  scoped_refptr<webrtc::VideoSourceInterface> source;
+  WebKit::WebMediaStream stream;
+  if (registry_) {
+    stream = registry_->GetMediaStream(url);
+  } else {
+    stream =
+        WebKit::WebMediaStreamRegistry::lookupMediaStreamDescriptor(GURL(url));
+  }
+  if (stream.isNull() || !stream.extraData()) {
+    LOG(ERROR) << "GetFirstVideoSource - invalid url: " << url;
+    return source;
+  }
+
+  // Get the first video track from the stream.
+  MediaStreamExtraData* extra_data =
+      static_cast<MediaStreamExtraData*>(stream.extraData());
+  if (!extra_data) {
+    LOG(ERROR) << "GetFirstVideoSource - MediaStreamExtraData is NULL.";
+    return source;
+  }
+  webrtc::MediaStreamInterface* native_stream = extra_data->stream();
+  if (!native_stream) {
+    LOG(ERROR) << "GetFirstVideoSource - native stream is NULL.";
+    return source;
+  }
+  webrtc::VideoTrackVector native_video_tracks =
+      native_stream->GetVideoTracks();
+  if (native_video_tracks.empty()) {
+    LOG(ERROR) << "GetFirstVideoSource - stream has no video track.";
+    return source;
+  }
+  source = native_video_tracks[0]->GetSource();
+  return source;
+}
+
+VideoRenderer* VideoSourceHandler::GetReceiver(
+    FrameReaderInterface* reader) {
+  std::map<FrameReaderInterface*, VideoRenderer*>::iterator it;
+  it = reader_to_receiver_.find(reader);
+  if (it == reader_to_receiver_.end()) {
+    return NULL;
+  }
+  return it->second;
+}
+
+}  // namespace content
+
diff --git a/content/renderer/media/video_source_handler.h b/content/renderer/media/video_source_handler.h
new file mode 100644
index 0000000..3d3b4df
--- /dev/null
+++ b/content/renderer/media/video_source_handler.h
@@ -0,0 +1,73 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_RENDERER_MEDIA_VIDEO_SOURCE_HANDLER_H_
+#define CONTENT_RENDERER_MEDIA_VIDEO_SOURCE_HANDLER_H_
+
+#include <map>
+#include <string>
+
+#include "base/compiler_specific.h"
+#include "base/memory/ref_counted.h"
+#include "content/common/content_export.h"
+#include "third_party/libjingle/source/talk/app/webrtc/videosourceinterface.h"
+
+namespace cricket {
+class VideoFrame;
+}
+
+namespace content {
+
+class MediaStreamDependencyFactory;
+class MediaStreamRegistryInterface;
+
+// Interface used by the effects pepper plugin to get captured frame
+// from the video track.
+class CONTENT_EXPORT FrameReaderInterface {
+ public:
+  // Got a new captured frame.
+  // The ownership of the |frame| is transfered to the caller. So the caller
+  // must delete |frame| when done with it.
+  virtual bool GotFrame(cricket::VideoFrame* frame) = 0;
+
+ protected:
+  virtual ~FrameReaderInterface() {}
+};
+
+// VideoSourceHandler is a glue class between the webrtc MediaStream and
+// the effects pepper plugin host.
+class CONTENT_EXPORT VideoSourceHandler {
+ public:
+  // |registry| is used to look up the media stream by url. If a NULL |registry|
+  // is given, the global WebKit::WebMediaStreamRegistry will be used.
+  explicit VideoSourceHandler(MediaStreamRegistryInterface* registry);
+  virtual ~VideoSourceHandler();
+  // Connects to the first video track in the MediaStream specified by |url| and
+  // the received frames will be delivered via |reader|.
+  // Returns true on success and false on failure.
+  bool Open(const std::string& url, FrameReaderInterface* reader);
+  // Closes |reader|'s connection with the first video track in
+  // the MediaStream specified by |url|, i.e. stops receiving frames from the
+  // video track.
+  // Returns true on success and false on failure.
+  bool Close(const std::string& url, FrameReaderInterface* reader);
+
+  // Gets the VideoRenderer associated with |reader|.
+  // Made it public only for testing purpose.
+  cricket::VideoRenderer* GetReceiver(FrameReaderInterface* reader);
+
+ private:
+  scoped_refptr<webrtc::VideoSourceInterface> GetFirstVideoSource(
+      const std::string& url);
+
+  MediaStreamRegistryInterface* registry_;
+  std::map<FrameReaderInterface*, cricket::VideoRenderer*> reader_to_receiver_;
+
+  DISALLOW_COPY_AND_ASSIGN(VideoSourceHandler);
+};
+
+}  // namespace content
+
+#endif  // CONTENT_RENDERER_MEDIA_VIDEO_SOURCE_HANDLER_H_
+
diff --git a/content/renderer/media/video_source_handler_unittest.cc b/content/renderer/media/video_source_handler_unittest.cc
new file mode 100644
index 0000000..653d7a2
--- /dev/null
+++ b/content/renderer/media/video_source_handler_unittest.cc
@@ -0,0 +1,89 @@
+// Copyright (c) 2013 The Chromium Authors. 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 "content/renderer/media/media_stream_extra_data.h"
+#include "content/renderer/media/media_stream_registry_interface.h"
+#include "content/renderer/media/mock_media_stream_dependency_factory.h"
+#include "content/renderer/media/mock_media_stream_registry.h"
+#include "content/renderer/media/video_source_handler.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/WebKit/Source/Platform/chromium/public/WebMediaStreamTrack.h"
+#include "third_party/WebKit/Source/Platform/chromium/public/WebString.h"
+#include "third_party/libjingle/source/talk/media/base/videorenderer.h"
+#include "third_party/libjingle/source/talk/media/webrtc/webrtcvideoframe.h"
+
+using cricket::VideoFrame;
+
+namespace content {
+
+static const std::string kTestStreamUrl = "stream_url";
+static const std::string kTestVideoTrackId = "video_track_id";
+static const std::string kUnknownStreamUrl = "unknown_stream_url";
+
+class FakeFrameReader : public FrameReaderInterface {
+ public:
+  virtual bool GotFrame(VideoFrame* frame) OVERRIDE {
+    last_frame_.reset(frame);
+    return true;
+  }
+
+  const VideoFrame* last_frame() {
+    return last_frame_.get();
+  }
+
+ private:
+  scoped_ptr<VideoFrame> last_frame_;
+};
+
+class VideoSourceHandlerTest : public ::testing::Test {
+ public:
+  VideoSourceHandlerTest() : registry_(&dependency_factory_) {
+    handler_.reset(new VideoSourceHandler(&registry_));
+    dependency_factory_.EnsurePeerConnectionFactory();
+    registry_.Init(kTestStreamUrl);
+    registry_.AddVideoTrack(kTestVideoTrackId);
+  }
+
+ protected:
+  scoped_ptr<VideoSourceHandler> handler_;
+  MockMediaStreamDependencyFactory dependency_factory_;
+  MockMediaStreamRegistry registry_;
+};
+
+TEST_F(VideoSourceHandlerTest, OpenClose) {
+  FakeFrameReader reader;
+  // Unknow url will return false.
+  EXPECT_FALSE(handler_->Open(kUnknownStreamUrl, &reader));
+  EXPECT_TRUE(handler_->Open(kTestStreamUrl, &reader));
+  cricket::WebRtcVideoFrame test_frame;
+  int width = 640;
+  int height = 360;
+  int64 et = 123456;
+  int64 ts = 789012;
+  test_frame.InitToBlack(width, height, 1, 1, et, ts);
+  cricket::VideoRenderer* receiver = handler_->GetReceiver(&reader);
+  ASSERT(receiver != NULL);
+  receiver->RenderFrame(&test_frame);
+
+  const VideoFrame* frame = reader.last_frame();
+  ASSERT_TRUE(frame != NULL);
+
+  // Compare |frame| to |test_frame|.
+  EXPECT_EQ(test_frame.GetWidth(), frame->GetWidth());
+  EXPECT_EQ(test_frame.GetHeight(), frame->GetHeight());
+  EXPECT_EQ(test_frame.GetElapsedTime(), frame->GetElapsedTime());
+  EXPECT_EQ(test_frame.GetTimeStamp(), frame->GetTimeStamp());
+  EXPECT_EQ(test_frame.GetYPlane(), frame->GetYPlane());
+  EXPECT_EQ(test_frame.GetUPlane(), frame->GetUPlane());
+  EXPECT_EQ(test_frame.GetVPlane(), frame->GetVPlane());
+
+  EXPECT_TRUE(handler_->Close(kTestStreamUrl, &reader));
+  EXPECT_TRUE(handler_->GetReceiver(&reader) == NULL);
+}
+
+}  // namespace content
diff --git a/content/renderer/media/webmediaplayer_proxy_impl_android.cc b/content/renderer/media/webmediaplayer_proxy_impl_android.cc
index 875e4c1..652964a 100644
--- a/content/renderer/media/webmediaplayer_proxy_impl_android.cc
+++ b/content/renderer/media/webmediaplayer_proxy_impl_android.cc
@@ -7,7 +7,7 @@
 #include "base/bind.h"
 #include "base/message_loop.h"
 #include "content/common/media/media_player_messages.h"
-#include "webkit/media/android/webmediaplayer_impl_android.h"
+#include "webkit/media/android/webmediaplayer_android.h"
 #include "webkit/media/android/webmediaplayer_manager_android.h"
 
 namespace content {
@@ -27,7 +27,8 @@
     const IPC::Message& msg) {
   bool handled = true;
   IPC_BEGIN_MESSAGE_MAP(WebMediaPlayerProxyImplAndroid, msg)
-    IPC_MESSAGE_HANDLER(MediaPlayerMsg_MediaPrepared, OnMediaPrepared)
+    IPC_MESSAGE_HANDLER(MediaPlayerMsg_MediaMetadataChanged,
+                        OnMediaMetadataChanged)
     IPC_MESSAGE_HANDLER(MediaPlayerMsg_MediaPlaybackCompleted,
                         OnMediaPlaybackCompleted)
     IPC_MESSAGE_HANDLER(MediaPlayerMsg_MediaBufferingUpdate,
@@ -43,15 +44,20 @@
     IPC_MESSAGE_HANDLER(MediaPlayerMsg_DidExitFullscreen, OnDidExitFullscreen)
     IPC_MESSAGE_HANDLER(MediaPlayerMsg_DidMediaPlayerPlay, OnPlayerPlay)
     IPC_MESSAGE_HANDLER(MediaPlayerMsg_DidMediaPlayerPause, OnPlayerPause)
+#if defined(GOOGLE_TV)
+    IPC_MESSAGE_HANDLER(MediaPlayerMsg_ReadFromDemuxer, OnReadFromDemuxer)
+#endif
   IPC_MESSAGE_UNHANDLED(handled = false)
   IPC_END_MESSAGE_MAP()
   return handled;
 }
 
 void WebMediaPlayerProxyImplAndroid::Initialize(
-    int player_id, const GURL& url, const GURL& first_party_for_cookies) {
+    int player_id, const GURL& url,
+    bool is_media_source,
+    const GURL& first_party_for_cookies) {
   Send(new MediaPlayerHostMsg_MediaPlayerInitialize(
-      routing_id(), player_id, url, first_party_for_cookies));
+      routing_id(), player_id, url, is_media_source, first_party_for_cookies));
 }
 
 void WebMediaPlayerProxyImplAndroid::Start(int player_id) {
@@ -74,97 +80,88 @@
   Send(new MediaPlayerHostMsg_DestroyMediaPlayer(routing_id(), player_id));
 }
 
-void WebMediaPlayerProxyImplAndroid::OnMediaPrepared(
+void WebMediaPlayerProxyImplAndroid::OnMediaMetadataChanged(
     int player_id,
-    base::TimeDelta duration) {
-  webkit_media::WebMediaPlayerImplAndroid* player =
-      GetWebMediaPlayer(player_id);
+    base::TimeDelta duration,
+    int width,
+    int height,
+    bool success) {
+  webkit_media::WebMediaPlayerAndroid* player = GetWebMediaPlayer(player_id);
   if (player)
-    player->OnMediaPrepared(duration);
+    player->OnMediaMetadataChanged(duration, width, height, success);
 }
 
 void WebMediaPlayerProxyImplAndroid::OnMediaPlaybackCompleted(
     int player_id) {
-  webkit_media::WebMediaPlayerImplAndroid* player =
-      GetWebMediaPlayer(player_id);
+  webkit_media::WebMediaPlayerAndroid* player = GetWebMediaPlayer(player_id);
   if (player)
     player->OnPlaybackComplete();
 }
 
 void WebMediaPlayerProxyImplAndroid::OnMediaBufferingUpdate(
     int player_id, int percent) {
-  webkit_media::WebMediaPlayerImplAndroid* player =
-      GetWebMediaPlayer(player_id);
+  webkit_media::WebMediaPlayerAndroid* player = GetWebMediaPlayer(player_id);
   if (player)
     player->OnBufferingUpdate(percent);
 }
 
 void WebMediaPlayerProxyImplAndroid::OnMediaSeekCompleted(
     int player_id, base::TimeDelta current_time) {
-  webkit_media::WebMediaPlayerImplAndroid* player =
-      GetWebMediaPlayer(player_id);
+  webkit_media::WebMediaPlayerAndroid* player = GetWebMediaPlayer(player_id);
   if (player)
     player->OnSeekComplete(current_time);
 }
 
 void WebMediaPlayerProxyImplAndroid::OnMediaError(
     int player_id, int error) {
-  webkit_media::WebMediaPlayerImplAndroid* player =
-      GetWebMediaPlayer(player_id);
+  webkit_media::WebMediaPlayerAndroid* player = GetWebMediaPlayer(player_id);
   if (player)
     player->OnMediaError(error);
 }
 
 void WebMediaPlayerProxyImplAndroid::OnVideoSizeChanged(
     int player_id, int width, int height) {
-  webkit_media::WebMediaPlayerImplAndroid* player =
-      GetWebMediaPlayer(player_id);
+  webkit_media::WebMediaPlayerAndroid* player = GetWebMediaPlayer(player_id);
   if (player)
     player->OnVideoSizeChanged(width, height);
 }
 
 void WebMediaPlayerProxyImplAndroid::OnTimeUpdate(
     int player_id, base::TimeDelta current_time) {
-  webkit_media::WebMediaPlayerImplAndroid* player =
-      GetWebMediaPlayer(player_id);
+  webkit_media::WebMediaPlayerAndroid* player = GetWebMediaPlayer(player_id);
   if (player)
     player->OnTimeUpdate(current_time);
 }
 
 void WebMediaPlayerProxyImplAndroid::OnMediaPlayerReleased(
     int player_id) {
-  webkit_media::WebMediaPlayerImplAndroid* player =
-      GetWebMediaPlayer(player_id);
+  webkit_media::WebMediaPlayerAndroid* player = GetWebMediaPlayer(player_id);
   if (player)
     player->OnPlayerReleased();
 }
 
 void WebMediaPlayerProxyImplAndroid::OnDidEnterFullscreen(
     int player_id) {
-  webkit_media::WebMediaPlayerImplAndroid* player =
-      GetWebMediaPlayer(player_id);
+  webkit_media::WebMediaPlayerAndroid* player = GetWebMediaPlayer(player_id);
   if (player)
     player->OnDidEnterFullscreen();
 }
 
 void WebMediaPlayerProxyImplAndroid::OnDidExitFullscreen(
     int player_id) {
-  webkit_media::WebMediaPlayerImplAndroid* player =
-      GetWebMediaPlayer(player_id);
+  webkit_media::WebMediaPlayerAndroid* player = GetWebMediaPlayer(player_id);
   if (player)
     player->OnDidExitFullscreen();
 }
 
 void WebMediaPlayerProxyImplAndroid::OnPlayerPlay(int player_id) {
-  webkit_media::WebMediaPlayerImplAndroid* player =
-      GetWebMediaPlayer(player_id);
+  webkit_media::WebMediaPlayerAndroid* player = GetWebMediaPlayer(player_id);
   if (player)
     player->OnMediaPlayerPlay();
 }
 
 void WebMediaPlayerProxyImplAndroid::OnPlayerPause(int player_id) {
-  webkit_media::WebMediaPlayerImplAndroid* player =
-      GetWebMediaPlayer(player_id);
+  webkit_media::WebMediaPlayerAndroid* player = GetWebMediaPlayer(player_id);
   if (player)
     player->OnMediaPlayerPause();
 }
@@ -177,13 +174,47 @@
   Send(new MediaPlayerHostMsg_ExitFullscreen(routing_id(), player_id));
 }
 
+#if defined(GOOGLE_TV)
 void WebMediaPlayerProxyImplAndroid::RequestExternalSurface(int player_id) {
   Send(new MediaPlayerHostMsg_RequestExternalSurface(routing_id(), player_id));
 }
 
-webkit_media::WebMediaPlayerImplAndroid*
+void WebMediaPlayerProxyImplAndroid::DidCommitCompositorFrame() {
+  std::map<int, gfx::RectF> geometry_change;
+  manager_->RetrieveGeometryChanges(&geometry_change);
+  for (std::map<int, gfx::RectF>::iterator it = geometry_change.begin();
+       it != geometry_change.end();
+       ++it) {
+    Send(new MediaPlayerHostMsg_NotifyGeometryChange(routing_id(),
+                                                     it->first,
+                                                     it->second));
+  }
+}
+
+void WebMediaPlayerProxyImplAndroid::DemuxerReady(
+    int player_id,
+    const media::MediaPlayerHostMsg_DemuxerReady_Params& params) {
+  Send(new MediaPlayerHostMsg_DemuxerReady(routing_id(), player_id, params));
+}
+
+void WebMediaPlayerProxyImplAndroid::ReadFromDemuxerAck(
+    int player_id,
+    const media::MediaPlayerHostMsg_ReadFromDemuxerAck_Params& params) {
+  Send(new MediaPlayerHostMsg_ReadFromDemuxerAck(
+      routing_id(), player_id, params));
+
+}
+void WebMediaPlayerProxyImplAndroid::OnReadFromDemuxer(
+    int player_id, media::DemuxerStream::Type type, bool seek_done) {
+  webkit_media::WebMediaPlayerAndroid* player = GetWebMediaPlayer(player_id);
+  if (player)
+    player->OnReadFromDemuxer(type, seek_done);
+}
+#endif
+
+webkit_media::WebMediaPlayerAndroid*
     WebMediaPlayerProxyImplAndroid::GetWebMediaPlayer(int player_id) {
-  return static_cast<webkit_media::WebMediaPlayerImplAndroid*>(
+  return static_cast<webkit_media::WebMediaPlayerAndroid*>(
       manager_->GetMediaPlayer(player_id));
 }
 
diff --git a/content/renderer/media/webmediaplayer_proxy_impl_android.h b/content/renderer/media/webmediaplayer_proxy_impl_android.h
index d8eb51d..a990459 100644
--- a/content/renderer/media/webmediaplayer_proxy_impl_android.h
+++ b/content/renderer/media/webmediaplayer_proxy_impl_android.h
@@ -11,14 +11,14 @@
 #include "webkit/media/android/webmediaplayer_proxy_android.h"
 
 namespace webkit_media {
-class WebMediaPlayerImplAndroid;
+class WebMediaPlayerAndroid;
 class WebMediaPlayerManagerAndroid;
 }
 
 namespace content {
 
 // This class manages all the IPC communications between
-// WebMediaPlayerImplAndroid and the MediaPlayerManagerAndroid in the browser
+// WebMediaPlayerAndroid and the MediaPlayerManagerAndroid in the browser
 // process.
 class WebMediaPlayerProxyImplAndroid
     : public RenderViewObserver,
@@ -26,7 +26,7 @@
  public:
   // Construct a WebMediaPlayerProxyImplAndroid object for the |render_view|.
   // |manager| is passed to this class so that it can find the right
-  // WebMediaPlayerImplAndroid using player IDs.
+  // WebMediaPlayerAndroid using player IDs.
   WebMediaPlayerProxyImplAndroid(
       RenderView* render_view,
       webkit_media::WebMediaPlayerManagerAndroid* manager);
@@ -36,6 +36,7 @@
 
   // Methods inherited from WebMediaPlayerProxyAndroid.
   virtual void Initialize(int player_id, const GURL& url,
+                          bool is_media_source,
                           const GURL& first_party_for_cookies) OVERRIDE;
   virtual void Start(int player_id) OVERRIDE;
   virtual void Pause(int player_id) OVERRIDE;
@@ -44,13 +45,25 @@
   virtual void DestroyPlayer(int player_id) OVERRIDE;
   virtual void EnterFullscreen(int player_id) OVERRIDE;
   virtual void ExitFullscreen(int player_id) OVERRIDE;
+#if defined(GOOGLE_TV)
   virtual void RequestExternalSurface(int player_id) OVERRIDE;
+  virtual void DemuxerReady(
+      int player_id,
+      const media::MediaPlayerHostMsg_DemuxerReady_Params& params) OVERRIDE;
+  virtual void ReadFromDemuxerAck(
+      int player_id,
+      const media::MediaPlayerHostMsg_ReadFromDemuxerAck_Params&) OVERRIDE;
+
+  // Methods inherited from RenderViewObserver.
+  virtual void DidCommitCompositorFrame() OVERRIDE;
+#endif
 
  private:
-  webkit_media::WebMediaPlayerImplAndroid* GetWebMediaPlayer(int player_id);
+  webkit_media::WebMediaPlayerAndroid* GetWebMediaPlayer(int player_id);
 
   // Message handlers.
-  void OnMediaPrepared(int player_id, base::TimeDelta duration);
+  void OnMediaMetadataChanged(int player_id, base::TimeDelta duration,
+                              int width, int height, bool success);
   void OnMediaPlaybackCompleted(int player_id);
   void OnMediaBufferingUpdate(int player_id, int percent);
   void OnMediaSeekCompleted(int player_id, base::TimeDelta current_time);
@@ -62,6 +75,10 @@
   void OnDidEnterFullscreen(int player_id);
   void OnPlayerPlay(int player_id);
   void OnPlayerPause(int player_id);
+#if defined(GOOGLE_TV)
+  void OnReadFromDemuxer(
+      int player_id, media::DemuxerStream::Type type, bool seek_done);
+#endif
 
   webkit_media::WebMediaPlayerManagerAndroid* manager_;
 
diff --git a/content/renderer/media/webrtc_audio_capturer.cc b/content/renderer/media/webrtc_audio_capturer.cc
index e37df57..92951e2 100644
--- a/content/renderer/media/webrtc_audio_capturer.cc
+++ b/content/renderer/media/webrtc_audio_capturer.cc
@@ -10,6 +10,7 @@
 #include "base/string_util.h"
 #include "content/common/child_process.h"
 #include "content/renderer/media/audio_device_factory.h"
+#include "content/renderer/media/webrtc_audio_capturer_sink_owner.h"
 #include "content/renderer/media/webrtc_audio_device_impl.h"
 #include "media/audio/audio_util.h"
 #include "media/audio/sample_rates.h"
@@ -65,77 +66,6 @@
   return buffer_size;
 }
 
-// Reference counted container of WebRtcAudioCapturerSink delegates.
-class WebRtcAudioCapturer::SinkOwner
-    : public base::RefCounted<WebRtcAudioCapturer::SinkOwner>,
-      public WebRtcAudioCapturerSink {
- public:
-  explicit SinkOwner(WebRtcAudioCapturerSink* sink);
-
-  virtual void CaptureData(const int16* audio_data,
-                           int number_of_channels,
-                           int number_of_frames,
-                           int audio_delay_milliseconds,
-                           double volume) OVERRIDE;
-  virtual void SetCaptureFormat(const media::AudioParameters& params) OVERRIDE;
-
-  bool IsEqual(const WebRtcAudioCapturerSink* other) const;
-  void Reset();
-
-  // Wrapper which allows to use std::find_if() when adding and removing
-  // sinks to/from the list.
-  struct WrapsSink {
-    WrapsSink(WebRtcAudioCapturerSink* sink) : sink_(sink) {}
-    bool operator()(
-        const scoped_refptr<WebRtcAudioCapturer::SinkOwner>& owner) {
-      return owner->IsEqual(sink_);
-    }
-    WebRtcAudioCapturerSink* sink_;
-  };
-
- private:
-  ~SinkOwner() {}
-
-  friend class base::RefCounted<WebRtcAudioCapturer::SinkOwner>;
-  WebRtcAudioCapturerSink* delegate_;
-  mutable base::Lock lock_;
-
-  DISALLOW_COPY_AND_ASSIGN(SinkOwner);
-};
-
-WebRtcAudioCapturer::SinkOwner::SinkOwner(
-    WebRtcAudioCapturerSink* sink)
-    : delegate_(sink) {
-}
-
-void WebRtcAudioCapturer::SinkOwner::CaptureData(
-    const int16* audio_data, int number_of_channels, int number_of_frames,
-    int audio_delay_milliseconds, double volume) {
-  base::AutoLock lock(lock_);
-  if (delegate_) {
-    delegate_->CaptureData(audio_data, number_of_channels, number_of_frames,
-                           audio_delay_milliseconds, volume);
-  }
-}
-
-void WebRtcAudioCapturer::SinkOwner::SetCaptureFormat(
-    const media::AudioParameters& params) {
-  base::AutoLock lock(lock_);
-  if (delegate_)
-    delegate_->SetCaptureFormat(params);
-}
-
-bool WebRtcAudioCapturer::SinkOwner::IsEqual(
-    const WebRtcAudioCapturerSink* other) const {
-  base::AutoLock lock(lock_);
-  return (other == delegate_);
-}
-
-void WebRtcAudioCapturer::SinkOwner::Reset() {
-  base::AutoLock lock(lock_);
-  delegate_ = NULL;
-}
-
 // This is a temporary audio buffer with parameters used to send data to
 // callbacks.
 class WebRtcAudioCapturer::ConfiguredBuffer :
@@ -179,7 +109,7 @@
 
 // static
 scoped_refptr<WebRtcAudioCapturer> WebRtcAudioCapturer::CreateCapturer() {
-  scoped_refptr<WebRtcAudioCapturer> capturer = new  WebRtcAudioCapturer();
+  scoped_refptr<WebRtcAudioCapturer> capturer = new WebRtcAudioCapturer();
   return capturer;
 }
 
@@ -189,26 +119,27 @@
   if (!new_buffer->Initialize(sample_rate, channel_layout))
     return false;
 
-  SinkList sinks;
+  TrackList tracks;
   {
     base::AutoLock auto_lock(lock_);
 
     buffer_ = new_buffer;
-    sinks = sinks_;
+    tracks = tracks_;
   }
 
-  // Tell all sinks which format we use.
-  for (SinkList::const_iterator it = sinks.begin(); it != sinks.end(); ++it)
+  // Tell all audio_tracks which format we use.
+  for (TrackList::const_iterator it = tracks.begin();
+       it != tracks.end(); ++it)
     (*it)->SetCaptureFormat(new_buffer->params());
 
   return true;
 }
 
-bool WebRtcAudioCapturer::Initialize(media::ChannelLayout channel_layout,
+bool WebRtcAudioCapturer::Initialize(int render_view_id,
+                                     media::ChannelLayout channel_layout,
                                      int sample_rate,
                                      int session_id) {
   DCHECK(thread_checker_.CalledOnValidThread());
-  DCHECK(!sinks_.empty());
   DVLOG(1) << "WebRtcAudioCapturer::Initialize()";
 
   DVLOG(1) << "Audio input hardware channel layout: " << channel_layout;
@@ -245,7 +176,7 @@
   // Create and configure the default audio capturing source. The |source_|
   // will be overwritten if an external client later calls SetCapturerSource()
   // providing an alternative media::AudioCapturerSource.
-  SetCapturerSource(AudioDeviceFactory::NewInputDevice(),
+  SetCapturerSource(AudioDeviceFactory::NewInputDevice(render_view_id),
                     channel_layout,
                     static_cast<float>(sample_rate));
 
@@ -262,39 +193,44 @@
 
 WebRtcAudioCapturer::~WebRtcAudioCapturer() {
   DCHECK(thread_checker_.CalledOnValidThread());
-  DCHECK(sinks_.empty());
+  DCHECK(tracks_.empty());
   DCHECK(!running_);
   DVLOG(1) << "WebRtcAudioCapturer::~WebRtcAudioCapturer()";
 }
 
-void WebRtcAudioCapturer::AddCapturerSink(WebRtcAudioCapturerSink* sink) {
+void WebRtcAudioCapturer::AddSink(
+    WebRtcAudioCapturerSink* track) {
   DCHECK(thread_checker_.CalledOnValidThread());
-  DVLOG(1) << "WebRtcAudioCapturer::AddCapturerSink()";
+  DVLOG(1) << "WebRtcAudioCapturer::AddSink()";
   base::AutoLock auto_lock(lock_);
-  // Verify that |sink| is not already added to the list.
+  // Verify that |track| is not already added to the list.
   DCHECK(std::find_if(
-      sinks_.begin(), sinks_.end(), SinkOwner::WrapsSink(sink)) ==
-      sinks_.end());
-  // Create (and add to the list) a new SinkOwner which owns the |sink|
-  // and delagates all calls to the WebRtcAudioCapturerSink interface.
-  sinks_.push_back(new WebRtcAudioCapturer::SinkOwner(sink));
+      tracks_.begin(), tracks_.end(),
+      WebRtcAudioCapturerSinkOwner::WrapsSink(track)) == tracks_.end());
+  // Create (and add to the list) a new WebRtcAudioCapturerSinkOwner which owns
+  // the |track| and delagates all calls to the WebRtcAudioCapturerSink
+  // interface.
+  tracks_.push_back(new WebRtcAudioCapturerSinkOwner(track));
+  // TODO(xians): should we call SetCapturerFormat() to each track?
 }
 
-void WebRtcAudioCapturer::RemoveCapturerSink(WebRtcAudioCapturerSink* sink) {
+void WebRtcAudioCapturer::RemoveSink(
+    WebRtcAudioCapturerSink* track) {
   DCHECK(thread_checker_.CalledOnValidThread());
-  DVLOG(1) << "WebRtcAudioCapturer::RemoveCapturerSink()";
+  DVLOG(1) << "WebRtcAudioCapturer::RemoveSink()";
 
   base::AutoLock auto_lock(lock_);
 
-  // Get iterator to the first element for which WrapsSink(sink) returns true.
-  SinkList::iterator it = std::find_if(sinks_.begin(), sinks_.end(),
-                                       SinkOwner::WrapsSink(sink));
-  if (it != sinks_.end()) {
+  // Get iterator to the first element for which WrapsSink(track) returns true.
+  TrackList::iterator it = std::find_if(
+      tracks_.begin(), tracks_.end(),
+      WebRtcAudioCapturerSinkOwner::WrapsSink(track));
+  if (it != tracks_.end()) {
     // Clear the delegate to ensure that no more capture callbacks will
     // be sent to this sink. Also avoids a possible crash which can happen
     // if this method is called while capturing is active.
     (*it)->Reset();
-    sinks_.erase(it);
+    tracks_.erase(it);
   }
 }
 
@@ -315,6 +251,9 @@
     source_.swap(old_source);
     source_ = source;
     current_buffer = buffer_;
+
+    // Reset the flag to allow calling Start() for the new source.
+    running_ = false;
   }
 
   const bool no_default_audio_source_exists = !current_buffer;
@@ -402,7 +341,7 @@
   // This callback is driven by AudioInputDevice::AudioThreadCallback if
   // |source_| is AudioInputDevice, otherwise it is driven by client's
   // CaptureCallback.
-  SinkList sinks;
+  TrackList tracks;
   scoped_refptr<ConfiguredBuffer> buffer_ref_while_calling;
   {
     base::AutoLock auto_lock(lock_);
@@ -413,7 +352,7 @@
     // a reference to the buffer so we can ensure it stays alive even if the
     // buffer is reconfigured while we are calling back.
     buffer_ref_while_calling = buffer_;
-    sinks = sinks_;
+    tracks = tracks_;
   }
 
   int bytes_per_sample =
@@ -424,9 +363,9 @@
   audio_source->ToInterleaved(audio_source->frames(), bytes_per_sample,
                               buffer_ref_while_calling->buffer());
 
-  // Feed the data to the sinks.
-  for (SinkList::const_iterator it = sinks.begin();
-       it != sinks.end();
+  // Feed the data to the tracks.
+  for (TrackList::const_iterator it = tracks.begin();
+       it != tracks.end();
        ++it) {
     (*it)->CaptureData(buffer_ref_while_calling->buffer(),
                        audio_source->channels(), audio_source->frames(),
diff --git a/content/renderer/media/webrtc_audio_capturer.h b/content/renderer/media/webrtc_audio_capturer.h
index 5d35604..12e0a34 100644
--- a/content/renderer/media/webrtc_audio_capturer.h
+++ b/content/renderer/media/webrtc_audio_capturer.h
@@ -23,10 +23,11 @@
 namespace content {
 
 class WebRtcAudioCapturerSink;
+class WebRtcAudioCapturerSinkOwner;
 class WebRtcLocalAudioRenderer;
 
 // This class manages the capture data flow by getting data from its
-// |source_|, and passing it to its |sink_|.
+// |source_|, and passing it to its |tracks_|.
 // It allows clients to inject their own capture data source by calling
 // SetCapturerSource().
 // The threading model for this class is rather complex since it will be
@@ -43,24 +44,24 @@
   static scoped_refptr<WebRtcAudioCapturer> CreateCapturer();
 
   // Creates and configures the default audio capturing source using the
-  // provided audio parameters, |session_id| is passed to the browser to
-  // decide which device to use.
-  // Called on the main render thread.
-  bool Initialize(media::ChannelLayout channel_layout,
+  // provided audio parameters.  |render_view_id| specifies the render view
+  // consuming audio for capture.  |session_id| is passed to the browser to
+  // decide which device to use.  Called on the main render thread.
+  bool Initialize(int render_view_id,
+                  media::ChannelLayout channel_layout,
                   int sample_rate,
                   int session_id);
 
-  // Called by the client on the sink side to add a sink.
+  // Add a audio track to the sinks of the capturer.
   // WebRtcAudioDeviceImpl calls this method on the main render thread but
   // other clients may call it from other threads. The current implementation
   // does not support multi-thread calling.
   // Called on the main render thread.
-  void AddCapturerSink(WebRtcAudioCapturerSink* sink);
+  void AddSink(WebRtcAudioCapturerSink* track);
 
-  // Called by the client on the sink side to remove a sink.
+  // Remove a audio track from the sinks of the capturer.
   // Called on the main render thread.
-  // Called on the main render thread.
-  void RemoveCapturerSink(WebRtcAudioCapturerSink* sink);
+  void RemoveSink(WebRtcAudioCapturerSink* track);
 
   // SetCapturerSource() is called if the client on the source side desires to
   // provide their own captured audio data. Client is responsible for calling
@@ -97,6 +98,14 @@
   // of this accessor and if we can remove it.
   media::AudioParameters audio_parameters() const;
 
+ protected:
+  friend class base::RefCountedThreadSafe<WebRtcAudioCapturer>;
+  WebRtcAudioCapturer();
+  virtual ~WebRtcAudioCapturer();
+
+ private:
+  typedef std::list<scoped_refptr<WebRtcAudioCapturerSinkOwner> > TrackList;
+
   // AudioCapturerSource::CaptureCallback implementation.
   // Called on the AudioInputDevice audio thread.
   virtual void Capture(media::AudioBus* audio_source,
@@ -104,16 +113,6 @@
                        double volume) OVERRIDE;
   virtual void OnCaptureError() OVERRIDE;
 
- protected:
-  friend class base::RefCountedThreadSafe<WebRtcAudioCapturer>;
-  virtual ~WebRtcAudioCapturer();
-
- private:
-  class SinkOwner;
-  typedef std::list<scoped_refptr<SinkOwner> > SinkList;
-
-  WebRtcAudioCapturer();
-
   // Reconfigures the capturer with a new buffer size and capture parameters.
   // Must be called without holding the lock. Returns true on success.
   bool Reconfigure(int sample_rate, media::ChannelLayout channel_layout);
@@ -121,12 +120,12 @@
   // Used to DCHECK that we are called on the correct thread.
   base::ThreadChecker thread_checker_;
 
-  // Protects |source_|, |sinks_|, |running_|, |loopback_fifo_|, |params_|,
-  // |buffering_| and |agc_is_enabled_|.
+  // Protects |source_|, |audio_tracks_|, |running_|, |loopback_fifo_|,
+  // |params_|, |buffering_| and |agc_is_enabled_|.
   mutable base::Lock lock_;
 
-  // A list of sinks that the audio data is fed to.
-  SinkList sinks_;
+  // A list of audio tracks that the audio data is fed to.
+  TrackList tracks_;
 
   // The audio data source from the browser process.
   scoped_refptr<media::AudioCapturerSource> source_;
diff --git a/content/renderer/media/webrtc_audio_capturer_sink_owner.cc b/content/renderer/media/webrtc_audio_capturer_sink_owner.cc
new file mode 100644
index 0000000..ab0c3d3
--- /dev/null
+++ b/content/renderer/media/webrtc_audio_capturer_sink_owner.cc
@@ -0,0 +1,42 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/media/webrtc_audio_capturer_sink_owner.h"
+
+namespace content {
+
+WebRtcAudioCapturerSinkOwner::WebRtcAudioCapturerSinkOwner(
+    WebRtcAudioCapturerSink* sink)
+    : delegate_(sink) {
+}
+
+void WebRtcAudioCapturerSinkOwner::CaptureData(
+    const int16* audio_data, int number_of_channels, int number_of_frames,
+    int audio_delay_milliseconds, double volume) {
+  base::AutoLock lock(lock_);
+  if (delegate_) {
+    delegate_->CaptureData(audio_data, number_of_channels, number_of_frames,
+                           audio_delay_milliseconds, volume);
+  }
+}
+
+void WebRtcAudioCapturerSinkOwner::SetCaptureFormat(
+    const media::AudioParameters& params) {
+  base::AutoLock lock(lock_);
+  if (delegate_)
+    delegate_->SetCaptureFormat(params);
+}
+
+bool WebRtcAudioCapturerSinkOwner::IsEqual(
+    const WebRtcAudioCapturerSink* other) const {
+  base::AutoLock lock(lock_);
+  return (other == delegate_);
+}
+
+void WebRtcAudioCapturerSinkOwner::Reset() {
+  base::AutoLock lock(lock_);
+  delegate_ = NULL;
+}
+
+}  // namespace content
diff --git a/content/renderer/media/webrtc_audio_capturer_sink_owner.h b/content/renderer/media/webrtc_audio_capturer_sink_owner.h
new file mode 100644
index 0000000..dd6264f
--- /dev/null
+++ b/content/renderer/media/webrtc_audio_capturer_sink_owner.h
@@ -0,0 +1,61 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_RENDERER_MEDIA_WEBRTC_AUDIO_CAPTURER_SINK_OWNER_H_
+#define CONTENT_RENDERER_MEDIA_WEBRTC_AUDIO_CAPTURER_SINK_OWNER_H_
+
+#include <list>
+
+#include "base/memory/ref_counted.h"
+#include "base/synchronization/lock.h"
+#include "content/renderer/media/webrtc_audio_device_impl.h"
+#include "media/audio/audio_parameters.h"
+
+namespace content {
+
+class WebRtcAudioCapturerSink;
+
+// Reference counted container of WebRtcAudioCapturerSink delegates.
+class WebRtcAudioCapturerSinkOwner
+    : public base::RefCountedThreadSafe<WebRtcAudioCapturerSinkOwner>,
+      public WebRtcAudioCapturerSink {
+ public:
+  explicit WebRtcAudioCapturerSinkOwner(WebRtcAudioCapturerSink* sink);
+
+  // WebRtcAudioCapturerSink implementation.
+  virtual void CaptureData(const int16* audio_data,
+                           int number_of_channels,
+                           int number_of_frames,
+                           int audio_delay_milliseconds,
+                           double volume) OVERRIDE;
+  virtual void SetCaptureFormat(const media::AudioParameters& params) OVERRIDE;
+
+  bool IsEqual(const WebRtcAudioCapturerSink* other) const;
+  void Reset();
+
+  // Wrapper which allows to use std::find_if() when adding and removing
+  // sinks to/from the list.
+  struct WrapsSink {
+    WrapsSink(WebRtcAudioCapturerSink* sink) : sink_(sink) {}
+    bool operator()(
+        const scoped_refptr<WebRtcAudioCapturerSinkOwner>& owner) {
+      return owner->IsEqual(sink_);
+    }
+    WebRtcAudioCapturerSink* sink_;
+  };
+
+ protected:
+  virtual ~WebRtcAudioCapturerSinkOwner() {}
+
+ private:
+  friend class base::RefCountedThreadSafe<WebRtcAudioCapturerSinkOwner>;
+  WebRtcAudioCapturerSink* delegate_;
+  mutable base::Lock lock_;
+
+  DISALLOW_COPY_AND_ASSIGN(WebRtcAudioCapturerSinkOwner);
+};
+
+}  // namespace content
+
+#endif  // CONTENT_RENDERER_MEDIA_WEBRTC_AUDIO_CAPTURER_SINK_OWNER_H_
diff --git a/content/renderer/media/webrtc_audio_device_impl.cc b/content/renderer/media/webrtc_audio_device_impl.cc
index 11091a6..f2763ca 100644
--- a/content/renderer/media/webrtc_audio_device_impl.cc
+++ b/content/renderer/media/webrtc_audio_device_impl.cc
@@ -226,8 +226,13 @@
 
   DCHECK(!capturer_);
   capturer_ = WebRtcAudioCapturer::CreateCapturer();
+  // Add itself as an audio track to the |capturer_|. This is because WebRTC
+  // supports only one ADM but multiple audio tracks, so the ADM can't be the
+  // sink of certain audio track now.
+  // TODO(xians): Register the ADM as the sink of the audio track if WebRTC
+  // supports one ADM for each audio track.
   if (capturer_)
-    capturer_->AddCapturerSink(this);
+    capturer_->AddSink(this);
 
   // We need to return a success to continue the initialization of WebRtc VoE
   // because failure on the capturer_ initialization should not prevent WebRTC
@@ -257,7 +262,7 @@
   if (capturer_) {
     // |capturer_| is stopped by the media stream, so do not need to
     // call Stop() here.
-    capturer_->RemoveCapturerSink(this);
+    capturer_->RemoveSink(this);
     capturer_ = NULL;
   }
 
diff --git a/content/renderer/media/webrtc_audio_device_impl.h b/content/renderer/media/webrtc_audio_device_impl.h
index e53bd09..56d256b 100644
--- a/content/renderer/media/webrtc_audio_device_impl.h
+++ b/content/renderer/media/webrtc_audio_device_impl.h
@@ -237,30 +237,6 @@
   virtual int32_t AddRef() OVERRIDE;
   virtual int32_t Release() OVERRIDE;
 
-  // WebRtcAudioCapturerSink implementation.
-
-  // Called on the AudioInputDevice worker thread.
-  virtual void CaptureData(const int16* audio_data,
-                           int number_of_channels,
-                           int number_of_frames,
-                           int audio_delay_milliseconds,
-                           double volume) OVERRIDE;
-
-  // Called on the main render thread.
-  virtual void SetCaptureFormat(const media::AudioParameters& params) OVERRIDE;
-
-  // WebRtcAudioRendererSource implementation.
-
-  // Called on the AudioInputDevice worker thread.
-  virtual void RenderData(uint8* audio_data,
-                          int number_of_channels,
-                          int number_of_frames,
-                          int audio_delay_milliseconds) OVERRIDE;
-
-  // Called on the main render thread.
-  virtual void SetRenderFormat(const media::AudioParameters& params) OVERRIDE;
-  virtual void RemoveAudioRenderer(WebRtcAudioRenderer* renderer) OVERRIDE;
-
   // webrtc::AudioDeviceModule implementation.
   // All implemented methods are called on the main render thread unless
   // anything else is stated.
@@ -338,6 +314,30 @@
   // Make destructor private to ensure that we can only be deleted by Release().
   virtual ~WebRtcAudioDeviceImpl();
 
+  // WebRtcAudioCapturerSink implementation.
+
+  // Called on the AudioInputDevice worker thread.
+  virtual void CaptureData(const int16* audio_data,
+                           int number_of_channels,
+                           int number_of_frames,
+                           int audio_delay_milliseconds,
+                           double volume) OVERRIDE;
+
+  // Called on the main render thread.
+  virtual void SetCaptureFormat(const media::AudioParameters& params) OVERRIDE;
+
+  // WebRtcAudioRendererSource implementation.
+
+  // Called on the AudioInputDevice worker thread.
+  virtual void RenderData(uint8* audio_data,
+                          int number_of_channels,
+                          int number_of_frames,
+                          int audio_delay_milliseconds) OVERRIDE;
+
+  // Called on the main render thread.
+  virtual void SetRenderFormat(const media::AudioParameters& params) OVERRIDE;
+  virtual void RemoveAudioRenderer(WebRtcAudioRenderer* renderer) OVERRIDE;
+
   // Used to DCHECK that we are called on the correct thread.
   base::ThreadChecker thread_checker_;
 
diff --git a/content/renderer/media/webrtc_audio_device_unittest.cc b/content/renderer/media/webrtc_audio_device_unittest.cc
index 73c95fe..cc34bb2 100644
--- a/content/renderer/media/webrtc_audio_device_unittest.cc
+++ b/content/renderer/media/webrtc_audio_device_unittest.cc
@@ -18,6 +18,10 @@
 #include "third_party/webrtc/voice_engine/include/voe_file.h"
 #include "third_party/webrtc/voice_engine/include/voe_network.h"
 
+#if defined(OS_WIN)
+#include "base/win/windows_version.h"
+#endif
+
 using media::AudioParameters;
 using testing::_;
 using testing::AnyNumber;
@@ -100,7 +104,7 @@
   int sample_rate = hardware_config->GetInputSampleRate();
   media::ChannelLayout channel_layout =
       hardware_config->GetInputChannelLayout();
-  if (!capturer->Initialize(channel_layout, sample_rate, 1))
+  if (!capturer->Initialize(kRenderViewId, channel_layout, sample_rate, 1))
     return false;
 
   return true;
@@ -122,7 +126,7 @@
   // TODO(henrika): Refactor in WebRTC and convert to Chrome coding style.
   virtual void Process(const int channel,
                        const webrtc::ProcessingTypes type,
-                       WebRtc_Word16 audio_10ms[],
+                       int16_t audio_10ms[],
                        const int length,
                        const int sampling_freq,
                        const bool is_stereo) OVERRIDE {
@@ -216,6 +220,12 @@
 // Basic test that instantiates and initializes an instance of
 // WebRtcAudioDeviceImpl.
 TEST_F(WebRTCAudioDeviceTest, Construct) {
+#if defined(OS_WIN)
+  // This test crashes on Win XP bots.
+  if (base::win::GetVersion() <= base::win::VERSION_XP)
+    return;
+#endif
+
   AudioParameters input_params(
       AudioParameters::AUDIO_PCM_LOW_LATENCY,
       media::CHANNEL_LAYOUT_MONO,
@@ -473,7 +483,7 @@
 
   // Play 2 seconds worth of audio and then quit.
   message_loop_.PostDelayedTask(FROM_HERE,
-                                MessageLoop::QuitClosure(),
+                                base::MessageLoop::QuitClosure(),
                                 base::TimeDelta::FromSeconds(6));
   message_loop_.Run();
 
@@ -567,7 +577,7 @@
 
   LOG(INFO) << ">> You should now be able to hear yourself in loopback...";
   message_loop_.PostDelayedTask(FROM_HERE,
-                                MessageLoop::QuitClosure(),
+                                base::MessageLoop::QuitClosure(),
                                 base::TimeDelta::FromSeconds(2));
   message_loop_.Run();
 
diff --git a/content/renderer/media/webrtc_audio_renderer.cc b/content/renderer/media/webrtc_audio_renderer.cc
index d5591d0..c85b2df 100644
--- a/content/renderer/media/webrtc_audio_renderer.cc
+++ b/content/renderer/media/webrtc_audio_renderer.cc
@@ -8,9 +8,9 @@
 #include "base/metrics/histogram.h"
 #include "base/string_util.h"
 #include "content/renderer/media/audio_device_factory.h"
-#include "content/renderer/media/renderer_audio_output_device.h"
 #include "content/renderer/media/webrtc_audio_device_impl.h"
 #include "content/renderer/render_thread_impl.h"
+#include "media/audio/audio_output_device.h"
 #include "media/audio/audio_parameters.h"
 #include "media/audio/sample_rates.h"
 #include "media/base/audio_hardware_config.h"
@@ -111,9 +111,6 @@
   DCHECK(!sink_);
   DCHECK(!source_);
 
-  sink_ = AudioDeviceFactory::NewOutputDevice();
-  DCHECK(sink_);
-
   // Use mono on all platforms but Windows for now.
   // TODO(henrika): Tracking at http://crbug.com/166771.
   media::ChannelLayout channel_layout = media::CHANNEL_LAYOUT_MONO;
@@ -126,6 +123,17 @@
       RenderThreadImpl::current()->GetAudioHardwareConfig();
   int sample_rate = hardware_config->GetOutputSampleRate();
   DVLOG(1) << "Audio output hardware sample rate: " << sample_rate;
+
+  // WebRTC does not yet support higher rates than 96000 on the client side
+  // and 48000 is the preferred sample rate. Therefore, if 192000 is detected,
+  // we change the rate to 48000 instead. The consequence is that the native
+  // layer will be opened up at 192kHz but WebRTC will provide data at 48kHz
+  // which will then be resampled by the audio converted on the browser side
+  // to match the native audio layer.
+  if (sample_rate == 192000) {
+    DVLOG(1) << "Resampling from 48000 to 192000 is required";
+    sample_rate = 48000;
+  }
   UMA_HISTOGRAM_ENUMERATION("WebRTC.AudioOutputSampleRate",
                             sample_rate, media::kUnexpectedAudioSampleRate);
 
@@ -208,8 +216,8 @@
   source->SetRenderFormat(source_params);
 
   // Configure the audio rendering client and start rendering.
+  sink_ = AudioDeviceFactory::NewOutputDevice(source_render_view_id_);
   sink_->Initialize(sink_params, this);
-  sink_->SetSourceRenderView(source_render_view_id_);
   sink_->Start();
 
   // User must call Play() before any audio can be heard.
diff --git a/content/renderer/media/webrtc_audio_renderer.h b/content/renderer/media/webrtc_audio_renderer.h
index e0b19c7..eb10256 100644
--- a/content/renderer/media/webrtc_audio_renderer.h
+++ b/content/renderer/media/webrtc_audio_renderer.h
@@ -14,9 +14,12 @@
 #include "media/base/audio_renderer_sink.h"
 #include "webkit/media/media_stream_audio_renderer.h"
 
+namespace media {
+class AudioOutputDevice;
+}
+
 namespace content {
 
-class RendererAudioOutputDevice;
 class WebRtcAudioRendererSource;
 
 // This renderer handles calls from the pipeline and WebRtc ADM. It is used
@@ -71,14 +74,14 @@
   const int source_render_view_id_;
 
   // The sink (destination) for rendered audio.
-  scoped_refptr<RendererAudioOutputDevice> sink_;
+  scoped_refptr<media::AudioOutputDevice> sink_;
 
   // Audio data source from the browser process.
   WebRtcAudioRendererSource* source_;
 
   // Buffers used for temporary storage during render callbacks.
   // Allocated during initialization.
-  scoped_array<int16> buffer_;
+  scoped_ptr<int16[]> buffer_;
 
   // Protects access to |state_|, |source_| and |sink_|.
   base::Lock lock_;
diff --git a/content/renderer/media/webrtc_local_audio_renderer.cc b/content/renderer/media/webrtc_local_audio_renderer.cc
index cc5ba77..3689754 100644
--- a/content/renderer/media/webrtc_local_audio_renderer.cc
+++ b/content/renderer/media/webrtc_local_audio_renderer.cc
@@ -9,8 +9,8 @@
 #include "base/message_loop_proxy.h"
 #include "base/synchronization/lock.h"
 #include "content/renderer/media/audio_device_factory.h"
-#include "content/renderer/media/renderer_audio_output_device.h"
 #include "content/renderer/media/webrtc_audio_capturer.h"
+#include "media/audio/audio_output_device.h"
 #include "media/base/audio_bus.h"
 
 namespace content {
@@ -60,12 +60,11 @@
   TRACE_EVENT0("audio", "WebRtcLocalAudioRenderer::CaptureData");
   base::AutoLock auto_lock(thread_lock_);
 
-  if (!playing_ || !track_is_enabled_) {
+  if (!playing_)
     return;
-  }
 
   // Push captured audio to FIFO so it can be read by a local sink.
-  if (loopback_fifo_ && track_is_enabled_) {
+  if (loopback_fifo_) {
     if (loopback_fifo_->frames() + number_of_frames <=
         loopback_fifo_->max_frames()) {
       scoped_ptr<media::AudioBus> audio_source = media::AudioBus::Create(
@@ -82,27 +81,17 @@
 
 void WebRtcLocalAudioRenderer::SetCaptureFormat(
     const media::AudioParameters& params) {
-  NOTIMPLEMENTED() << "WebRtcLocalAudioRenderer::SetCaptureFormat()";
-}
-
-// webrtc::ObserverInterface implementation
-void WebRtcLocalAudioRenderer::OnChanged() {
-  DVLOG(1) << "WebRtcLocalAudioRenderer::OnChanged()";
-  DCHECK(thread_checker_.CalledOnValidThread());
-  base::AutoLock auto_lock(thread_lock_);
-  track_is_enabled_ = audio_track_->enabled();
+  audio_params_ = params;
 }
 
 // WebRtcLocalAudioRenderer::WebRtcLocalAudioRenderer implementation.
 WebRtcLocalAudioRenderer::WebRtcLocalAudioRenderer(
-    const scoped_refptr<WebRtcAudioCapturer>& source,
-    webrtc::AudioTrackInterface* audio_track,
+    WebRtcLocalAudioTrack* audio_track,
     int source_render_view_id)
-    : source_(source),
-      audio_track_(audio_track),
+    : audio_track_(audio_track),
       source_render_view_id_(source_render_view_id),
-      playing_(false),
-      track_is_enabled_(true) {
+      playing_(false) {
+  DCHECK(audio_track);
   DVLOG(1) << "WebRtcLocalAudioRenderer::WebRtcLocalAudioRenderer()";
 }
 
@@ -115,31 +104,14 @@
 void WebRtcLocalAudioRenderer::Start() {
   DVLOG(1) << "WebRtcLocalAudioRenderer::Start()";
   DCHECK(thread_checker_.CalledOnValidThread());
-  DCHECK(source_);
-
-  if (audio_track_) {
-    audio_track_->RegisterObserver(this);
-    track_is_enabled_ = audio_track_->enabled();
-  }
+  // Add this class as sink to the audio track to ensure that we receive
+  // WebRtcAudioCapturerSink::CaptureData() callbacks for captured audio.
+  // |audio_params_| will be updated right after the AddCapturerAudioTrack().
+  audio_track_->AddSink(this);
 
   base::AutoLock auto_lock(thread_lock_);
   DCHECK(!sink_);
 
-  // Add this class as sink to the capturer to ensure that we receive
-  // WebRtcAudioCapturerSink::CaptureData() callbacks for captured audio.
-  source_->AddCapturerSink(this);
-
-  // Use the capturing source audio parameters when opening the output audio
-  // device. Any mismatch will be compensated for by the audio output back-end.
-  // Note that the buffer size is modified to make the full-duplex scheme less
-  // resource intensive. By doubling the buffer size (compared to the capture
-  // side), the callback frequency of browser side callbacks will be lower and
-  // tests have shown that it resolves issues with audio glitches for some
-  // cases where resampling is needed on the output side.
-  // TODO(henrika): verify this scheme on as many different devices and
-  // combinations of sample rates as possible
-  media::AudioParameters source_params = source_->audio_parameters();
-
   // TODO(henrika): we could add a more dynamic solution here but I prefer
   // a fixed size combined with bad audio at overflow. The alternative is
   // that we start to build up latency and that can be more difficult to
@@ -150,24 +122,22 @@
   // the FIFO overflows.
   DCHECK(!loopback_fifo_);
   loopback_fifo_.reset(new media::AudioFifo(
-      source_params.channels(),
-      10 * source_params.frames_per_buffer()));
+      audio_params_.channels(), 10 * audio_params_.frames_per_buffer()));
 
-  media::AudioParameters sink_params(source_params.format(),
-                                     source_params.channel_layout(),
-                                     source_params.sample_rate(),
-                                     source_params.bits_per_sample(),
-                                     2 * source_params.frames_per_buffer());
-  sink_ = AudioDeviceFactory::NewOutputDevice();
+  media::AudioParameters sink_params(audio_params_.format(),
+                                     audio_params_.channel_layout(),
+                                     audio_params_.sample_rate(),
+                                     audio_params_.bits_per_sample(),
+                                     2 * audio_params_.frames_per_buffer());
+  sink_ = AudioDeviceFactory::NewOutputDevice(source_render_view_id_);
+
   // TODO(henrika): we could utilize the unified audio here instead and do
   // sink_->InitializeIO(sink_params, 2, callback_.get());
   // It would then be possible to avoid using the WebRtcAudioCapturer.
   sink_->Initialize(sink_params, this);
-  sink_->SetSourceRenderView(source_render_view_id_);
 
   // Start the capturer and local rendering. Note that, the capturer is owned
   // by the WebRTC ADM and might already bee running.
-  source_->Start();
   sink_->Start();
 
   last_render_time_ = base::Time::Now();
@@ -198,13 +168,8 @@
   // Ensure that the capturer stops feeding us with captured audio.
   // Note that, we do not stop the capturer here since it may still be used by
   // the WebRTC ADM.
-  source_->RemoveCapturerSink(this);
-  source_ = NULL;
-
-  if (audio_track_) {
-    audio_track_->UnregisterObserver(this);
-    audio_track_ = NULL;
-  }
+  audio_track_->RemoveSink(this);
+  audio_track_ = NULL;
 }
 
 void WebRtcLocalAudioRenderer::Play() {
diff --git a/content/renderer/media/webrtc_local_audio_renderer.h b/content/renderer/media/webrtc_local_audio_renderer.h
index 0bd310a..15d5116 100644
--- a/content/renderer/media/webrtc_local_audio_renderer.h
+++ b/content/renderer/media/webrtc_local_audio_renderer.h
@@ -11,28 +11,24 @@
 #include "base/threading/thread_checker.h"
 #include "content/common/content_export.h"
 #include "content/renderer/media/webrtc_audio_device_impl.h"
-#include "third_party/libjingle/source/talk/app/webrtc/mediastreaminterface.h"
+#include "content/renderer/media/webrtc_local_audio_track.h"
 #include "webkit/media/media_stream_audio_renderer.h"
 
 namespace media {
 class AudioBus;
+class AudioOutputDevice;
 class AudioParameters;
 }
 
-namespace webrtc {
-class AudioTrackInterface;
-}
-
 namespace content {
 
-class RendererAudioOutputDevice;
 class WebRtcAudioCapturer;
 
 // WebRtcLocalAudioRenderer is a webkit_media::MediaStreamAudioRenderer
 // designed for rendering local audio media stream tracks,
 // http://dev.w3.org/2011/webrtc/editor/getusermedia.html#mediastreamtrack
 // It also implements media::AudioRendererSink::RenderCallback to render audio
-// data provided from a WebRtcAudioCapturer source which is set at construction.
+// data provided from a WebRtcLocalAudioTrack source.
 // When the audio layer in the browser process asks for data to render, this
 // class provides the data by implementing the WebRtcAudioCapturerSink
 // interface, i.e., we are a sink seen from the WebRtcAudioCapturer perspective.
@@ -43,14 +39,12 @@
 class CONTENT_EXPORT WebRtcLocalAudioRenderer
     : NON_EXPORTED_BASE(public webkit_media::MediaStreamAudioRenderer),
       NON_EXPORTED_BASE(public media::AudioRendererSink::RenderCallback),
-      NON_EXPORTED_BASE(public WebRtcAudioCapturerSink),
-      NON_EXPORTED_BASE(public webrtc::ObserverInterface) {
+      NON_EXPORTED_BASE(public WebRtcAudioCapturerSink) {
  public:
   // Creates a local renderer and registers a capturing |source| object.
   // The |source| is owned by the WebRtcAudioDeviceImpl.
   // Called on the main thread.
-  WebRtcLocalAudioRenderer(const scoped_refptr<WebRtcAudioCapturer>& source,
-                           webrtc::AudioTrackInterface* audio_track,
+  WebRtcLocalAudioRenderer(WebRtcLocalAudioTrack* audio_track,
                            int source_render_view_id);
 
   // webkit_media::MediaStreamAudioRenderer implementation.
@@ -63,6 +57,14 @@
   virtual base::TimeDelta GetCurrentRenderTime() const OVERRIDE;
   virtual bool IsLocalRenderer() const OVERRIDE;
 
+  const base::TimeDelta& total_render_time() const {
+    return total_render_time_;
+  }
+
+ protected:
+  virtual ~WebRtcLocalAudioRenderer();
+
+ private:
   // content::WebRtcAudioCapturerSink implementation.
 
   // Called on the AudioInputDevice worker thread.
@@ -82,30 +84,19 @@
                      int audio_delay_milliseconds) OVERRIDE;
   virtual void OnRenderError() OVERRIDE;
 
-  // webrtc::ObserverInterface implementation.
-  // Called on the main render thread.
-  virtual void OnChanged() OVERRIDE;
-
-  base::TimeDelta total_render_time() const { return total_render_time_; }
-
- protected:
-  virtual ~WebRtcLocalAudioRenderer();
-
- private:
-  // The source of data to render. Given that this class implements local
-  // loopback, the source is a capture instance reading data from the
-  // selected microphone. The recorded data is stored in a FIFO and consumed
+  // The audio track which provides data to render. Given that this class
+  // implements local loopback, the audio track is getting data from a capture
+  // instance like a selected microphone and forwards the recorded data to its
+  // sinks. The recorded data is stored in a FIFO and consumed
   // by this class when the sink asks for new data.
   // The WebRtcAudioCapturer is today created by WebRtcAudioDeviceImpl.
-  scoped_refptr<WebRtcAudioCapturer> source_;
-
-  scoped_refptr<webrtc::AudioTrackInterface> audio_track_;
+  scoped_refptr<WebRtcLocalAudioTrack> audio_track_;
 
   // The render view in which the audio is rendered into |sink_|.
   const int source_render_view_id_;
 
   // The sink (destination) for rendered audio.
-  scoped_refptr<RendererAudioOutputDevice> sink_;
+  scoped_refptr<media::AudioOutputDevice> sink_;
 
   // Used to DCHECK that we are called on the correct thread.
   base::ThreadChecker thread_checker_;
@@ -121,12 +112,12 @@
   // Keeps track of total time audio has been rendered.
   base::TimeDelta total_render_time_;
 
+  // The audio parameters used by the renderer.
+  media::AudioParameters audio_params_;
+
   // Set when playing, cleared when paused.
   bool playing_;
 
-  // Stores latest media track state for the enabled attribute.
-  bool track_is_enabled_;
-
   // Protects |loopback_fifo_|, |playing_| and |sink_|.
   mutable base::Lock thread_lock_;
 
diff --git a/content/renderer/media/webrtc_local_audio_track.cc b/content/renderer/media/webrtc_local_audio_track.cc
new file mode 100644
index 0000000..b277cad
--- /dev/null
+++ b/content/renderer/media/webrtc_local_audio_track.cc
@@ -0,0 +1,123 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/media/webrtc_local_audio_track.h"
+
+#include "content/renderer/media/webrtc_audio_capturer.h"
+#include "content/renderer/media/webrtc_audio_capturer_sink_owner.h"
+
+namespace content {
+
+static const char kAudioTrackKind[] = "audio";
+
+scoped_refptr<WebRtcLocalAudioTrack> WebRtcLocalAudioTrack::Create(
+    const std::string& id,
+    const scoped_refptr<WebRtcAudioCapturer>& capturer,
+    webrtc::AudioSourceInterface* track_source) {
+  talk_base::RefCountedObject<WebRtcLocalAudioTrack>* track =
+      new talk_base::RefCountedObject<WebRtcLocalAudioTrack>(
+          id, capturer, track_source);
+  return track;
+}
+
+WebRtcLocalAudioTrack::WebRtcLocalAudioTrack(
+    const std::string& label,
+    const scoped_refptr<WebRtcAudioCapturer>& capturer,
+    webrtc::AudioSourceInterface* track_source)
+    : webrtc::MediaStreamTrack<webrtc::AudioTrackInterface>(label),
+      capturer_(capturer),
+      track_source_(track_source) {
+  DCHECK(capturer);
+  capturer_->AddSink(this);
+  params_ = capturer_->audio_parameters();
+  DVLOG(1) << "WebRtcLocalAudioTrack::WebRtcLocalAudioTrack()";
+}
+
+WebRtcLocalAudioTrack::~WebRtcLocalAudioTrack() {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK(sinks_.empty());
+  capturer_->RemoveSink(this);
+  DVLOG(1) << "WebRtcLocalAudioTrack::~WebRtcLocalAudioTrack()";
+}
+
+// Content::WebRtcAudioCapturerSink implementation.
+void WebRtcLocalAudioTrack::CaptureData(const int16* audio_data,
+                                        int number_of_channels,
+                                        int number_of_frames,
+                                        int audio_delay_milliseconds,
+                                        double volume) {
+  SinkList sinks;
+  {
+    base::AutoLock auto_lock(lock_);
+    // When the track is diabled, we simply return here.
+    // TODO(xians): Figure out if we should feed zero to sinks instead, in
+    // order to inject VAD data in such case.
+    if (!enabled())
+      return;
+
+    sinks = sinks_;
+  }
+
+  // Feed the data to the sinks.
+  for (SinkList::const_iterator it = sinks.begin();
+       it != sinks.end();
+       ++it) {
+    (*it)->CaptureData(audio_data, number_of_channels, number_of_frames,
+                       audio_delay_milliseconds, volume);
+  }
+}
+
+void WebRtcLocalAudioTrack::SetCaptureFormat(
+    const media::AudioParameters& params) {
+  base::AutoLock auto_lock(lock_);
+  params_ = params;
+}
+
+// webrtc::AudioTrackInterface implementation.
+webrtc::AudioSourceInterface* WebRtcLocalAudioTrack::GetSource() const {
+  return track_source_;
+}
+
+std::string WebRtcLocalAudioTrack::kind() const {
+  return kAudioTrackKind;
+}
+
+void WebRtcLocalAudioTrack::AddSink(WebRtcAudioCapturerSink* sink) {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  DVLOG(1) << "WebRtcLocalAudioTrack::AddSink()";
+  base::AutoLock auto_lock(lock_);
+  sink->SetCaptureFormat(params_);
+
+  // Verify that |sink| is not already added to the list.
+  DCHECK(std::find_if(
+      sinks_.begin(), sinks_.end(),
+      WebRtcAudioCapturerSinkOwner::WrapsSink(sink)) == sinks_.end());
+
+  // Create (and add to the list) a new WebRtcAudioCapturerSinkOwner which owns
+  // the |sink| and delagates all calls to the WebRtcAudioCapturerSink
+  // interface.
+  sinks_.push_back(new WebRtcAudioCapturerSinkOwner(sink));
+}
+
+void WebRtcLocalAudioTrack::RemoveSink(
+    WebRtcAudioCapturerSink* sink) {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  DVLOG(1) << "WebRtcLocalAudioTrack::RemoveSink()";
+
+  base::AutoLock auto_lock(lock_);
+
+  // Get iterator to the first element for which WrapsSink(sink) returns true.
+  SinkList::iterator it = std::find_if(
+      sinks_.begin(), sinks_.end(),
+      WebRtcAudioCapturerSinkOwner::WrapsSink(sink));
+  if (it != sinks_.end()) {
+    // Clear the delegate to ensure that no more capture callbacks will
+    // be sent to this sink. Also avoids a possible crash which can happen
+    // if this method is called while capturing is active.
+    (*it)->Reset();
+    sinks_.erase(it);
+  }
+}
+
+}  // namespace content
diff --git a/content/renderer/media/webrtc_local_audio_track.h b/content/renderer/media/webrtc_local_audio_track.h
new file mode 100644
index 0000000..660d696
--- /dev/null
+++ b/content/renderer/media/webrtc_local_audio_track.h
@@ -0,0 +1,98 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_RENDERER_MEDIA_WEBRTC_LOCAL_AUDIO_TRACK_H_
+#define CONTENT_RENDERER_MEDIA_WEBRTC_LOCAL_AUDIO_TRACK_H_
+
+#include <list>
+#include <string>
+
+#include "base/synchronization/lock.h"
+#include "base/threading/thread_checker.h"
+#include "content/renderer/media/webrtc_audio_device_impl.h"
+#include "third_party/libjingle/source/talk/app/webrtc/mediastreaminterface.h"
+#include "third_party/libjingle/source/talk/app/webrtc/mediastreamtrack.h"
+
+
+namespace content {
+
+class WebRtcAudioCapturer;
+class WebRtcAudioCapturerSinkOwner;
+
+// A WebRtcLocalAudioTrack instance contains the implementations of
+// MediaStreamTrack and WebRtcAudioCapturerSink.
+// When an instance is created, it will register itself as a track to the
+// WebRtcAudioCapturer to get the captured data, and forward the data to
+// its |sinks_|. The data flow can be stopped by disabling the audio track.
+class CONTENT_EXPORT WebRtcLocalAudioTrack
+    : NON_EXPORTED_BASE(public WebRtcAudioCapturerSink),
+      NON_EXPORTED_BASE(
+          public webrtc::MediaStreamTrack<webrtc::AudioTrackInterface>) {
+ public:
+  static scoped_refptr<WebRtcLocalAudioTrack> Create(
+      const std::string& id,
+      const scoped_refptr<WebRtcAudioCapturer>& capturer,
+      webrtc::AudioSourceInterface* stream_source);
+
+  // Add a sink to the track. This function will trigger a SetCaptureFormat()
+  // call on the |sink|.
+  // Called on the main render thread.
+  void AddSink(WebRtcAudioCapturerSink* sink);
+
+  // Remove a sink from the track.
+  // Called on the main render thread.
+  void RemoveSink(WebRtcAudioCapturerSink* sink);
+
+ protected:
+  WebRtcLocalAudioTrack(const std::string& label,
+                        const scoped_refptr<WebRtcAudioCapturer>& capturer,
+                        webrtc::AudioSourceInterface* stream_source);
+  virtual ~WebRtcLocalAudioTrack();
+
+ private:
+  typedef std::list<scoped_refptr<WebRtcAudioCapturerSinkOwner> > SinkList;
+
+  // content::WebRtcAudioCapturerSink implementation.
+  // Called on the AudioInputDevice worker thread.
+  virtual void CaptureData(const int16* audio_data,
+                           int number_of_channels,
+                           int number_of_frames,
+                           int audio_delay_milliseconds,
+                           double volume) OVERRIDE;
+
+  // Can be called on different user threads.
+  virtual void SetCaptureFormat(const media::AudioParameters& params) OVERRIDE;
+
+  // webrtc::AudioTrackInterface implementation.
+  virtual webrtc::AudioSourceInterface* GetSource() const OVERRIDE;
+
+  // webrtc::MediaStreamTrack implementation.
+  virtual std::string kind() const OVERRIDE;
+
+  // The provider of captured data to render.
+  // The WebRtcAudioCapturer is today created by WebRtcAudioDeviceImpl.
+  scoped_refptr<WebRtcAudioCapturer> capturer_;
+
+  // The source of the audio track which handles the audio constraints.
+  // TODO(xians): merge |track_source_| to |capturer_|.
+  talk_base::scoped_refptr<webrtc::AudioSourceInterface> track_source_;
+
+  // A list of sinks that the audio data is fed to.
+  SinkList sinks_;
+
+  // Used to DCHECK that we are called on the correct thread.
+  base::ThreadChecker thread_checker_;
+
+  // Cached values of the audio parameters used by the |source_| and |sinks_|.
+  media::AudioParameters params_;
+
+  // Protects |params_| and |sinks_|.
+  mutable base::Lock lock_;
+
+  DISALLOW_COPY_AND_ASSIGN(WebRtcLocalAudioTrack);
+};
+
+}  // namespace content
+
+#endif  // CONTENT_RENDERER_MEDIA_WEBRTC_LOCAL_AUDIO_TRACK_H_
diff --git a/content/renderer/media/webrtc_local_audio_track_unittest.cc b/content/renderer/media/webrtc_local_audio_track_unittest.cc
new file mode 100644
index 0000000..7e2f473
--- /dev/null
+++ b/content/renderer/media/webrtc_local_audio_track_unittest.cc
@@ -0,0 +1,241 @@
+// Copyright 2013 The Chromium Authors. 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 "content/renderer/media/webrtc_audio_capturer.h"
+#include "content/renderer/media/webrtc_local_audio_track.h"
+#include "media/audio/audio_parameters.h"
+#include "media/base/audio_bus.h"
+#include "media/base/audio_capturer_source.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using ::testing::_;
+using ::testing::AtLeast;
+using ::testing::Return;
+
+namespace content {
+
+namespace {
+
+ACTION_P(SignalEvent, event) {
+  event->Signal();
+}
+
+// A simple thread that we use to fake the audio thread which provides data to
+// the |WebRtcAudioCapturer|.
+class FakeAudioThread : public base::PlatformThread::Delegate {
+ public:
+  explicit FakeAudioThread(const scoped_refptr<WebRtcAudioCapturer>& capturer)
+    : capturer_(capturer),
+      thread_(base::kNullThreadHandle),
+      closure_(false, false) {
+    DCHECK(capturer);
+    audio_bus_ = media::AudioBus::Create(capturer_->audio_parameters());
+  }
+
+  virtual ~FakeAudioThread() { DCHECK(!thread_); }
+
+  // base::PlatformThread::Delegate:
+  virtual void ThreadMain() OVERRIDE {
+    while (true) {
+      if (closure_.IsSignaled())
+        return;
+
+      media::AudioCapturerSource::CaptureCallback* callback =
+          static_cast<media::AudioCapturerSource::CaptureCallback*>(capturer_);
+      audio_bus_->Zero();
+      callback->Capture(audio_bus_.get(), 0, 0);
+
+      // Sleep 1ms to yield the resource for the main thread.
+      base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(1));
+    }
+  }
+
+  void Start() {
+    base::PlatformThread::CreateWithPriority(
+        0, this, &thread_, base::kThreadPriority_RealtimeAudio);
+    CHECK(thread_ != base::kNullThreadHandle);
+  }
+
+  void Stop() {
+    closure_.Signal();
+    base::PlatformThread::Join(thread_);
+    thread_ = base::kNullThreadHandle;
+  }
+
+ private:
+  scoped_ptr<media::AudioBus> audio_bus_;
+  scoped_refptr<WebRtcAudioCapturer> capturer_;
+  base::PlatformThreadHandle thread_;
+  base::WaitableEvent closure_;
+  DISALLOW_COPY_AND_ASSIGN(FakeAudioThread);
+};
+
+class MockCapturerSource : public media::AudioCapturerSource {
+ public:
+  MockCapturerSource() {}
+  MOCK_METHOD3(Initialize, void(const media::AudioParameters& params,
+                                CaptureCallback* callback,
+                                int session_id));
+  MOCK_METHOD0(Start, void());
+  MOCK_METHOD0(Stop, void());
+  MOCK_METHOD1(SetVolume, void(double volume));
+  MOCK_METHOD1(SetAutomaticGainControl, void(bool enable));
+
+ protected:
+  virtual ~MockCapturerSource() {}
+};
+
+class MockWebRtcAudioCapturerSink : public WebRtcAudioCapturerSink {
+ public:
+  MockWebRtcAudioCapturerSink() {}
+  ~MockWebRtcAudioCapturerSink() {}
+  MOCK_METHOD5(CaptureData, void(const int16* audio_data,
+                                 int number_of_channels,
+                                 int number_of_frames,
+                                 int audio_delay_milliseconds,
+                                 double volume));
+  MOCK_METHOD1(SetCaptureFormat, void(const media::AudioParameters& params));
+};
+
+}  // namespace
+
+class WebRtcLocalAudioTrackTest : public ::testing::Test {
+ protected:
+  virtual void SetUp() OVERRIDE {
+    capturer_ = WebRtcAudioCapturer::CreateCapturer();
+    capturer_source_ = new MockCapturerSource();
+    EXPECT_CALL(*capturer_source_, Initialize(_, capturer_.get(), 0))
+        .WillOnce(Return());
+    capturer_->SetCapturerSource(capturer_source_,
+                                 media::CHANNEL_LAYOUT_STEREO,
+                                 48000);
+
+    EXPECT_CALL(*capturer_source_, Start()).WillOnce(Return());
+    EXPECT_CALL(*capturer_source_, SetAutomaticGainControl(false))
+        .WillOnce(Return());
+    capturer_->Start();
+    audio_thread_.reset(new FakeAudioThread(capturer_));
+    audio_thread_->Start();
+  }
+
+  virtual void TearDown() {
+    audio_thread_->Stop();
+    audio_thread_.reset();
+    EXPECT_CALL(*capturer_source_, Stop()).WillOnce(Return());
+    capturer_->Stop();
+  }
+
+  scoped_refptr<MockCapturerSource> capturer_source_;
+  scoped_refptr<WebRtcAudioCapturer> capturer_;
+  scoped_ptr<FakeAudioThread> audio_thread_;
+};
+
+// Creates a capturer and audio track, fakes its audio thread, and
+// connect/disconnect the sink to the audio track on the fly, the sink should
+// get data callback when the track is connected to the capturer but not when
+// the track is disconnected from the capturer.
+TEST_F(WebRtcLocalAudioTrackTest, ConnectAndDisconnectOneSink) {
+  scoped_refptr<WebRtcLocalAudioTrack> track =
+      WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL);
+  EXPECT_TRUE(track->enabled());
+  scoped_ptr<MockWebRtcAudioCapturerSink> sink(
+      new MockWebRtcAudioCapturerSink());
+  const media::AudioParameters params = capturer_->audio_parameters();
+  base::WaitableEvent event(false, false);
+  EXPECT_CALL(*sink, SetCaptureFormat(_)).WillOnce(Return());
+  EXPECT_CALL(*sink, CaptureData(
+      _, params.channels(), params.frames_per_buffer(), 0, 0))
+      .Times(AtLeast(1)).WillRepeatedly(SignalEvent(&event));
+  track->AddSink(sink.get());
+
+  EXPECT_TRUE(event.TimedWait(TestTimeouts::tiny_timeout()));
+  track->RemoveSink(sink.get());
+  track = NULL;
+}
+
+// The same setup as ConnectAndDisconnectOneSink, but enable and disable the
+// audio track on the fly. When the audio track is disabled, there is no data
+// callback to the sink; when the audio track is enabled, there comes data
+// callback.
+// TODO(xians): Enable this test after resolving the racing issue that TSAN
+// reports on MediaStreamTrack::enabled();
+TEST_F(WebRtcLocalAudioTrackTest, DISABLED_DisableEnableAudioTrack) {
+  scoped_refptr<WebRtcLocalAudioTrack> track =
+    WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL);
+  EXPECT_TRUE(track->enabled());
+  EXPECT_TRUE(track->set_enabled(false));
+  scoped_ptr<MockWebRtcAudioCapturerSink> sink(
+      new MockWebRtcAudioCapturerSink());
+  const media::AudioParameters params = capturer_->audio_parameters();
+  base::WaitableEvent event(false, false);
+  EXPECT_CALL(*sink, SetCaptureFormat(_)).WillOnce(Return());
+  EXPECT_CALL(*sink, CaptureData(
+      _, params.channels(), params.frames_per_buffer(), 0, 0))
+      .Times(0);
+  track->AddSink(sink.get());
+  EXPECT_FALSE(event.TimedWait(TestTimeouts::tiny_timeout()));
+
+  event.Reset();
+  EXPECT_CALL(*sink, CaptureData(
+      _, params.channels(), params.frames_per_buffer(), 0, 0))
+      .Times(AtLeast(1)).WillRepeatedly(SignalEvent(&event));
+  EXPECT_TRUE(track->set_enabled(true));
+  EXPECT_TRUE(event.TimedWait(TestTimeouts::tiny_timeout()));
+  track->RemoveSink(sink.get());
+  track = NULL;
+}
+
+// Create multiple audio tracks and enable/disable them, verify that the audio
+// callbacks appear/disappear.
+// TODO(xians): Enable the test after the racing problem is resolved.
+TEST_F(WebRtcLocalAudioTrackTest, DISABLED_MultipleAudioTracks) {
+  scoped_refptr<WebRtcLocalAudioTrack> track_1 =
+    WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL);
+  EXPECT_TRUE(track_1->enabled());
+  scoped_ptr<MockWebRtcAudioCapturerSink> sink_1(
+      new MockWebRtcAudioCapturerSink());
+  const media::AudioParameters params = capturer_->audio_parameters();
+  base::WaitableEvent event_1(false, false);
+  EXPECT_CALL(*sink_1, SetCaptureFormat(_)).WillOnce(Return());
+  EXPECT_CALL(*sink_1, CaptureData(
+      _, params.channels(), params.frames_per_buffer(), 0, 0))
+      .Times(AtLeast(1)).WillRepeatedly(SignalEvent(&event_1));
+  track_1->AddSink(sink_1.get());
+
+  scoped_refptr<WebRtcLocalAudioTrack> track_2 =
+    WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL);
+  EXPECT_TRUE(track_2->set_enabled(false));
+  scoped_ptr<MockWebRtcAudioCapturerSink> sink_2(
+      new MockWebRtcAudioCapturerSink());
+  EXPECT_CALL(*sink_2, SetCaptureFormat(_)).WillOnce(Return());
+  EXPECT_CALL(*sink_2, CaptureData(
+      _, params.channels(), params.frames_per_buffer(), 0, 0))
+      .Times(0);
+  track_2->AddSink(sink_2.get());
+  EXPECT_TRUE(event_1.TimedWait(TestTimeouts::tiny_timeout()));
+
+
+  // Enable |track_2|, and verify the data callback comes to |sink_2|;
+  event_1.Reset();
+  base::WaitableEvent event_2(false, false);
+  EXPECT_CALL(*sink_1, CaptureData(
+      _, params.channels(), params.frames_per_buffer(), 0, 0))
+      .Times(AtLeast(1)).WillRepeatedly(SignalEvent(&event_1));
+  EXPECT_CALL(*sink_2, CaptureData(
+      _, params.channels(), params.frames_per_buffer(), 0, 0))
+      .Times(AtLeast(1)).WillRepeatedly(SignalEvent(&event_2));
+  EXPECT_TRUE(track_2->set_enabled(true));
+  EXPECT_TRUE(event_1.TimedWait(TestTimeouts::tiny_timeout()));
+  EXPECT_TRUE(event_2.TimedWait(TestTimeouts::tiny_timeout()));
+
+  track_1->RemoveSink(sink_1.get());
+  track_2->RemoveSink(sink_2.get());
+  track_1 = NULL;
+  track_2 = NULL;
+}
+
+}  // namespace content
diff --git a/content/renderer/media/webrtc_logging_handler_impl.cc b/content/renderer/media/webrtc_logging_handler_impl.cc
new file mode 100644
index 0000000..6e3702e
--- /dev/null
+++ b/content/renderer/media/webrtc_logging_handler_impl.cc
@@ -0,0 +1,50 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/media/webrtc_logging_handler_impl.h"
+
+#include "base/logging.h"
+#include "base/message_loop_proxy.h"
+#include "content/renderer/media/webrtc_logging_message_filter.h"
+
+namespace content {
+
+WebRtcLoggingHandlerImpl::WebRtcLoggingHandlerImpl(
+    const scoped_refptr<WebRtcLoggingMessageFilter>& message_filter,
+    const scoped_refptr<base::MessageLoopProxy>& io_message_loop)
+    : message_filter_(message_filter),
+      io_message_loop_(io_message_loop) {
+}
+
+WebRtcLoggingHandlerImpl::~WebRtcLoggingHandlerImpl() {
+}
+
+void WebRtcLoggingHandlerImpl::OnFilterRemoved() {
+  message_filter_ = NULL;
+}
+
+void WebRtcLoggingHandlerImpl::OpenLog() {
+  DCHECK(io_message_loop_->BelongsToCurrentThread());
+  // TODO(grunell): Check if already opened. (Could have been opened by another
+  // render view.)
+  if (message_filter_)
+    message_filter_->OpenLog();
+}
+
+void WebRtcLoggingHandlerImpl::OnLogOpened(
+    base::SharedMemoryHandle handle,
+    uint32 length) {
+  DCHECK(io_message_loop_->BelongsToCurrentThread());
+  // TODO(grunell): Implement.
+  NOTIMPLEMENTED();
+}
+
+void WebRtcLoggingHandlerImpl::OnOpenLogFailed() {
+  DCHECK(io_message_loop_->BelongsToCurrentThread());
+  DLOG(ERROR) << "Could not open log.";
+  // TODO(grunell): Implement.
+  NOTIMPLEMENTED();
+}
+
+}  // namespace content
diff --git a/content/renderer/media/webrtc_logging_handler_impl.h b/content/renderer/media/webrtc_logging_handler_impl.h
new file mode 100644
index 0000000..ca7b0ef
--- /dev/null
+++ b/content/renderer/media/webrtc_logging_handler_impl.h
@@ -0,0 +1,51 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_RENDERER_MEDIA_WEBRTC_LOGGING_HANDLER_IMPL_H_
+#define CONTENT_RENDERER_MEDIA_WEBRTC_LOGGING_HANDLER_IMPL_H_
+
+#include "base/memory/ref_counted.h"
+#include "base/shared_memory.h"
+#include "content/common/content_export.h"
+#include "ipc/ipc_channel_proxy.h"
+
+namespace base {
+class MessageLoopProxy;
+}
+
+namespace content {
+
+class WebRtcLoggingMessageFilter;
+
+// WebRtcLoggingHandlerImpl handles WebRTC logging. There is one object per
+// render thread. It communicates with WebRtcLoggingHandlerHost and receives
+// logging messages from libjingle and writes them to a shared memory buffer.
+class CONTENT_EXPORT WebRtcLoggingHandlerImpl
+    : public base::RefCounted<WebRtcLoggingHandlerImpl> {
+ public:
+  WebRtcLoggingHandlerImpl(
+      const scoped_refptr<WebRtcLoggingMessageFilter>& message_filter,
+      const scoped_refptr<base::MessageLoopProxy>& io_message_loop);
+
+  void OnFilterRemoved();
+
+  void OpenLog();
+
+  void OnLogOpened(base::SharedMemoryHandle handle, uint32 length);
+  void OnOpenLogFailed();
+
+ private:
+  friend class base::RefCounted<WebRtcLoggingHandlerImpl>;
+  virtual ~WebRtcLoggingHandlerImpl();
+
+  scoped_refptr<WebRtcLoggingMessageFilter> message_filter_;
+
+  scoped_refptr<base::MessageLoopProxy> io_message_loop_;
+
+  DISALLOW_COPY_AND_ASSIGN(WebRtcLoggingHandlerImpl);
+};
+
+}  // namespace content
+
+#endif  // CONTENT_RENDERER_MEDIA_WEBRTC_LOGGING_HANDLER_IMPL_H_
diff --git a/content/renderer/media/webrtc_logging_message_filter.cc b/content/renderer/media/webrtc_logging_message_filter.cc
new file mode 100644
index 0000000..db43d96
--- /dev/null
+++ b/content/renderer/media/webrtc_logging_message_filter.cc
@@ -0,0 +1,90 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/media/webrtc_logging_message_filter.h"
+
+#include "base/logging.h"
+#include "base/message_loop_proxy.h"
+#include "content/common/media/webrtc_logging_messages.h"
+#include "content/renderer/media/webrtc_logging_handler_impl.h"
+#include "ipc/ipc_logging.h"
+
+namespace content {
+
+WebRtcLoggingMessageFilter::WebRtcLoggingMessageFilter(
+    const scoped_refptr<base::MessageLoopProxy>& io_message_loop)
+    : io_message_loop_(io_message_loop),
+      channel_(NULL) {
+}
+
+WebRtcLoggingMessageFilter::~WebRtcLoggingMessageFilter() {
+}
+
+bool WebRtcLoggingMessageFilter::OnMessageReceived(
+    const IPC::Message& message) {
+  DCHECK(io_message_loop_->BelongsToCurrentThread());
+  bool handled = true;
+  IPC_BEGIN_MESSAGE_MAP(WebRtcLoggingMessageFilter, message)
+    IPC_MESSAGE_HANDLER(WebRtcLoggingMsg_LogOpened, OnLogOpened)
+    IPC_MESSAGE_HANDLER(WebRtcLoggingMsg_OpenLogFailed, OnOpenLogFailed)
+    IPC_MESSAGE_UNHANDLED(handled = false)
+  IPC_END_MESSAGE_MAP()
+  return handled;
+}
+
+void WebRtcLoggingMessageFilter::OnFilterAdded(IPC::Channel* channel) {
+  DCHECK(io_message_loop_->BelongsToCurrentThread());
+  channel_ = channel;
+}
+
+void WebRtcLoggingMessageFilter::OnFilterRemoved() {
+  DCHECK(io_message_loop_->BelongsToCurrentThread());
+  channel_ = NULL;
+  RemoveDelegate();
+}
+
+void WebRtcLoggingMessageFilter::OnChannelClosing() {
+  DCHECK(io_message_loop_->BelongsToCurrentThread());
+  channel_ = NULL;
+  RemoveDelegate();
+}
+
+void WebRtcLoggingMessageFilter::SetDelegate(
+    scoped_refptr<WebRtcLoggingHandlerImpl>& logging_handler) {
+  logging_handler_ = logging_handler;
+}
+
+void WebRtcLoggingMessageFilter::RemoveDelegate() {
+  logging_handler_ = NULL;
+}
+
+void WebRtcLoggingMessageFilter::OpenLog() {
+  Send(new WebRtcLoggingMsg_OpenLog());
+}
+
+void WebRtcLoggingMessageFilter::OnLogOpened(
+    base::SharedMemoryHandle handle,
+    uint32 length) {
+  DCHECK(io_message_loop_->BelongsToCurrentThread());
+  if (logging_handler_)
+    logging_handler_->OnLogOpened(handle, length);
+}
+
+void WebRtcLoggingMessageFilter::OnOpenLogFailed() {
+  DCHECK(io_message_loop_->BelongsToCurrentThread());
+  if (logging_handler_)
+    logging_handler_->OnOpenLogFailed();
+}
+
+void WebRtcLoggingMessageFilter::Send(IPC::Message* message) {
+  DCHECK(io_message_loop_->BelongsToCurrentThread());
+  if (!channel_) {
+    DLOG(ERROR) << "IPC channel not available.";
+    delete message;
+  } else {
+    channel_->Send(message);
+  }
+}
+
+}  // namespace content
diff --git a/content/renderer/media/webrtc_logging_message_filter.h b/content/renderer/media/webrtc_logging_message_filter.h
new file mode 100644
index 0000000..33b5ccd
--- /dev/null
+++ b/content/renderer/media/webrtc_logging_message_filter.h
@@ -0,0 +1,61 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_RENDERER_MEDIA_WEBRTC_LOGGING_MESSAGE_FILTER_H_
+#define CONTENT_RENDERER_MEDIA_WEBRTC_LOGGING_MESSAGE_FILTER_H_
+
+#include "base/shared_memory.h"
+#include "content/common/content_export.h"
+#include "ipc/ipc_channel_proxy.h"
+
+namespace base {
+class MessageLoopProxy;
+}
+
+namespace content {
+
+class WebRtcLoggingHandlerImpl;
+
+// Filter for WebRTC logging messages. Sits between WebRtcLoggingHandlerImpl
+// (renderer process) and WebRtcLoggingHandlerHost (browser process). Must be
+// called on the IO thread.
+class CONTENT_EXPORT WebRtcLoggingMessageFilter
+    : public IPC::ChannelProxy::MessageFilter {
+ public:
+  explicit WebRtcLoggingMessageFilter(
+      const scoped_refptr<base::MessageLoopProxy>& io_message_loop);
+
+  virtual void SetDelegate(
+      scoped_refptr<WebRtcLoggingHandlerImpl>& logging_handler);
+  virtual void RemoveDelegate();
+
+  virtual void OpenLog();
+
+ protected:
+  virtual ~WebRtcLoggingMessageFilter();
+
+ private:
+  // IPC::ChannelProxy::MessageFilter implementation.
+  virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+  virtual void OnFilterAdded(IPC::Channel* channel) OVERRIDE;
+  virtual void OnFilterRemoved() OVERRIDE;
+  virtual void OnChannelClosing() OVERRIDE;
+
+  void OnLogOpened(base::SharedMemoryHandle handle, uint32 length);
+  void OnOpenLogFailed();
+
+  void Send(IPC::Message* message);
+
+  scoped_refptr<WebRtcLoggingHandlerImpl> logging_handler_;
+
+  scoped_refptr<base::MessageLoopProxy> io_message_loop_;
+
+  IPC::Channel* channel_;
+
+  DISALLOW_COPY_AND_ASSIGN(WebRtcLoggingMessageFilter);
+};
+
+}  // namespace content
+
+#endif  // CONTENT_RENDERER_MEDIA_WEBRTC_LOGGING_MESSAGE_FILTER_H_
diff --git a/content/renderer/p2p/ipc_network_manager.cc b/content/renderer/p2p/ipc_network_manager.cc
index 2ddc397..34a65c5 100644
--- a/content/renderer/p2p/ipc_network_manager.cc
+++ b/content/renderer/p2p/ipc_network_manager.cc
@@ -14,7 +14,7 @@
     : socket_dispatcher_(socket_dispatcher),
       start_count_(0),
       network_list_received_(false),
-      ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) {
+      weak_factory_(this) {
   socket_dispatcher_->AddNetworkListObserver(this);
 }
 
@@ -26,9 +26,10 @@
 void IpcNetworkManager::StartUpdating() {
   if (network_list_received_) {
     // Post a task to avoid reentrancy.
-    MessageLoop::current()->PostTask(
-        FROM_HERE, base::Bind(&IpcNetworkManager::SendNetworksChangedSignal,
-                              weak_factory_.GetWeakPtr()));
+    base::MessageLoop::current()->PostTask(
+        FROM_HERE,
+        base::Bind(&IpcNetworkManager::SendNetworksChangedSignal,
+                   weak_factory_.GetWeakPtr()));
   }
   ++start_count_;
 }
diff --git a/content/renderer/p2p/ipc_socket_factory.cc b/content/renderer/p2p/ipc_socket_factory.cc
index ea53678..d1f5686 100644
--- a/content/renderer/p2p/ipc_socket_factory.cc
+++ b/content/renderer/p2p/ipc_socket_factory.cc
@@ -5,6 +5,7 @@
 #include "content/renderer/p2p/ipc_socket_factory.h"
 
 #include "base/compiler_specific.h"
+#include "base/debug/trace_event.h"
 #include "base/message_loop.h"
 #include "base/message_loop_proxy.h"
 #include "content/renderer/p2p/socket_client.h"
@@ -16,6 +17,10 @@
 
 namespace {
 
+// TODO(hclam): This shouldn't be a pre-defined value. Bug: crbug.com/181321.
+const int kMaxPendingPackets = 32;
+const int kWritableSignalThreshold = 0;
+
 // IpcPacketSocket implements talk_base::AsyncPacketSocket interface
 // using P2PSocketClient that works over IPC-channel. It must be used
 // on the thread it was created.
@@ -47,6 +52,7 @@
   virtual void OnOpen(const net::IPEndPoint& address) OVERRIDE;
   virtual void OnIncomingTcpConnection(const net::IPEndPoint& address,
                                        P2PSocketClient* client) OVERRIDE;
+  virtual void OnSendComplete() OVERRIDE;
   virtual void OnError() OVERRIDE;
   virtual void OnDataReceived(const net::IPEndPoint& address,
                               const std::vector<char>& data) OVERRIDE;
@@ -67,7 +73,7 @@
   P2PSocketType type_;
 
   // Message loop on which this socket was created and being used.
-  MessageLoop* message_loop_;
+  base::MessageLoop* message_loop_;
 
   // Corresponding P2P socket client.
   scoped_refptr<P2PSocketClient> client_;
@@ -83,6 +89,14 @@
   // Current state of the object.
   InternalState state_;
 
+  // Number which have been sent to the browser, but for which we haven't
+  // received response.
+  int send_packets_pending_;
+
+  // Set to true once EWOULDBLOCK was returned from Send(). Indicates that the
+  // caller expects SignalWritable notification.
+  bool writable_signal_expected_;
+
   // Current error code. Valid when state_ == IS_ERROR.
   int error_;
 
@@ -91,10 +105,11 @@
 
 IpcPacketSocket::IpcPacketSocket()
     : type_(P2P_SOCKET_UDP),
-      message_loop_(MessageLoop::current()),
+      message_loop_(base::MessageLoop::current()),
       state_(IS_UNINITIALIZED),
-      error_(0) {
-}
+      send_packets_pending_(0),
+      writable_signal_expected_(false),
+      error_(0) {}
 
 IpcPacketSocket::~IpcPacketSocket() {
   if (state_ == IS_OPENING || state_ == IS_OPEN ||
@@ -106,7 +121,7 @@
 bool IpcPacketSocket::Init(P2PSocketType type, P2PSocketClient* client,
                            const talk_base::SocketAddress& local_address,
                            const talk_base::SocketAddress& remote_address) {
-  DCHECK_EQ(MessageLoop::current(), message_loop_);
+  DCHECK_EQ(base::MessageLoop::current(), message_loop_);
   DCHECK_EQ(state_, IS_UNINITIALIZED);
 
   type_ = type;
@@ -135,7 +150,7 @@
     P2PSocketClient* client,
     const talk_base::SocketAddress& local_address,
     const talk_base::SocketAddress& remote_address) {
-  DCHECK_EQ(MessageLoop::current(), message_loop_);
+  DCHECK_EQ(base::MessageLoop::current(), message_loop_);
   DCHECK_EQ(state_, IS_UNINITIALIZED);
 
   client_ = client;
@@ -147,23 +162,23 @@
 
 // talk_base::AsyncPacketSocket interface.
 talk_base::SocketAddress IpcPacketSocket::GetLocalAddress() const {
-  DCHECK_EQ(MessageLoop::current(), message_loop_);
+  DCHECK_EQ(base::MessageLoop::current(), message_loop_);
   return local_address_;
 }
 
 talk_base::SocketAddress IpcPacketSocket::GetRemoteAddress() const {
-  DCHECK_EQ(MessageLoop::current(), message_loop_);
+  DCHECK_EQ(base::MessageLoop::current(), message_loop_);
   return remote_address_;
 }
 
 int IpcPacketSocket::Send(const void *data, size_t data_size) {
-  DCHECK_EQ(MessageLoop::current(), message_loop_);
+  DCHECK_EQ(base::MessageLoop::current(), message_loop_);
   return SendTo(data, data_size, remote_address_);
 }
 
 int IpcPacketSocket::SendTo(const void *data, size_t data_size,
                             const talk_base::SocketAddress& address) {
-  DCHECK_EQ(MessageLoop::current(), message_loop_);
+  DCHECK_EQ(base::MessageLoop::current(), message_loop_);
 
   switch (state_) {
     case IS_UNINITIALIZED:
@@ -180,15 +195,24 @@
       break;
   }
 
+  if (send_packets_pending_ > kMaxPendingPackets) {
+    TRACE_EVENT_INSTANT1("p2p", "MaxPendingPacketsWouldBlock",
+                         TRACE_EVENT_SCOPE_THREAD, "id", client_->socket_id());
+    writable_signal_expected_ = true;
+    error_ = EWOULDBLOCK;
+    return -1;
+  }
+
   const char* data_char = reinterpret_cast<const char*>(data);
   std::vector<char> data_vector(data_char, data_char + data_size);
 
   net::IPEndPoint address_chrome;
   if (!jingle_glue::SocketAddressToIPEndPoint(address, &address_chrome)) {
-    // Just drop the packet if we failed to convert the address.
-    return 0;
+    NOTREACHED();
+    return -1;
   }
 
+  ++send_packets_pending_;
   client_->Send(address_chrome, data_vector);
 
   // Fake successful send. The caller ignores result anyway.
@@ -196,7 +220,7 @@
 }
 
 int IpcPacketSocket::Close() {
-  DCHECK_EQ(MessageLoop::current(), message_loop_);
+  DCHECK_EQ(base::MessageLoop::current(), message_loop_);
 
   client_->Close();
   state_ = IS_CLOSED;
@@ -205,7 +229,7 @@
 }
 
 talk_base::AsyncPacketSocket::State IpcPacketSocket::GetState() const {
-  DCHECK_EQ(MessageLoop::current(), message_loop_);
+  DCHECK_EQ(base::MessageLoop::current(), message_loop_);
 
   switch (state_) {
     case IS_UNINITIALIZED:
@@ -238,24 +262,21 @@
 
 int IpcPacketSocket::SetOption(talk_base::Socket::Option opt, int value) {
   // We don't support socket options for IPC sockets.
-  //
-  // TODO(sergeyu): Make sure we set proper socket options on the
-  // browser side.
   return -1;
 }
 
 int IpcPacketSocket::GetError() const {
-  DCHECK_EQ(MessageLoop::current(), message_loop_);
+  DCHECK_EQ(base::MessageLoop::current(), message_loop_);
   return error_;
 }
 
 void IpcPacketSocket::SetError(int error) {
-  DCHECK_EQ(MessageLoop::current(), message_loop_);
+  DCHECK_EQ(base::MessageLoop::current(), message_loop_);
   error_ = error;
 }
 
 void IpcPacketSocket::OnOpen(const net::IPEndPoint& address) {
-  DCHECK_EQ(MessageLoop::current(), message_loop_);
+  DCHECK_EQ(base::MessageLoop::current(), message_loop_);
 
   if (!jingle_glue::IPEndPointToSocketAddress(address, &local_address_)) {
     // Always expect correct IPv4 address to be allocated.
@@ -274,7 +295,7 @@
 void IpcPacketSocket::OnIncomingTcpConnection(
     const net::IPEndPoint& address,
     P2PSocketClient* client) {
-  DCHECK_EQ(MessageLoop::current(), message_loop_);
+  DCHECK_EQ(base::MessageLoop::current(), message_loop_);
 
   scoped_ptr<IpcPacketSocket> socket(new IpcPacketSocket());
 
@@ -287,15 +308,28 @@
   SignalNewConnection(this, socket.release());
 }
 
+void IpcPacketSocket::OnSendComplete() {
+  DCHECK_EQ(base::MessageLoop::current(), message_loop_);
+
+  --send_packets_pending_;
+  DCHECK_GE(send_packets_pending_, 0);
+
+  if (writable_signal_expected_ &&
+      send_packets_pending_ <= kWritableSignalThreshold) {
+    SignalReadyToSend(this);
+    writable_signal_expected_ = false;
+  }
+}
+
 void IpcPacketSocket::OnError() {
-  DCHECK_EQ(MessageLoop::current(), message_loop_);
+  DCHECK_EQ(base::MessageLoop::current(), message_loop_);
   state_ = IS_ERROR;
   error_ = ECONNABORTED;
 }
 
 void IpcPacketSocket::OnDataReceived(const net::IPEndPoint& address,
                                      const std::vector<char>& data) {
-  DCHECK_EQ(MessageLoop::current(), message_loop_);
+  DCHECK_EQ(base::MessageLoop::current(), message_loop_);
 
   talk_base::SocketAddress address_lj;
   if (!jingle_glue::IPEndPointToSocketAddress(address, &address_lj)) {
diff --git a/content/renderer/p2p/port_allocator.cc b/content/renderer/p2p/port_allocator.cc
index 7d06f6e..c8241e3 100644
--- a/content/renderer/p2p/port_allocator.cc
+++ b/content/renderer/p2p/port_allocator.cc
@@ -74,6 +74,9 @@
   if (config_.disable_tcp_transport)
     flags |= cricket::PORTALLOCATOR_DISABLE_TCP;
   set_flags(flags);
+  // TODO(ronghuawu): crbug/138185 add ourselves to the firewall list in browser
+  // process and then remove below line.
+  set_allow_tcp_listen(false);
 }
 
 P2PPortAllocator::~P2PPortAllocator() {
@@ -199,7 +202,7 @@
 
   relay_session_request_.reset(
       allocator_->web_frame_->createAssociatedURLLoader(options));
-  if (!relay_session_request_.get()) {
+  if (!relay_session_request_) {
     LOG(ERROR) << "Failed to create URL loader.";
     return;
   }
@@ -282,8 +285,8 @@
 }
 
 void P2PPortAllocatorSession::AddConfig() {
-  cricket::PortConfiguration* config =
-      new cricket::PortConfiguration(stun_server_address_, "", "");
+  cricket::PortConfiguration* config = new cricket::PortConfiguration(
+      stun_server_address_, std::string(), std::string());
 
   if (allocator_->config_.legacy_relay) {
     // Passing empty credentials for legacy google relay.
diff --git a/content/renderer/p2p/socket_client.cc b/content/renderer/p2p/socket_client.cc
index e6f5a0f..ed3f211 100644
--- a/content/renderer/p2p/socket_client.cc
+++ b/content/renderer/p2p/socket_client.cc
@@ -134,6 +134,19 @@
   }
 }
 
+void P2PSocketClient::OnSendComplete() {
+  DCHECK(ipc_message_loop_->BelongsToCurrentThread());
+
+  delegate_message_loop_->PostTask(
+      FROM_HERE, base::Bind(&P2PSocketClient::DeliverOnSendComplete, this));
+}
+
+void P2PSocketClient::DeliverOnSendComplete() {
+  DCHECK(delegate_message_loop_->BelongsToCurrentThread());
+  if (delegate_)
+    delegate_->OnSendComplete();
+}
+
 void P2PSocketClient::OnError() {
   DCHECK(ipc_message_loop_->BelongsToCurrentThread());
   state_ = STATE_ERROR;
diff --git a/content/renderer/p2p/socket_client.h b/content/renderer/p2p/socket_client.h
index d74107f..fd8537e 100644
--- a/content/renderer/p2p/socket_client.h
+++ b/content/renderer/p2p/socket_client.h
@@ -27,7 +27,8 @@
 // thread which is specified in Init().
 class P2PSocketClient : public base::RefCountedThreadSafe<P2PSocketClient> {
  public:
-  // Delegate is called on the the same thread on the delegate thread.
+  // Delegate is called on the the same thread on which P2PSocketCLient is
+  // created.
   class Delegate {
    public:
     virtual ~Delegate() { }
@@ -35,6 +36,7 @@
     virtual void OnOpen(const net::IPEndPoint& address) = 0;
     virtual void OnIncomingTcpConnection(const net::IPEndPoint& address,
                                          P2PSocketClient* client) = 0;
+    virtual void OnSendComplete() = 0;
     virtual void OnError() = 0;
     virtual void OnDataReceived(const net::IPEndPoint& address,
                                 const std::vector<char>& data) = 0;
@@ -80,6 +82,8 @@
   // Message handlers that run on IPC thread.
   void OnSocketCreated(const net::IPEndPoint& address);
   void OnIncomingTcpConnection(const net::IPEndPoint& address);
+  void OnSendComplete(int packet_id);
+  void OnSendComplete();
   void OnError();
   void OnDataReceived(const net::IPEndPoint& address,
                       const std::vector<char>& data);
@@ -89,6 +93,7 @@
   void DeliverOnIncomingTcpConnection(
       const net::IPEndPoint& address,
       scoped_refptr<P2PSocketClient> new_client);
+  void DeliverOnSendComplete();
   void DeliverOnError();
   void DeliverOnDataReceived(const net::IPEndPoint& address,
                              const std::vector<char>& data);
diff --git a/content/renderer/p2p/socket_dispatcher.cc b/content/renderer/p2p/socket_dispatcher.cc
index c999e62..7fe71ee 100644
--- a/content/renderer/p2p/socket_dispatcher.cc
+++ b/content/renderer/p2p/socket_dispatcher.cc
@@ -63,6 +63,7 @@
     IPC_MESSAGE_HANDLER(P2PMsg_GetHostAddressResult, OnGetHostAddressResult)
     IPC_MESSAGE_HANDLER(P2PMsg_OnSocketCreated, OnSocketCreated)
     IPC_MESSAGE_HANDLER(P2PMsg_OnIncomingTcpConnection, OnIncomingTcpConnection)
+    IPC_MESSAGE_HANDLER(P2PMsg_OnSendComplete, OnSendComplete)
     IPC_MESSAGE_HANDLER(P2PMsg_OnError, OnError)
     IPC_MESSAGE_HANDLER(P2PMsg_OnDataReceived, OnDataReceived)
     IPC_MESSAGE_UNHANDLED(handled = false)
@@ -152,6 +153,13 @@
   }
 }
 
+void P2PSocketDispatcher::OnSendComplete(int socket_id) {
+  P2PSocketClient* client = GetClient(socket_id);
+  if (client) {
+    client->OnSendComplete();
+  }
+}
+
 void P2PSocketDispatcher::OnError(int socket_id) {
   P2PSocketClient* client = GetClient(socket_id);
   if (client) {
diff --git a/content/renderer/p2p/socket_dispatcher.h b/content/renderer/p2p/socket_dispatcher.h
index e17a8c1..cbd8f2a 100644
--- a/content/renderer/p2p/socket_dispatcher.h
+++ b/content/renderer/p2p/socket_dispatcher.h
@@ -102,6 +102,7 @@
                               const net::IPAddressNumber& address);
   void OnSocketCreated(int socket_id, const net::IPEndPoint& address);
   void OnIncomingTcpConnection(int socket_id, const net::IPEndPoint& address);
+  void OnSendComplete(int socket_id);
   void OnError(int socket_id);
   void OnDataReceived(int socket_id, const net::IPEndPoint& address,
                       const std::vector<char>& data);
diff --git a/content/renderer/password_form_conversion_utils.cc b/content/renderer/password_form_conversion_utils.cc
index 68b1ee5..d173815 100644
--- a/content/renderer/password_form_conversion_utils.cc
+++ b/content/renderer/password_form_conversion_utils.cc
@@ -22,6 +22,11 @@
   password_form->submit_element = web_password_form.submitElement;
   password_form->username_element = web_password_form.userNameElement;
   password_form->username_value = web_password_form.userNameValue;
+  password_form->possible_usernames.insert(
+      password_form->possible_usernames.begin(),
+      web_password_form.possibleUserNames.data(),
+      web_password_form.possibleUserNames.data() +
+      web_password_form.possibleUserNames.size());
   password_form->password_element = web_password_form.passwordElement;
   password_form->password_value = web_password_form.passwordValue;
   password_form->password_autocomplete_set =
diff --git a/content/renderer/pepper/content_renderer_pepper_host_factory.cc b/content/renderer/pepper/content_renderer_pepper_host_factory.cc
index 0e7f380..a9c6f23 100644
--- a/content/renderer/pepper/content_renderer_pepper_host_factory.cc
+++ b/content/renderer/pepper/content_renderer_pepper_host_factory.cc
@@ -7,20 +7,24 @@
 #include "base/logging.h"
 #include "base/string_util.h"
 #include "content/renderer/pepper/pepper_audio_input_host.h"
-#include "content/renderer/pepper/pepper_directory_reader_host.h"
 #include "content/renderer/pepper/pepper_file_chooser_host.h"
 #include "content/renderer/pepper/pepper_file_io_host.h"
+#include "content/renderer/pepper/pepper_file_system_host.h"
 #include "content/renderer/pepper/pepper_graphics_2d_host.h"
 #include "content/renderer/pepper/pepper_truetype_font_host.h"
 #include "content/renderer/pepper/pepper_video_capture_host.h"
+#include "content/renderer/pepper/pepper_video_destination_host.h"
+#include "content/renderer/pepper/pepper_video_source_host.h"
 #include "content/renderer/pepper/pepper_websocket_host.h"
 #include "content/renderer/pepper/renderer_ppapi_host_impl.h"
 #include "ppapi/host/resource_host.h"
+#include "ppapi/proxy/ppapi_message_utils.h"
 #include "ppapi/proxy/ppapi_messages.h"
 #include "ppapi/proxy/serialized_structs.h"
 
 using ppapi::host::ResourceHost;
 using ppapi::proxy::SerializedTrueTypeFontDesc;
+using ppapi::UnpackMessage;
 
 namespace content {
 
@@ -45,23 +49,34 @@
 
   // Public interfaces.
   switch (message.type()) {
+    case PpapiHostMsg_FileIO_Create::ID:
+      return scoped_ptr<ResourceHost>(new PepperFileIOHost(
+          host_, instance, params.pp_resource()));
+    case PpapiHostMsg_FileSystem_Create::ID: {
+      PP_FileSystemType file_system_type;
+      if (!UnpackMessage<PpapiHostMsg_FileSystem_Create>(message,
+                                                         &file_system_type)) {
+        NOTREACHED();
+        return scoped_ptr<ResourceHost>();
+      }
+      return scoped_ptr<ResourceHost>(new PepperFileSystemHost(
+          host_, instance, params.pp_resource(), file_system_type));
+    }
     case PpapiHostMsg_Graphics2D_Create::ID: {
-      PpapiHostMsg_Graphics2D_Create::Schema::Param msg_params;
-      if (!PpapiHostMsg_Graphics2D_Create::Read(&message, &msg_params)) {
+      PP_Size size;
+      PP_Bool is_always_opaque;
+      if (!UnpackMessage<PpapiHostMsg_Graphics2D_Create>(message, &size,
+                                                         &is_always_opaque)) {
         NOTREACHED();
         return scoped_ptr<ResourceHost>();
       }
       return scoped_ptr<ResourceHost>(
           PepperGraphics2DHost::Create(host_, instance, params.pp_resource(),
-                                       msg_params.a /* PP_Size */,
-                                       msg_params.b /* PP_Bool */));
+                                       size, is_always_opaque));
     }
     case PpapiHostMsg_WebSocket_Create::ID:
       return scoped_ptr<ResourceHost>(new PepperWebSocketHost(
           host_, instance, params.pp_resource()));
-    case PpapiHostMsg_FileIO_Create::ID:
-      return scoped_ptr<ResourceHost>(new PepperFileIOHost(
-          host_, instance, params.pp_resource()));
   }
 
   // Dev interfaces.
@@ -70,21 +85,18 @@
       case PpapiHostMsg_AudioInput_Create::ID:
         return scoped_ptr<ResourceHost>(new PepperAudioInputHost(
             host_, instance, params.pp_resource()));
-      case PpapiHostMsg_DirectoryReader_Create::ID:
-        return scoped_ptr<ResourceHost>(new PepperDirectoryReaderHost(
-            host_, instance, params.pp_resource()));
       case PpapiHostMsg_FileChooser_Create::ID:
         return scoped_ptr<ResourceHost>(new PepperFileChooserHost(
             host_, instance, params.pp_resource()));
       case PpapiHostMsg_TrueTypeFont_Create::ID: {
-        PpapiHostMsg_TrueTypeFont_Create::Schema::Param msg_params;
-        if (!PpapiHostMsg_TrueTypeFont_Create::Read(&message, &msg_params)) {
+        SerializedTrueTypeFontDesc desc;
+        if (!UnpackMessage<PpapiHostMsg_TrueTypeFont_Create>(message,
+                                                             &desc)) {
           NOTREACHED();
           return scoped_ptr<ResourceHost>();
         }
         // Check that the family name is valid UTF-8 before passing it to the
         // host OS.
-        const SerializedTrueTypeFontDesc& desc = msg_params.a;
         if (IsStringUTF8(desc.family)) {
           return scoped_ptr<ResourceHost>(new PepperTrueTypeFontHost(
               host_, instance, params.pp_resource(), desc));
@@ -103,6 +115,18 @@
     }
   }
 
+  // Private interfaces.
+  if (GetPermissions().HasPermission(ppapi::PERMISSION_PRIVATE)) {
+    switch (message.type()) {
+      case PpapiHostMsg_VideoDestination_Create::ID:
+        return scoped_ptr<ResourceHost>(new PepperVideoDestinationHost(
+            host_, instance, params.pp_resource()));
+      case PpapiHostMsg_VideoSource_Create::ID:
+        return scoped_ptr<ResourceHost>(new PepperVideoSourceHost(
+            host_, instance, params.pp_resource()));
+    }
+  }
+
   return scoped_ptr<ResourceHost>();
 }
 
diff --git a/content/renderer/pepper/null_file_system_callback_dispatcher.cc b/content/renderer/pepper/null_file_system_callback_dispatcher.cc
new file mode 100644
index 0000000..0c8d6a3
--- /dev/null
+++ b/content/renderer/pepper/null_file_system_callback_dispatcher.cc
@@ -0,0 +1,59 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/pepper/null_file_system_callback_dispatcher.h"
+
+#include "base/files/file_path.h"
+#include "base/files/file_util_proxy.h"
+#include "base/logging.h"
+#include "googleurl/src/gurl.h"
+
+namespace content {
+
+void NullFileSystemCallbackDispatcher::DidSucceed() {
+  NOTREACHED();
+}
+
+void NullFileSystemCallbackDispatcher::DidReadMetadata(
+    const base::PlatformFileInfo& /* file_info */,
+    const base::FilePath& /* platform_path */) {
+  NOTREACHED();
+}
+
+void NullFileSystemCallbackDispatcher::DidCreateSnapshotFile(
+    const base::PlatformFileInfo& /* file_info */,
+    const base::FilePath& /* platform_path */) {
+  NOTREACHED();
+}
+
+void NullFileSystemCallbackDispatcher::DidReadDirectory(
+    const std::vector<base::FileUtilProxy::Entry>& /* entries */,
+    bool /* has_more */) {
+  NOTREACHED();
+}
+
+void NullFileSystemCallbackDispatcher::DidOpenFileSystem(
+    const std::string& /* name */,
+    const GURL& /* root */) {
+  NOTREACHED();
+}
+
+void NullFileSystemCallbackDispatcher::DidWrite(int64 /* bytes */,
+                                                bool /* complete */) {
+  NOTREACHED();
+}
+
+void NullFileSystemCallbackDispatcher::DidOpenFile(
+    base::PlatformFile /* file */,
+    int /* file_open_id */,
+    quota::QuotaLimitType /* quota_policy */) {
+  NOTREACHED();
+}
+
+void NullFileSystemCallbackDispatcher::DidFail(
+    base::PlatformFileError /* platform_error */) {
+  NOTREACHED();
+}
+
+}  // namespace content
diff --git a/content/renderer/pepper/null_file_system_callback_dispatcher.h b/content/renderer/pepper/null_file_system_callback_dispatcher.h
new file mode 100644
index 0000000..1031948
--- /dev/null
+++ b/content/renderer/pepper/null_file_system_callback_dispatcher.h
@@ -0,0 +1,55 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_RENDERER_PEPPER_NULL_FILE_SYSTEM_CALLBACK_DISPATCHER_H_
+#define CONTENT_RENDERER_PEPPER_NULL_FILE_SYSTEM_CALLBACK_DISPATCHER_H_
+
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/platform_file.h"
+#include "webkit/fileapi/file_system_callback_dispatcher.h"
+#include "webkit/quota/quota_types.h"
+
+class GURL;
+
+namespace base {
+class FilePath;
+class FileUtilProxy;
+struct PlatformFileInfo;
+}  // namespace base
+
+namespace content {
+
+class NullFileSystemCallbackDispatcher
+    : public fileapi::FileSystemCallbackDispatcher {
+ public:
+  NullFileSystemCallbackDispatcher() {}
+
+  virtual ~NullFileSystemCallbackDispatcher(){}
+
+  virtual void DidSucceed() OVERRIDE;
+  virtual void DidReadMetadata(const base::PlatformFileInfo& file_info,
+                               const base::FilePath& platform_path) OVERRIDE;
+  virtual void DidCreateSnapshotFile(
+      const base::PlatformFileInfo& file_info,
+      const base::FilePath& platform_path) OVERRIDE;
+  virtual void DidReadDirectory(
+      const std::vector<base::FileUtilProxy::Entry>& entries,
+      bool has_more) OVERRIDE;
+  virtual void DidOpenFileSystem(const std::string& name,
+                                 const GURL& root) OVERRIDE;
+  virtual void DidWrite(int64 bytes, bool complete) OVERRIDE;
+  virtual void DidOpenFile(base::PlatformFile file,
+                           int file_open_id,
+                           quota::QuotaLimitType quota_policy) OVERRIDE;
+  virtual void DidFail(base::PlatformFileError platform_error) OVERRIDE;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(NullFileSystemCallbackDispatcher);
+};
+
+}  // namespace content
+
+#endif  // CONTENT_RENDERER_PEPPER_NULL_FILE_SYSTEM_CALLBACK_DISPATCHER_H_
diff --git a/content/renderer/pepper/pepper_audio_input_host.cc b/content/renderer/pepper/pepper_audio_input_host.cc
index 413675a..7d494b1 100644
--- a/content/renderer/pepper/pepper_audio_input_host.cc
+++ b/content/renderer/pepper/pepper_audio_input_host.cc
@@ -44,8 +44,7 @@
     : ResourceHost(host->GetPpapiHost(), instance, resource),
       renderer_ppapi_host_(host),
       audio_input_(NULL),
-      ALLOW_THIS_IN_INITIALIZER_LIST(
-          enumeration_helper_(this, this, PP_DEVICETYPE_DEV_AUDIOCAPTURE)) {
+      enumeration_helper_(this, this, PP_DEVICETYPE_DEV_AUDIOCAPTURE) {
 }
 
 PepperAudioInputHost::~PepperAudioInputHost() {
@@ -94,7 +93,7 @@
     const std::string& device_id,
     PP_AudioSampleRate sample_rate,
     uint32_t sample_frame_count) {
-  if (open_context_.get())
+  if (open_context_)
     return PP_ERROR_INPROGRESS;
   if (audio_input_)
     return PP_ERROR_FAILED;
@@ -143,7 +142,7 @@
   base::SyncSocket scoped_socket(socket_handle);
   base::SharedMemory scoped_shared_memory(shared_memory_handle, false);
 
-  if (!open_context_.get()) {
+  if (!open_context_) {
     NOTREACHED();
     return;
   }
@@ -208,7 +207,7 @@
   audio_input_->ShutDown();
   audio_input_ = NULL;
 
-  if (open_context_.get()) {
+  if (open_context_) {
     open_context_->params.set_result(PP_ERROR_ABORTED);
     host()->SendReply(*open_context_, PpapiPluginMsg_AudioInput_OpenReply());
     open_context_.reset();
diff --git a/content/renderer/pepper/pepper_broker_impl.cc b/content/renderer/pepper/pepper_broker_impl.cc
index d814dda..550c3be 100644
--- a/content/renderer/pepper/pepper_broker_impl.cc
+++ b/content/renderer/pepper/pepper_broker_impl.cc
@@ -226,7 +226,7 @@
     return;
   }
 
-  if (dispatcher_.get()) {
+  if (dispatcher_) {
     ConnectPluginToBroker(client);
     pending_connects_.erase(entry);
     return;
diff --git a/content/renderer/pepper/pepper_broker_impl_unittest.cc b/content/renderer/pepper/pepper_broker_impl_unittest.cc
index aa61bf8..dc894a9 100644
--- a/content/renderer/pepper/pepper_broker_impl_unittest.cc
+++ b/content/renderer/pepper/pepper_broker_impl_unittest.cc
@@ -16,7 +16,7 @@
 
 class PepperBrokerImplTest : public ::testing::Test {
  protected:
-  MessageLoopForIO message_loop_;
+  base::MessageLoopForIO message_loop_;
   // We need a render process for ppapi::proxy::ProxyChannel to work.
   MockRenderProcess mock_process_;
 };
diff --git a/content/renderer/pepper/pepper_device_enumeration_event_handler.cc b/content/renderer/pepper/pepper_device_enumeration_event_handler.cc
index b23df8a..7a8dce6 100644
--- a/content/renderer/pepper/pepper_device_enumeration_event_handler.cc
+++ b/content/renderer/pepper/pepper_device_enumeration_event_handler.cc
@@ -78,7 +78,7 @@
 }
 
 void PepperDeviceEnumerationEventHandler::OnDeviceOpenFailed(int request_id) {
-  NotifyDeviceOpened(request_id, false, "");
+  NotifyDeviceOpened(request_id, false, std::string());
 }
 
 // static
diff --git a/content/renderer/pepper/pepper_device_enumeration_host_helper.cc b/content/renderer/pepper/pepper_device_enumeration_host_helper.cc
index 4b21565..2352673 100644
--- a/content/renderer/pepper/pepper_device_enumeration_host_helper.cc
+++ b/content/renderer/pepper/pepper_device_enumeration_host_helper.cc
@@ -70,10 +70,13 @@
       bool succeeded,
       const std::vector<ppapi::DeviceRefData>& devices) {
     if (sync_call_) {
-      MessageLoop::current()->PostTask(
+      base::MessageLoop::current()->PostTask(
           FROM_HERE,
-          base::Bind(&ScopedRequest::EnumerateDevicesCallbackBody, AsWeakPtr(),
-                     request_id, succeeded, devices));
+          base::Bind(&ScopedRequest::EnumerateDevicesCallbackBody,
+                     AsWeakPtr(),
+                     request_id,
+                     succeeded,
+                     devices));
     } else {
       DCHECK_EQ(request_id_, request_id);
       callback_.Run(request_id, succeeded, devices);
@@ -133,7 +136,7 @@
 
 int32_t PepperDeviceEnumerationHostHelper::OnEnumerateDevices(
     HostMessageContext* context) {
-  if (enumerate_devices_context_.get())
+  if (enumerate_devices_context_)
     return PP_ERROR_INPROGRESS;
 
   enumerate_.reset(new ScopedRequest(
diff --git a/content/renderer/pepper/pepper_directory_reader_host.cc b/content/renderer/pepper/pepper_directory_reader_host.cc
deleted file mode 100644
index 2c3846c..0000000
--- a/content/renderer/pepper/pepper_directory_reader_host.cc
+++ /dev/null
@@ -1,217 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/renderer/pepper/pepper_directory_reader_host.h"
-
-#include "base/compiler_specific.h"
-#include "base/files/file_path.h"
-#include "base/utf_string_conversions.h"
-#include "content/public/renderer/renderer_ppapi_host.h"
-#include "ppapi/c/pp_errors.h"
-#include "ppapi/host/dispatch_host_message.h"
-#include "ppapi/host/ppapi_host.h"
-#include "ppapi/proxy/ppapi_messages.h"
-#include "ppapi/shared_impl/file_type_conversion.h"
-#include "ppapi/shared_impl/ppb_file_ref_shared.h"
-#include "ppapi/thunk/enter.h"
-#include "webkit/fileapi/file_system_callback_dispatcher.h"
-#include "webkit/plugins/ppapi/ppapi_plugin_instance.h"
-#include "webkit/plugins/ppapi/ppb_file_system_impl.h"
-#include "webkit/plugins/ppapi/resource_helper.h"
-
-using ppapi::thunk::EnterResource;
-using ppapi::thunk::PPB_FileRef_API;
-using webkit::ppapi::PPB_FileRef_Impl;
-
-namespace content {
-
-namespace {
-
-std::string FilePathStringToUTF8String(const base::FilePath::StringType& str) {
-#if defined(OS_WIN)
-  return WideToUTF8(str);
-#elif defined(OS_POSIX)
-  return str;
-#else
-#error "Unsupported platform."
-#endif
-}
-
-base::FilePath::StringType UTF8StringToFilePathString(const std::string& str) {
-#if defined(OS_WIN)
-  return UTF8ToWide(str);
-#elif defined(OS_POSIX)
-  return str;
-#else
-#error "Unsupported platform."
-#endif
-}
-
-class ReadDirectoryCallback : public fileapi::FileSystemCallbackDispatcher {
- public:
-  typedef base::Callback<void (const PepperDirectoryReaderHost::Entries&,
-                               bool, int32_t)>
-      OnReadDirectoryCallback;
-
-  explicit ReadDirectoryCallback(const OnReadDirectoryCallback& callback)
-      : callback_(callback) {}
-  virtual ~ReadDirectoryCallback() {}
-
-  virtual void DidSucceed() OVERRIDE {
-    NOTREACHED();
-  }
-
-  virtual void DidReadMetadata(const base::PlatformFileInfo& file_info,
-                               const base::FilePath& platform_path) OVERRIDE {
-    NOTREACHED();
-  }
-
-  virtual void DidCreateSnapshotFile(
-      const base::PlatformFileInfo& file_info,
-      const base::FilePath& platform_path) OVERRIDE {
-    NOTREACHED();
-  }
-
-  virtual void DidReadDirectory(
-      const std::vector<base::FileUtilProxy::Entry>& entries,
-      bool has_more) OVERRIDE {
-    callback_.Run(entries, has_more, PP_OK);
-  }
-
-  virtual void DidOpenFileSystem(const std::string& name,
-                                 const GURL& root) OVERRIDE {
-    NOTREACHED();
-  }
-
-  virtual void DidFail(base::PlatformFileError error) OVERRIDE {
-    callback_.Run(PepperDirectoryReaderHost::Entries(),
-                  false,
-                  ppapi::PlatformFileErrorToPepperError(error));
-  }
-
-  virtual void DidWrite(int64 bytes, bool complete) OVERRIDE {
-    NOTREACHED();
-  }
-
-  virtual void DidOpenFile(base::PlatformFile file) OVERRIDE {
-    NOTREACHED();
-  }
-
- private:
-  OnReadDirectoryCallback callback_;
-};
-
-}  // namespace
-
-PepperDirectoryReaderHost::PepperDirectoryReaderHost(
-    RendererPpapiHost* host,
-    PP_Instance instance,
-    PP_Resource resource)
-    : ResourceHost(host->GetPpapiHost(), instance, resource),
-      renderer_ppapi_host_(host),
-      weak_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
-}
-
-PepperDirectoryReaderHost::~PepperDirectoryReaderHost() {
-}
-
-int32_t PepperDirectoryReaderHost::OnResourceMessageReceived(
-    const IPC::Message& msg,
-    ppapi::host::HostMessageContext* context) {
-  IPC_BEGIN_MESSAGE_MAP(PepperDirectoryReaderHost, msg)
-    PPAPI_DISPATCH_HOST_RESOURCE_CALL(
-        PpapiHostMsg_DirectoryReader_GetEntries, OnGetEntries)
-  IPC_END_MESSAGE_MAP()
-  return PP_ERROR_FAILED;
-}
-
-int32_t PepperDirectoryReaderHost::OnGetEntries(
-    ppapi::host::HostMessageContext* host_context,
-    const ppapi::HostResource& resource) {
-  reply_context_ = host_context->MakeReplyMessageContext();
-
-  EnterResource<PPB_FileRef_API> enter(resource.host_resource(), true);
-  if (enter.failed())
-    return PP_ERROR_FAILED;
-  directory_ref_ = static_cast<PPB_FileRef_Impl*>(enter.object());
-
-  if (directory_ref_->GetFileSystemType() == PP_FILESYSTEMTYPE_EXTERNAL)
-    return PP_ERROR_FAILED;
-
-  webkit::ppapi::PluginInstance* plugin_instance =
-      renderer_ppapi_host_->GetPluginInstance(pp_instance());
-  if (!plugin_instance)
-    return PP_ERROR_FAILED;
-
-  if (!plugin_instance->delegate()->ReadDirectory(
-          directory_ref_->GetFileSystemURL(),
-          new ReadDirectoryCallback(
-              base::Bind(&PepperDirectoryReaderHost::OnReadDirectory,
-                         weak_factory_.GetWeakPtr()))))
-    return PP_ERROR_FAILED;
-  return PP_OK_COMPLETIONPENDING;
-}
-
-void PepperDirectoryReaderHost::OnReadDirectory(const Entries& entries,
-                                                bool has_more,
-                                                int32_t result) {
-  // The current filesystem backend always returns false.
-  DCHECK(!has_more);
-  if (result == PP_OK && !AddNewEntries(entries))
-    result = PP_ERROR_FAILED;
-  SendGetEntriesReply(result);
-}
-
-bool PepperDirectoryReaderHost::AddNewEntries(const Entries& entries) {
-  std::string dir_path = directory_ref_->GetCreateInfo().path;
-  if (dir_path[dir_path.size() - 1] != '/')
-    dir_path += '/';
-  base::FilePath::StringType dir_file_path =
-      UTF8StringToFilePathString(dir_path);
-
-  for (Entries::const_iterator it = entries.begin();
-       it != entries.end(); ++it) {
-    EntryData data;
-    data.file_ref = PPB_FileRef_Impl::CreateInternal(
-        directory_ref_->file_system()->pp_resource(),
-        FilePathStringToUTF8String(dir_file_path + it->name));
-    if (!data.file_ref) {
-      entry_data_.clear();
-      return false;
-    }
-    data.file_type = it->is_directory ?
-                     PP_FILETYPE_DIRECTORY : PP_FILETYPE_REGULAR;
-    entry_data_.push_back(data);
-  }
-
-  return true;
-}
-
-void PepperDirectoryReaderHost::SendGetEntriesReply(int32_t result) {
-  std::vector<ppapi::PPB_FileRef_CreateInfo> host_resources;
-  std::vector<PP_FileType> file_types;
-
-  for (std::vector<EntryData>::iterator it = entry_data_.begin();
-       it != entry_data_.end(); ++it) {
-    // Add a ref count on behalf of the plugin side.
-    it->file_ref->GetReference();
-    host_resources.push_back(it->file_ref->GetCreateInfo());
-    file_types.push_back(it->file_type);
-  }
-  entry_data_.clear();
-
-  reply_context_.params.set_result(result);
-  host()->SendReply(
-      reply_context_,
-      PpapiPluginMsg_DirectoryReader_GetEntriesReply(host_resources,
-                                                     file_types));
-}
-
-PepperDirectoryReaderHost::EntryData::EntryData() {
-}
-
-PepperDirectoryReaderHost::EntryData::~EntryData() {
-}
-
-}  // namespace content
diff --git a/content/renderer/pepper/pepper_directory_reader_host.h b/content/renderer/pepper/pepper_directory_reader_host.h
deleted file mode 100644
index 3c57ee2..0000000
--- a/content/renderer/pepper/pepper_directory_reader_host.h
+++ /dev/null
@@ -1,72 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_RENDERER_PEPPER_PEPPER_DIRECTORY_READER_HOST_H_
-#define CONTENT_RENDERER_PEPPER_PEPPER_DIRECTORY_READER_HOST_H_
-
-#include <vector>
-
-#include "base/basictypes.h"
-#include "base/files/file_util_proxy.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/weak_ptr.h"
-#include "content/common/content_export.h"
-#include "ppapi/c/pp_file_info.h"
-#include "ppapi/host/host_message_context.h"
-#include "ppapi/host/resource_host.h"
-#include "webkit/plugins/ppapi/ppb_file_ref_impl.h"
-
-namespace ppapi {
-struct PPB_FileRef_CreateInfo;
-}
-
-namespace content {
-
-class RendererPpapiHost;
-
-class CONTENT_EXPORT PepperDirectoryReaderHost
-    : public ppapi::host::ResourceHost {
- public:
-  typedef std::vector<base::FileUtilProxy::Entry> Entries;
-
-  PepperDirectoryReaderHost(RendererPpapiHost* host,
-                            PP_Instance instance,
-                            PP_Resource resource);
-  virtual ~PepperDirectoryReaderHost();
-
-  virtual int32_t OnResourceMessageReceived(
-      const IPC::Message& msg,
-      ppapi::host::HostMessageContext* context) OVERRIDE;
-
- private:
-  struct EntryData {
-    EntryData();
-    ~EntryData();
-    scoped_refptr<webkit::ppapi::PPB_FileRef_Impl> file_ref;
-    PP_FileType file_type;
-  };
-
-  int32_t OnGetEntries(ppapi::host::HostMessageContext* host_context,
-                       const ppapi::HostResource& resource);
-  void OnReadDirectory(const Entries& entries, bool has_more, int32_t result);
-  bool AddNewEntries(const Entries& entries);
-
-  void SendGetEntriesReply(int32_t result);
-
-  RendererPpapiHost* renderer_ppapi_host_;
-  ppapi::host::ReplyMessageContext reply_context_;
-
-  scoped_refptr<webkit::ppapi::PPB_FileRef_Impl> directory_ref_;
-
-  // Ensures that the resources are alive for as long as the host is.
-  std::vector<EntryData> entry_data_;
-
-  base::WeakPtrFactory<PepperDirectoryReaderHost> weak_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(PepperDirectoryReaderHost);
-};
-
-}
-
-#endif  // CONTENT_RENDERER_PEPPER_PEPPER_DIRECTORY_READER_HOST_H_
diff --git a/content/renderer/pepper/pepper_file_chooser_host_unittest.cc b/content/renderer/pepper/pepper_file_chooser_host_unittest.cc
index 8517220..b5d2f98 100644
--- a/content/renderer/pepper/pepper_file_chooser_host_unittest.cc
+++ b/content/renderer/pepper/pepper_file_chooser_host_unittest.cc
@@ -31,11 +31,9 @@
 class PepperFileChooserHostTest : public RenderViewTest {
  public:
   PepperFileChooserHostTest()
-      : pp_instance_(123456),
-        old_content_client_(NULL) {}
+      : pp_instance_(123456) {}
 
   virtual void SetUp() {
-    old_content_client_ = GetContentClient();
     SetContentClient(&client_);
     RenderViewTest::SetUp();
 
@@ -45,7 +43,6 @@
     globals_.GetResourceTracker()->DidDeleteInstance(pp_instance_);
 
     RenderViewTest::TearDown();
-    SetContentClient(old_content_client_);
   }
 
   PP_Instance pp_instance() const { return pp_instance_; }
@@ -55,9 +52,6 @@
 
   ppapi::TestGlobals globals_;
   TestContentClient client_;
-
-  // Original value for the content client.
-  ContentClient* old_content_client_;
 };
 
 // For testing to convert our hardcoded file paths to 8-bit.
diff --git a/content/renderer/pepper/pepper_file_io_host.cc b/content/renderer/pepper/pepper_file_io_host.cc
index d0fb617..cec0b3e 100644
--- a/content/renderer/pepper/pepper_file_io_host.cc
+++ b/content/renderer/pepper/pepper_file_io_host.cc
@@ -5,8 +5,13 @@
 #include "content/renderer/pepper/pepper_file_io_host.h"
 
 #include "base/bind.h"
+#include "base/callback.h"
 #include "base/callback_helpers.h"
+#include "base/command_line.h"
 #include "base/files/file_util_proxy.h"
+#include "content/public/common/content_client.h"
+#include "content/public/renderer/content_renderer_client.h"
+#include "content/renderer/pepper/null_file_system_callback_dispatcher.h"
 #include "ppapi/c/pp_errors.h"
 #include "ppapi/host/dispatch_host_message.h"
 #include "ppapi/host/ppapi_host.h"
@@ -14,7 +19,6 @@
 #include "ppapi/shared_impl/file_type_conversion.h"
 #include "ppapi/shared_impl/time_conversion.h"
 #include "ppapi/thunk/enter.h"
-#include "webkit/fileapi/file_system_callback_dispatcher.h"
 #include "webkit/plugins/ppapi/file_callbacks.h"
 #include "webkit/plugins/ppapi/host_globals.h"
 #include "webkit/plugins/ppapi/ppapi_plugin_instance.h"
@@ -44,7 +48,7 @@
 typedef base::Callback<void (base::PlatformFileError)> PlatformGeneralCallback;
 
 class PlatformGeneralCallbackTranslator
-    : public fileapi::FileSystemCallbackDispatcher {
+    : public NullFileSystemCallbackDispatcher {
  public:
   explicit PlatformGeneralCallbackTranslator(
       const PlatformGeneralCallback& callback)
@@ -56,38 +60,8 @@
     callback_.Run(base::PLATFORM_FILE_OK);
   }
 
-  virtual void DidReadMetadata(const base::PlatformFileInfo& file_info,
-                               const base::FilePath& platform_path) OVERRIDE {
-    NOTREACHED();
-  }
-
-  virtual void DidCreateSnapshotFile(
-      const base::PlatformFileInfo& file_info,
-      const base::FilePath& platform_path) OVERRIDE {
-    NOTREACHED();
-  }
-
-  virtual void DidReadDirectory(
-      const std::vector<base::FileUtilProxy::Entry>& entries,
-      bool has_more) OVERRIDE {
-    NOTREACHED();
-  }
-
-  virtual void DidOpenFileSystem(const std::string& name,
-                                 const GURL& root) OVERRIDE {
-    NOTREACHED();
-  }
-
-  virtual void DidFail(base::PlatformFileError error_code) OVERRIDE {
-    callback_.Run(error_code);
-  }
-
-  virtual void DidWrite(int64 bytes, bool complete) OVERRIDE {
-    NOTREACHED();
-  }
-
-  virtual void DidOpenFile(base::PlatformFile file) OVERRIDE {
-    NOTREACHED();
+  virtual void DidFail(base::PlatformFileError platform_error) OVERRIDE {
+    callback_.Run(platform_error);
   }
 
  private:
@@ -109,8 +83,9 @@
     : ResourceHost(host->GetPpapiHost(), instance, resource),
       file_(base::kInvalidPlatformFileValue),
       file_system_type_(PP_FILESYSTEMTYPE_INVALID),
+      quota_policy_(quota::kQuotaLimitTypeUnknown),
       is_running_in_process_(host->IsRunningInProcess()),
-      weak_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
+      weak_factory_(this) {
   // TODO(victorhsieh): eliminate plugin_delegate_ as it's no longer needed.
   webkit::ppapi::PluginInstance* plugin_instance =
       webkit::ppapi::HostGlobals::Get()->GetInstance(instance);
@@ -147,6 +122,8 @@
                                       OnHostMsgWillSetLength)
     PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_FileIO_GetOSFileDescriptor,
                                         OnHostMsgGetOSFileDescriptor)
+    PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_FileIO_RequestOSFileHandle,
+                                        OnHostMsgRequestOSFileHandle)
   IPC_END_MESSAGE_MAP()
   return PP_ERROR_FAILED;
 }
@@ -309,7 +286,7 @@
   if (rv != PP_OK)
     return rv;
 
-  if (quota_file_io_.get()) {
+  if (quota_file_io_) {
     if (!quota_file_io_->Write(
             offset, buffer.c_str(), buffer.size(),
             base::Bind(&PepperFileIOHost::ExecutePlatformWriteCallback,
@@ -410,12 +387,12 @@
   if (rv != PP_OK)
     return rv;
 
-  if (!quota_file_io_.get())
+  if (!quota_file_io_)
     return PP_OK;
 
   if (!quota_file_io_->WillWrite(
           offset, bytes_to_write,
-          base::Bind(&PepperFileIOHost::ExecutePlatformWillWriteCallback,
+          base::Bind(&PepperFileIOHost::ExecutePlatformWriteCallback,
                      weak_factory_.GetWeakPtr(),
                      context->MakeReplyMessageContext())))
     return PP_ERROR_FAILED;
@@ -432,7 +409,7 @@
   if (rv != PP_OK)
     return rv;
 
-  if (!quota_file_io_.get())
+  if (!quota_file_io_)
     return PP_OK;
 
   if (!quota_file_io_->WillSetLength(
@@ -446,22 +423,44 @@
   return PP_OK_COMPLETIONPENDING;
 }
 
+int32_t PepperFileIOHost::OnHostMsgRequestOSFileHandle(
+    ppapi::host::HostMessageContext* context) {
+  if (!is_running_in_process_ &&
+      quota_policy_ != quota::kQuotaLimitTypeUnlimited)
+    return PP_ERROR_FAILED;
+
+  RendererPpapiHost* renderer_ppapi_host =
+      RendererPpapiHost::GetForPPInstance(pp_instance());
+
+  IPC::PlatformFileForTransit file =
+      renderer_ppapi_host->ShareHandleWithRemote(file_, false);
+  if (file == IPC::InvalidPlatformFileForTransit())
+    return PP_ERROR_FAILED;
+  ppapi::host::ReplyMessageContext reply_context =
+      context->MakeReplyMessageContext();
+  reply_context.params.AppendHandle(ppapi::proxy::SerializedHandle(
+      ppapi::proxy::SerializedHandle::FILE, file));
+  host()->SendReply(reply_context,
+                    PpapiPluginMsg_FileIO_RequestOSFileHandleReply());
+  return PP_OK_COMPLETIONPENDING;
+}
+
 int32_t PepperFileIOHost::OnHostMsgGetOSFileDescriptor(
     ppapi::host::HostMessageContext* context) {
   if (!is_running_in_process_)
     return PP_ERROR_FAILED;
+
   int32_t fd =
 #if defined(OS_POSIX)
-    file_;
+      file_;
 #elif defined(OS_WIN)
-    reinterpret_cast<uintptr_t>(file_);
+      reinterpret_cast<uintptr_t>(file_);
 #else
-    -1;  // Platform not supported.
+      -1;
 #endif
-  // TODO(victorhsieh): Pass the file handle in the reply params once this works
-  // in-process.
+
   host()->SendReply(context->MakeReplyMessageContext(),
-      PpapiPluginMsg_FileIO_GetOSFileDescriptorReply(fd));
+                    PpapiPluginMsg_FileIO_GetOSFileDescriptorReply(fd));
   return PP_OK_COMPLETIONPENDING;
 }
 
@@ -502,9 +501,11 @@
     ppapi::host::ReplyMessageContext reply_context,
     base::PlatformFileError error_code,
     base::PassPlatformFile file,
+    quota::QuotaLimitType quota_policy,
     const PluginDelegate::NotifyCloseFileCallback& callback) {
   if (error_code == base::PLATFORM_FILE_OK)
     notify_close_file_callback_ = callback;
+  quota_policy_ = quota_policy;
   ExecutePlatformOpenFileCallback(reply_context, error_code, file);
 }
 
@@ -549,16 +550,6 @@
     ppapi::host::ReplyMessageContext reply_context,
     base::PlatformFileError error_code,
     int bytes_written) {
-  int32_t pp_error = ::ppapi::PlatformFileErrorToPepperError(error_code);
-  reply_context.params.set_result(ErrorOrByteNumber(pp_error, bytes_written));
-  host()->SendReply(reply_context, PpapiPluginMsg_FileIO_GeneralReply());
-  state_manager_.SetOperationFinished();
-}
-
-void PepperFileIOHost::ExecutePlatformWillWriteCallback(
-    ppapi::host::ReplyMessageContext reply_context,
-    base::PlatformFileError error_code,
-    int bytes_written) {
   // On the plugin side, the callback expects a parameter with different meaning
   // depends on whether is negative or not. It is the result here. We translate
   // for the callback.
@@ -569,4 +560,3 @@
 }
 
 }  // namespace content
-
diff --git a/content/renderer/pepper/pepper_file_io_host.h b/content/renderer/pepper/pepper_file_io_host.h
index b66cb6f..505af9c 100644
--- a/content/renderer/pepper/pepper_file_io_host.h
+++ b/content/renderer/pepper/pepper_file_io_host.h
@@ -5,6 +5,7 @@
 #ifndef CONTENT_RENDERER_PEPPER_PEPPER_FILE_IO_HOST_H_
 #define CONTENT_RENDERER_PEPPER_PEPPER_FILE_IO_HOST_H_
 
+#include <set>
 #include <string>
 
 #include "base/basictypes.h"
@@ -58,6 +59,9 @@
                              int64_t length);
   int32_t OnHostMsgClose(ppapi::host::HostMessageContext* context);
   int32_t OnHostMsgFlush(ppapi::host::HostMessageContext* context);
+  // Private API.
+  int32_t OnHostMsgRequestOSFileHandle(
+      ppapi::host::HostMessageContext* context);
   // Trusted API.
   int32_t OnHostMsgGetOSFileDescriptor(
       ppapi::host::HostMessageContext* context);
@@ -80,6 +84,7 @@
       ReplyMessageContext reply_context,
       base::PlatformFileError error_code,
       base::PassPlatformFile file,
+      quota::QuotaLimitType quota_policy,
       const PluginDelegate::NotifyCloseFileCallback& callback);
   void ExecutePlatformQueryCallback(ReplyMessageContext reply_context,
                                     base::PlatformFileError error_code,
@@ -90,9 +95,6 @@
   void ExecutePlatformWriteCallback(ReplyMessageContext reply_context,
                                     base::PlatformFileError error_code,
                                     int bytes_written);
-  void ExecutePlatformWillWriteCallback(ReplyMessageContext reply_context,
-                                        base::PlatformFileError error_code,
-                                        int bytes_written);
 
   // TODO(victorhsieh): eliminate plugin_delegate_ as it's no longer needed.
   webkit::ppapi::PluginDelegate* plugin_delegate_;  // Not owned.
@@ -107,6 +109,9 @@
   // Valid only for PP_FILESYSTEMTYPE_LOCAL{PERSISTENT,TEMPORARY}.
   GURL file_system_url_;
 
+  // Used to check if we can pass file handle to plugins.
+  quota::QuotaLimitType quota_policy_;
+
   // Callback function for notifying when the file handle is closed.
   PluginDelegate::NotifyCloseFileCallback notify_close_file_callback_;
 
@@ -126,4 +131,3 @@
 }  // namespace content
 
 #endif  // CONTENT_RENDERER_PEPPER_PEPPER_FILE_IO_HOST_H_
-
diff --git a/content/renderer/pepper/pepper_file_system_host.cc b/content/renderer/pepper/pepper_file_system_host.cc
new file mode 100644
index 0000000..f29ef65
--- /dev/null
+++ b/content/renderer/pepper/pepper_file_system_host.cc
@@ -0,0 +1,132 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/pepper/pepper_file_system_host.h"
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "content/common/child_thread.h"
+#include "content/common/fileapi/file_system_dispatcher.h"
+#include "content/public/renderer/renderer_ppapi_host.h"
+#include "content/renderer/pepper/null_file_system_callback_dispatcher.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/host/dispatch_host_message.h"
+#include "ppapi/host/ppapi_host.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/shared_impl/file_type_conversion.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/WebPluginContainer.h"
+#include "webkit/plugins/ppapi/ppapi_plugin_instance.h"
+
+namespace content {
+
+namespace {
+
+class PlatformCallbackAdaptor : public NullFileSystemCallbackDispatcher {
+ public:
+  explicit PlatformCallbackAdaptor(
+      const base::WeakPtr<PepperFileSystemHost>& weak_host)
+      : weak_host_(weak_host) {}
+
+  virtual ~PlatformCallbackAdaptor() {}
+
+  virtual void DidOpenFileSystem(const std::string& /* unused */,
+                                 const GURL& root) OVERRIDE {
+    if (weak_host_)
+      weak_host_->OpenFileSystemReply(PP_OK, root);
+  }
+
+  virtual void DidFail(base::PlatformFileError platform_error) OVERRIDE {
+    if (weak_host_) {
+      weak_host_->OpenFileSystemReply(
+          ppapi::PlatformFileErrorToPepperError(platform_error), GURL());
+    }
+  }
+
+ private:
+  base::WeakPtr<PepperFileSystemHost> weak_host_;
+};
+
+}  // namespace
+
+PepperFileSystemHost::PepperFileSystemHost(RendererPpapiHost* host,
+                                           PP_Instance instance,
+                                           PP_Resource resource,
+                                           PP_FileSystemType type)
+    : ResourceHost(host->GetPpapiHost(), instance, resource),
+      renderer_ppapi_host_(host),
+      weak_factory_(this),
+      type_(type),
+      opened_(false),
+      called_open_(false) {
+}
+
+PepperFileSystemHost::~PepperFileSystemHost() {
+}
+
+int32_t PepperFileSystemHost::OnResourceMessageReceived(
+    const IPC::Message& msg,
+    ppapi::host::HostMessageContext* context) {
+  IPC_BEGIN_MESSAGE_MAP(PepperFileSystemHost, msg)
+    PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FileSystem_Open,
+                                      OnHostMsgOpen)
+  IPC_END_MESSAGE_MAP()
+  return PP_ERROR_FAILED;
+}
+
+void PepperFileSystemHost::OpenFileSystemReply(int32_t pp_error,
+                                               const GURL& root) {
+  opened_ = (pp_error == PP_OK);
+  root_url_ = root;
+  reply_context_.params.set_result(pp_error);
+  host()->SendReply(reply_context_,
+                    PpapiPluginMsg_FileSystem_OpenReply());
+  reply_context_ = ppapi::host::ReplyMessageContext();
+}
+
+int32_t PepperFileSystemHost::OnHostMsgOpen(
+    ppapi::host::HostMessageContext* context,
+    int64_t expected_size) {
+  // Not allow multiple opens.
+  if (called_open_)
+    return PP_ERROR_INPROGRESS;
+  called_open_ = true;
+
+  fileapi::FileSystemType file_system_type;
+  switch (type_) {
+    case PP_FILESYSTEMTYPE_LOCALTEMPORARY:
+      file_system_type = fileapi::kFileSystemTypeTemporary;
+      break;
+    case PP_FILESYSTEMTYPE_LOCALPERSISTENT:
+      file_system_type = fileapi::kFileSystemTypePersistent;
+      break;
+    case PP_FILESYSTEMTYPE_EXTERNAL:
+      file_system_type = fileapi::kFileSystemTypeExternal;
+      break;
+    default:
+      return PP_ERROR_FAILED;
+  }
+
+  webkit::ppapi::PluginInstance* plugin_instance =
+      renderer_ppapi_host_->GetPluginInstance(pp_instance());
+  if (!plugin_instance)
+    return PP_ERROR_FAILED;
+
+  FileSystemDispatcher* file_system_dispatcher =
+      ChildThread::current()->file_system_dispatcher();
+  reply_context_ = context->MakeReplyMessageContext();
+  if (!file_system_dispatcher->OpenFileSystem(
+      GURL(plugin_instance->container()->element().document().url()).
+          GetOrigin(),
+      file_system_type, expected_size, true /* create */,
+      new PlatformCallbackAdaptor(weak_factory_.GetWeakPtr()))) {
+    return PP_ERROR_FAILED;
+  }
+
+  return PP_OK_COMPLETIONPENDING;
+}
+
+}  // namespace content
diff --git a/content/renderer/pepper/pepper_file_system_host.h b/content/renderer/pepper/pepper_file_system_host.h
new file mode 100644
index 0000000..92f69a6
--- /dev/null
+++ b/content/renderer/pepper/pepper_file_system_host.h
@@ -0,0 +1,61 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_RENDERER_PEPPER_PEPPER_FILE_SYSTEM_HOST_H_
+#define CONTENT_RENDERER_PEPPER_PEPPER_FILE_SYSTEM_HOST_H_
+
+#include "base/basictypes.h"
+#include "base/memory/weak_ptr.h"
+#include "googleurl/src/gurl.h"
+#include "ppapi/c/pp_file_info.h"
+#include "ppapi/host/host_message_context.h"
+#include "ppapi/host/resource_host.h"
+
+namespace content {
+
+class RendererPpapiHost;
+
+class PepperFileSystemHost :
+    public ppapi::host::ResourceHost,
+    public base::SupportsWeakPtr<PepperFileSystemHost> {
+ public:
+  PepperFileSystemHost(RendererPpapiHost* host,
+                       PP_Instance instance,
+                       PP_Resource resource,
+                       PP_FileSystemType type);
+  virtual ~PepperFileSystemHost();
+
+  // ppapi::host::ResourceHost override.
+  virtual int32_t OnResourceMessageReceived(
+      const IPC::Message& msg,
+      ppapi::host::HostMessageContext* context) OVERRIDE;
+
+  // Supports FileRefs direct access on the host side.
+  PP_FileSystemType GetType() const { return type_; }
+  bool IsOpened() const { return opened_; }
+  GURL GetRootUrl() const { return root_url_; }
+
+  // It's public only to allow PlatformCallbackAdaptor to access.
+  void OpenFileSystemReply(int32_t pp_error,
+                           const GURL& root);
+
+ private:
+  int32_t OnHostMsgOpen(ppapi::host::HostMessageContext* context,
+                        int64_t expected_size);
+
+  RendererPpapiHost* renderer_ppapi_host_;
+  ppapi::host::ReplyMessageContext reply_context_;
+  base::WeakPtrFactory<PepperFileSystemHost> weak_factory_;
+
+  PP_FileSystemType type_;
+  bool opened_;  // whether open is successful.
+  GURL root_url_;
+  bool called_open_;  // whether open has been called.
+
+  DISALLOW_COPY_AND_ASSIGN(PepperFileSystemHost);
+};
+
+}  // namespace content
+
+#endif  // CONTENT_RENDERER_PEPPER_PEPPER_FILE_SYSTEM_HOST_H_
diff --git a/content/renderer/pepper/pepper_graphics_2d_host.cc b/content/renderer/pepper/pepper_graphics_2d_host.cc
index fc5e139..778f4f0 100644
--- a/content/renderer/pepper/pepper_graphics_2d_host.cc
+++ b/content/renderer/pepper/pepper_graphics_2d_host.cc
@@ -189,7 +189,7 @@
       offscreen_flush_pending_(false),
       is_always_opaque_(false),
       scale_(1.0f),
-      weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)),
+      weak_ptr_factory_(this),
       is_running_in_process_(host->IsRunningInProcess()) {
 }
 
@@ -725,7 +725,7 @@
 
 void PepperGraphics2DHost::ScheduleOffscreenFlushAck() {
   offscreen_flush_pending_ = true;
-  MessageLoop::current()->PostDelayedTask(
+  base::MessageLoop::current()->PostDelayedTask(
       FROM_HERE,
       base::Bind(&PepperGraphics2DHost::SendOffscreenFlushAck,
                  weak_ptr_factory_.GetWeakPtr()),
diff --git a/content/renderer/pepper/pepper_in_process_resource_creation.cc b/content/renderer/pepper/pepper_in_process_resource_creation.cc
index d9de4de..4ce8a08 100644
--- a/content/renderer/pepper/pepper_in_process_resource_creation.cc
+++ b/content/renderer/pepper/pepper_in_process_resource_creation.cc
@@ -17,6 +17,7 @@
 #include "ppapi/proxy/browser_font_resource_trusted.h"
 #include "ppapi/proxy/file_chooser_resource.h"
 #include "ppapi/proxy/file_io_resource.h"
+#include "ppapi/proxy/file_system_resource.h"
 #include "ppapi/proxy/graphics_2d_resource.h"
 #include "ppapi/proxy/ppapi_messages.h"
 #include "ppapi/proxy/printing_resource.h"
@@ -26,6 +27,7 @@
 #include "ppapi/shared_impl/ppapi_globals.h"
 #include "ppapi/shared_impl/ppapi_permissions.h"
 #include "ppapi/shared_impl/resource_tracker.h"
+#include "ppapi/shared_impl/var.h"
 #include "webkit/plugins/ppapi/ppapi_plugin_instance.h"
 
 // Note that the code in the creation functions in this file should generally
@@ -64,10 +66,13 @@
 PP_Resource PepperInProcessResourceCreation::CreateFileChooser(
     PP_Instance instance,
     PP_FileChooserMode_Dev mode,
-    const char* accept_types) {
+    const PP_Var& accept_types) {
+  scoped_refptr<ppapi::StringVar> string_var =
+      ppapi::StringVar::FromPPVar(accept_types);
+  std::string str = string_var ? string_var->value() : std::string();
   return (new ppapi::proxy::FileChooserResource(
       host_impl_->in_process_router()->GetPluginConnection(),
-      instance, mode, accept_types))->GetReference();
+      instance, mode, str.c_str()))->GetReference();
 }
 
 PP_Resource PepperInProcessResourceCreation::CreateFileIO(
@@ -77,13 +82,21 @@
       instance))->GetReference();
 }
 
+PP_Resource PepperInProcessResourceCreation::CreateFileSystem(
+    PP_Instance instance,
+    PP_FileSystemType type) {
+  return (new ppapi::proxy::FileSystemResource(
+      host_impl_->in_process_router()->GetPluginConnection(),
+      instance, type))->GetReference();
+}
+
 PP_Resource PepperInProcessResourceCreation::CreateGraphics2D(
     PP_Instance instance,
-    const PP_Size& size,
+    const PP_Size* size,
     PP_Bool is_always_opaque) {
   return (new ppapi::proxy::Graphics2DResource(
           host_impl_->in_process_router()->GetPluginConnection(),
-          instance, size, is_always_opaque))->GetReference();
+          instance, *size, is_always_opaque))->GetReference();
 }
 
 PP_Resource PepperInProcessResourceCreation::CreatePrinting(
@@ -95,17 +108,16 @@
 
 PP_Resource PepperInProcessResourceCreation::CreateTrueTypeFont(
     PP_Instance instance,
-    const PP_TrueTypeFontDesc_Dev& desc) {
+    const PP_TrueTypeFontDesc_Dev* desc) {
   NOTIMPLEMENTED();
   return 0;
 }
 
 PP_Resource PepperInProcessResourceCreation::CreateURLRequestInfo(
-    PP_Instance instance,
-    const ::ppapi::URLRequestInfoData& data) {
+    PP_Instance instance) {
   return (new ppapi::proxy::URLRequestInfoResource(
       host_impl_->in_process_router()->GetPluginConnection(),
-      instance, data))->GetReference();
+      instance, ::ppapi::URLRequestInfoData()))->GetReference();
 }
 
 PP_Resource PepperInProcessResourceCreation::CreateURLResponseInfo(
diff --git a/content/renderer/pepper/pepper_in_process_resource_creation.h b/content/renderer/pepper/pepper_in_process_resource_creation.h
index 4f0d5fa..847320b 100644
--- a/content/renderer/pepper/pepper_in_process_resource_creation.h
+++ b/content/renderer/pepper/pepper_in_process_resource_creation.h
@@ -48,20 +48,21 @@
   virtual PP_Resource CreateFileChooser(
       PP_Instance instance,
       PP_FileChooserMode_Dev mode,
-      const char* accept_types) OVERRIDE;
+      const PP_Var& accept_types) OVERRIDE;
   virtual PP_Resource CreateFileIO(PP_Instance instance) OVERRIDE;
+  virtual PP_Resource CreateFileSystem(PP_Instance instance,
+                                       PP_FileSystemType type) OVERRIDE;
   virtual PP_Resource CreateGraphics2D(
       PP_Instance pp_instance,
-      const PP_Size& size,
+      const PP_Size* size,
       PP_Bool is_always_opaque) OVERRIDE;
   virtual PP_Resource CreatePrinting(
       PP_Instance instance) OVERRIDE;
   virtual PP_Resource CreateTrueTypeFont(
       PP_Instance instance,
-      const struct PP_TrueTypeFontDesc_Dev& desc) OVERRIDE;
+      const struct PP_TrueTypeFontDesc_Dev* desc) OVERRIDE;
   virtual PP_Resource CreateURLRequestInfo(
-      PP_Instance instance,
-      const ::ppapi::URLRequestInfoData& data) OVERRIDE;
+      PP_Instance instance) OVERRIDE;
   virtual PP_Resource CreateURLResponseInfo(
       PP_Instance instance,
       const ::ppapi::URLResponseInfoData& data,
diff --git a/content/renderer/pepper/pepper_in_process_router.cc b/content/renderer/pepper/pepper_in_process_router.cc
index 1cdccc2..acd4226 100644
--- a/content/renderer/pepper/pepper_in_process_router.cc
+++ b/content/renderer/pepper/pepper_in_process_router.cc
@@ -35,7 +35,7 @@
     : host_impl_(host_impl),
       pending_message_id_(0),
       reply_result_(false),
-      weak_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
+      weak_factory_(this) {
   dummy_browser_channel_.reset(
       new Channel(base::Bind(&PepperInProcessRouter::DummySendTo,
                              base::Unretained(this))));
@@ -94,11 +94,11 @@
   } else {
     CHECK(!pending_message_id_);
     // Dispatch plugin messages from the message loop.
-    MessageLoop::current()->PostTask(
+    base::MessageLoop::current()->PostTask(
         FROM_HERE,
         base::Bind(&PepperInProcessRouter::DispatchPluginMsg,
-          weak_factory_.GetWeakPtr(),
-          base::Owned(message.release())));
+                   weak_factory_.GetWeakPtr(),
+                   base::Owned(message.release())));
   }
   return true;
 }
diff --git a/content/renderer/pepper/pepper_platform_audio_input_impl.cc b/content/renderer/pepper/pepper_platform_audio_input_impl.cc
index f71b642..76afa17 100644
--- a/content/renderer/pepper/pepper_platform_audio_input_impl.cc
+++ b/content/renderer/pepper/pepper_platform_audio_input_impl.cc
@@ -9,7 +9,6 @@
 #include "base/message_loop_proxy.h"
 #include "build/build_config.h"
 #include "content/common/child_process.h"
-#include "content/common/media/audio_messages.h"
 #include "content/renderer/media/audio_input_message_filter.h"
 #include "content/renderer/pepper/pepper_plugin_delegate_impl.h"
 #include "content/renderer/render_thread_impl.h"
@@ -55,6 +54,10 @@
 void PepperPlatformAudioInputImpl::ShutDown() {
   DCHECK(main_message_loop_proxy_->BelongsToCurrentThread());
 
+  // Make sure we don't call shutdown more than once.
+  if (!client_)
+    return;
+
   // Called on the main thread to stop all audio callbacks. We must only change
   // the client on the main thread, and the delegates from the I/O thread.
   client_ = NULL;
@@ -80,9 +83,8 @@
   DCHECK_EQ(1, total_segments);
 
   if (base::MessageLoopProxy::current() != main_message_loop_proxy_) {
-    // No need to check |shutdown_called_| here. If shutdown has occurred,
-    // |client_| will be NULL and the handles will be cleaned up on the main
-    // thread.
+    // If shutdown has occurred, |client_| will be NULL and the handles will be
+    // cleaned up on the main thread.
     main_message_loop_proxy_->PostTask(
         FROM_HERE,
         base::Bind(&PepperPlatformAudioInputImpl::OnStreamCreated, this,
@@ -107,7 +109,7 @@
 }
 
 void PepperPlatformAudioInputImpl::OnIPCClosed() {
-  ipc_ = NULL;
+  ipc_.reset();
 }
 
 PepperPlatformAudioInputImpl::~PepperPlatformAudioInputImpl() {
@@ -116,19 +118,14 @@
   // Although these members should be accessed on a specific thread (either the
   // main thread or the I/O thread), it should be fine to examine their value
   // here.
-  DCHECK_EQ(0, stream_id_);
+  DCHECK(!ipc_);
   DCHECK(!client_);
   DCHECK(label_.empty());
-  DCHECK(shutdown_called_);
 }
 
 PepperPlatformAudioInputImpl::PepperPlatformAudioInputImpl()
     : client_(NULL),
-      stream_id_(0),
-      render_view_id_(MSG_ROUTING_NONE),
-      main_message_loop_proxy_(base::MessageLoopProxy::current()),
-      shutdown_called_(false) {
-  ipc_ = RenderThreadImpl::current()->audio_input_message_filter();
+      main_message_loop_proxy_(base::MessageLoopProxy::current()) {
 }
 
 bool PepperPlatformAudioInputImpl::Initialize(
@@ -142,8 +139,10 @@
   if (!plugin_delegate || !client)
     return false;
 
+  ipc_ = RenderThreadImpl::current()->audio_input_message_filter()->
+      CreateAudioInputIPC(plugin_delegate->GetRoutingID());
+
   plugin_delegate_ = plugin_delegate;
-  render_view_id_ = plugin_delegate_->GetRoutingID();
   client_ = client;
 
   params_.Reset(media::AudioParameters::AUDIO_PCM_LINEAR,
@@ -164,26 +163,19 @@
   DCHECK(ChildProcess::current()->io_message_loop_proxy()->
       BelongsToCurrentThread());
 
-  if (shutdown_called_)
+  if (!ipc_)
     return;
 
-  // Make sure we don't call init more than once.
-  DCHECK_EQ(0, stream_id_);
-  stream_id_ = ipc_->AddDelegate(this);
-  DCHECK_NE(0, stream_id_);
-
   // We will be notified by OnStreamCreated().
-  ipc_->CreateStream(stream_id_, session_id, params_, false, 1);
+  ipc_->CreateStream(this, session_id, params_, false, 1);
 }
 
 void PepperPlatformAudioInputImpl::StartCaptureOnIOThread() {
   DCHECK(ChildProcess::current()->io_message_loop_proxy()->
       BelongsToCurrentThread());
 
-  if (stream_id_) {
-    ipc_->AssociateStreamWithConsumer(stream_id_, render_view_id_);
-    ipc_->RecordStream(stream_id_);
-  }
+  if (ipc_)
+    ipc_->RecordStream();
 }
 
 void PepperPlatformAudioInputImpl::StopCaptureOnIOThread() {
@@ -191,24 +183,17 @@
       BelongsToCurrentThread());
 
   // TODO(yzshen): We cannot re-start capturing if the stream is closed.
-  if (stream_id_)
-    ipc_->CloseStream(stream_id_);
+  if (ipc_) {
+    ipc_->CloseStream();
+    ipc_.reset();
+  }
 }
 
 void PepperPlatformAudioInputImpl::ShutDownOnIOThread() {
   DCHECK(ChildProcess::current()->io_message_loop_proxy()->
       BelongsToCurrentThread());
 
-  // Make sure we don't call shutdown more than once.
-  if (shutdown_called_)
-    return;
-  shutdown_called_ = true;
-
-  if (stream_id_) {
-    ipc_->CloseStream(stream_id_);
-    ipc_->RemoveDelegate(stream_id_);
-    stream_id_ = 0;
-  }
+  StopCaptureOnIOThread();
 
   main_message_loop_proxy_->PostTask(
       FROM_HERE,
diff --git a/content/renderer/pepper/pepper_platform_audio_input_impl.h b/content/renderer/pepper/pepper_platform_audio_input_impl.h
index 7d71347..0cfa92d 100644
--- a/content/renderer/pepper/pepper_platform_audio_input_impl.h
+++ b/content/renderer/pepper/pepper_platform_audio_input_impl.h
@@ -9,9 +9,9 @@
 
 #include "base/basictypes.h"
 #include "base/compiler_specific.h"
-#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
 #include "base/memory/weak_ptr.h"
-#include "content/renderer/media/audio_input_message_filter.h"
+#include "media/audio/audio_input_ipc.h"
 #include "media/audio/audio_parameters.h"
 #include "webkit/plugins/ppapi/plugin_delegate.h"
 
@@ -21,7 +21,6 @@
 
 namespace content {
 
-class AudioInputMessageFilter;
 class PepperPluginDelegateImpl;
 
 // PepperPlatformAudioInputImpl is operated on two threads: the main thread (the
@@ -93,15 +92,8 @@
   webkit::ppapi::PluginDelegate::PlatformAudioInputClient* client_;
 
   // Used to send/receive IPC. THIS MUST ONLY BE ACCESSED ON THE
-  // I/O thread except to send messages and get the message loop.
-  scoped_refptr<AudioInputMessageFilter> ipc_;
-
-  // Our ID on the MessageFilter. THIS MUST ONLY BE ACCESSED ON THE I/O THREAD
-  // or else you could race with the initialize function which sets it.
-  int32 stream_id_;
-
-  // The render view into which the audio is sent.
-  int render_view_id_;
+  // I/O THREAD.
+  scoped_ptr<media::AudioInputIPC> ipc_;
 
   base::MessageLoopProxy* main_message_loop_proxy_;
 
@@ -112,10 +104,6 @@
   // THE MAIN THREAD.
   std::string label_;
 
-  // Whether ShutDownOnIOThread() has been called. THIS MUST ONLY BE ACCESSED ON
-  // THE I/O THREAD.
-  bool shutdown_called_;
-
   // Initialized on the main thread and accessed on the I/O thread afterwards.
   media::AudioParameters params_;
 
diff --git a/content/renderer/pepper/pepper_platform_audio_output_impl.cc b/content/renderer/pepper/pepper_platform_audio_output_impl.cc
index 90ec7eb..e53dd6d 100644
--- a/content/renderer/pepper/pepper_platform_audio_output_impl.cc
+++ b/content/renderer/pepper/pepper_platform_audio_output_impl.cc
@@ -5,7 +5,6 @@
 #include "content/renderer/pepper/pepper_platform_audio_output_impl.h"
 
 #include "base/bind.h"
-#include "base/command_line.h"
 #include "base/logging.h"
 #include "base/message_loop_proxy.h"
 #include "build/build_config.h"
@@ -14,7 +13,6 @@
 #include "content/renderer/media/audio_message_filter.h"
 #include "content/renderer/render_thread_impl.h"
 #include "media/base/audio_hardware_config.h"
-#include "media/base/media_switches.h"
 
 namespace content {
 
@@ -97,21 +95,19 @@
 }
 
 void PepperPlatformAudioOutputImpl::OnIPCClosed() {
-  ipc_ = NULL;
+  ipc_.reset();
 }
 
 PepperPlatformAudioOutputImpl::~PepperPlatformAudioOutputImpl() {
   // Make sure we have been shut down. Warning: this will usually happen on
   // the I/O thread!
-  DCHECK_EQ(0, stream_id_);
+  DCHECK(!ipc_);
   DCHECK(!client_);
 }
 
 PepperPlatformAudioOutputImpl::PepperPlatformAudioOutputImpl()
     : client_(NULL),
-      stream_id_(0),
       main_message_loop_proxy_(base::MessageLoopProxy::current()) {
-  ipc_ = RenderThreadImpl::current()->audio_message_filter();
 }
 
 bool PepperPlatformAudioOutputImpl::Initialize(
@@ -122,66 +118,54 @@
   DCHECK(client);
   client_ = client;
 
-  media::AudioParameters::Format format;
-  const int kMaxFramesForLowLatency = 2047;
+  RenderThreadImpl* const render_thread = RenderThreadImpl::current();
+  ipc_ = render_thread->audio_message_filter()->
+      CreateAudioOutputIPC(source_render_view_id);
+  CHECK(ipc_);
 
-  media::AudioHardwareConfig* hardware_config =
-      RenderThreadImpl::current()->GetAudioHardwareConfig();
-
-  const CommandLine* cmd_line = CommandLine::ForCurrentProcess();
-  if (!cmd_line->HasSwitch(switches::kDisableAudioOutputResampler)) {
-    // Rely on AudioOutputResampler to handle any inconsistencies between the
-    // hardware params required for low latency and the requested params.
-    format = media::AudioParameters::AUDIO_PCM_LOW_LATENCY;
-  } else if (sample_rate == hardware_config->GetOutputSampleRate() &&
-             frames_per_buffer <= kMaxFramesForLowLatency &&
-             frames_per_buffer % hardware_config->GetOutputBufferSize() == 0) {
-    // Use the low latency back end if the client request is compatible, and
-    // the sample count is low enough to justify using AUDIO_PCM_LOW_LATENCY.
-    format = media::AudioParameters::AUDIO_PCM_LOW_LATENCY;
-  } else {
-    format = media::AudioParameters::AUDIO_PCM_LINEAR;
-  }
-
-  media::AudioParameters params(format, media::CHANNEL_LAYOUT_STEREO,
-                                sample_rate, 16, frames_per_buffer);
+  media::AudioParameters params(
+      media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
+      media::CHANNEL_LAYOUT_STEREO, sample_rate, 16, frames_per_buffer);
 
   ChildProcess::current()->io_message_loop()->PostTask(
       FROM_HERE,
       base::Bind(&PepperPlatformAudioOutputImpl::InitializeOnIOThread,
-                 this, params, source_render_view_id));
+                 this, params));
   return true;
 }
 
 void PepperPlatformAudioOutputImpl::InitializeOnIOThread(
-    const media::AudioParameters& params, int source_render_view_id) {
-  // Make sure we don't call init more than once.
-  DCHECK_EQ(0, stream_id_);
-  stream_id_ = ipc_->AddDelegate(this);
-  DCHECK_NE(0, stream_id_);
-
-  ipc_->CreateStream(stream_id_, params);
-  ipc_->AssociateStreamWithProducer(stream_id_, source_render_view_id);
+    const media::AudioParameters& params) {
+  DCHECK(ChildProcess::current()->io_message_loop_proxy()->
+      BelongsToCurrentThread());
+  if (ipc_)
+    ipc_->CreateStream(this, params);
 }
 
 void PepperPlatformAudioOutputImpl::StartPlaybackOnIOThread() {
-  if (stream_id_)
-    ipc_->PlayStream(stream_id_);
+  DCHECK(ChildProcess::current()->io_message_loop_proxy()->
+      BelongsToCurrentThread());
+  if (ipc_)
+    ipc_->PlayStream();
 }
 
 void PepperPlatformAudioOutputImpl::StopPlaybackOnIOThread() {
-  if (stream_id_)
-    ipc_->PauseStream(stream_id_);
+  DCHECK(ChildProcess::current()->io_message_loop_proxy()->
+      BelongsToCurrentThread());
+  if (ipc_)
+    ipc_->PauseStream();
 }
 
 void PepperPlatformAudioOutputImpl::ShutDownOnIOThread() {
+  DCHECK(ChildProcess::current()->io_message_loop_proxy()->
+      BelongsToCurrentThread());
+
   // Make sure we don't call shutdown more than once.
-  if (!stream_id_)
+  if (!ipc_)
     return;
 
-  ipc_->CloseStream(stream_id_);
-  ipc_->RemoveDelegate(stream_id_);
-  stream_id_ = 0;
+  ipc_->CloseStream();
+  ipc_.reset();
 
   Release();  // Release for the delegate, balances out the reference taken in
               // PepperPluginDelegateImpl::CreateAudio.
diff --git a/content/renderer/pepper/pepper_platform_audio_output_impl.h b/content/renderer/pepper/pepper_platform_audio_output_impl.h
index 0be7588..b8eb05d 100644
--- a/content/renderer/pepper/pepper_platform_audio_output_impl.h
+++ b/content/renderer/pepper/pepper_platform_audio_output_impl.h
@@ -7,6 +7,7 @@
 
 #include "base/basictypes.h"
 #include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
 #include "media/audio/audio_output_ipc.h"
 #include "webkit/plugins/ppapi/plugin_delegate.h"
 
@@ -20,8 +21,6 @@
 
 namespace content {
 
-class AudioMessageFilter;
-
 class PepperPlatformAudioOutputImpl
     : public webkit::ppapi::PluginDelegate::PlatformAudioOutput,
       public media::AudioOutputIPCDelegate,
@@ -63,8 +62,7 @@
       webkit::ppapi::PluginDelegate::PlatformAudioOutputClient* client);
 
   // I/O thread backends to above functions.
-  void InitializeOnIOThread(const media::AudioParameters& params,
-                            int source_render_view_id);
+  void InitializeOnIOThread(const media::AudioParameters& params);
   void StartPlaybackOnIOThread();
   void StopPlaybackOnIOThread();
   void ShutDownOnIOThread();
@@ -75,11 +73,7 @@
 
   // Used to send/receive IPC. THIS MUST ONLY BE ACCESSED ON THE
   // I/O thread except to send messages and get the message loop.
-  scoped_refptr<AudioMessageFilter> ipc_;
-
-  // Our ID on the MessageFilter. THIS MUST ONLY BE ACCESSED ON THE I/O THREAD
-  // or else you could race with the initialize function which sets it.
-  int32 stream_id_;
+  scoped_ptr<media::AudioOutputIPC> ipc_;
 
   base::MessageLoopProxy* main_message_loop_proxy_;
 
diff --git a/content/renderer/pepper/pepper_platform_context_3d_impl.cc b/content/renderer/pepper/pepper_platform_context_3d_impl.cc
index 2a839ae..09e5935 100644
--- a/content/renderer/pepper/pepper_platform_context_3d_impl.cc
+++ b/content/renderer/pepper/pepper_platform_context_3d_impl.cc
@@ -24,7 +24,7 @@
     : parent_texture_id_(0),
       has_alpha_(false),
       command_buffer_(NULL),
-      weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
+      weak_ptr_factory_(this) {
 }
 
 PlatformContext3DImpl::~PlatformContext3DImpl() {
@@ -53,7 +53,7 @@
 
   channel_ = render_thread->EstablishGpuChannelSync(
       CAUSE_FOR_GPU_LAUNCH_PEPPERPLATFORMCONTEXT3DIMPL_INITIALIZE);
-  if (!channel_.get())
+  if (!channel_)
     return false;
   DCHECK(channel_->state() == GpuChannelHost::kConnected);
 
diff --git a/content/renderer/pepper/pepper_platform_image_2d_impl.cc b/content/renderer/pepper/pepper_platform_image_2d_impl.cc
index dcad9ce..4a0b4f1 100644
--- a/content/renderer/pepper/pepper_platform_image_2d_impl.cc
+++ b/content/renderer/pepper/pepper_platform_image_2d_impl.cc
@@ -22,7 +22,7 @@
 // On Mac, we have to tell the browser to free the transport DIB.
 PepperPlatformImage2DImpl::~PepperPlatformImage2DImpl() {
 #if defined(OS_MACOSX)
-  if (dib_.get()) {
+  if (dib_) {
     RenderThreadImpl::current()->Send(
         new ViewHostMsg_FreeTransportDIB(dib_->id()));
   }
diff --git a/content/renderer/pepper/pepper_platform_video_capture_impl.cc b/content/renderer/pepper/pepper_platform_video_capture_impl.cc
index 35bfd58..39ee609 100644
--- a/content/renderer/pepper/pepper_platform_video_capture_impl.cc
+++ b/content/renderer/pepper/pepper_platform_video_capture_impl.cc
@@ -21,9 +21,8 @@
     : plugin_delegate_(plugin_delegate),
       device_id_(device_id),
       session_id_(0),
-      ALLOW_THIS_IN_INITIALIZER_LIST(
-          handler_proxy_(new media::VideoCaptureHandlerProxy(
-              this, base::MessageLoopProxy::current()))),
+      handler_proxy_(new media::VideoCaptureHandlerProxy(
+          this, base::MessageLoopProxy::current())),
       handler_(handler),
       video_capture_(NULL),
       unbalanced_start_(false) {
diff --git a/content/renderer/pepper/pepper_plugin_delegate_impl.cc b/content/renderer/pepper/pepper_plugin_delegate_impl.cc
index d2be7cc..110e1bc 100644
--- a/content/renderer/pepper/pepper_plugin_delegate_impl.cc
+++ b/content/renderer/pepper/pepper_plugin_delegate_impl.cc
@@ -43,6 +43,7 @@
 #include "content/renderer/pepper/content_renderer_pepper_host_factory.h"
 #include "content/renderer/pepper/pepper_broker_impl.h"
 #include "content/renderer/pepper/pepper_device_enumeration_event_handler.h"
+#include "content/renderer/pepper/pepper_file_system_host.h"
 #include "content/renderer/pepper/pepper_hung_plugin_filter.h"
 #include "content/renderer/pepper/pepper_in_process_resource_creation.h"
 #include "content/renderer/pepper/pepper_platform_audio_input_impl.h"
@@ -254,16 +255,18 @@
   webkit::ppapi::PluginInstance* plugin_;
 };
 
+void DoNotifyCloseFile(int file_open_id, base::PlatformFileError /* unused */) {
+  ChildThread::current()->file_system_dispatcher()->NotifyCloseFile(
+      file_open_id);
+}
+
 class AsyncOpenFileSystemURLCallbackTranslator
     : public fileapi::FileSystemCallbackDispatcher {
  public:
   AsyncOpenFileSystemURLCallbackTranslator(
       const webkit::ppapi::PluginDelegate::AsyncOpenFileSystemURLCallback&
-          callback,
-      const webkit::ppapi::PluginDelegate::NotifyCloseFileCallback&
-          close_file_callback)
-    : callback_(callback),
-      close_file_callback_(close_file_callback) {
+          callback)
+    : callback_(callback) {
   }
 
   virtual ~AsyncOpenFileSystemURLCallbackTranslator() {}
@@ -295,6 +298,7 @@
     base::PlatformFile invalid_file = base::kInvalidPlatformFileValue;
     callback_.Run(error_code,
                   base::PassPlatformFile(&invalid_file),
+                  quota::kQuotaLimitTypeUnknown,
                   webkit::ppapi::PluginDelegate::NotifyCloseFileCallback());
   }
 
@@ -302,27 +306,25 @@
     NOTREACHED();
   }
 
-  virtual void DidOpenFile(base::PlatformFile file) OVERRIDE {
+  virtual void DidOpenFile(base::PlatformFile file,
+                           int file_open_id,
+                           quota::QuotaLimitType quota_policy) OVERRIDE {
     callback_.Run(base::PLATFORM_FILE_OK,
                   base::PassPlatformFile(&file),
-                  close_file_callback_);
+                  quota_policy,
+                  base::Bind(&DoNotifyCloseFile, file_open_id));
     // Make sure we won't leak file handle if the requester has died.
     if (file != base::kInvalidPlatformFileValue) {
       base::FileUtilProxy::Close(
           RenderThreadImpl::current()->GetFileThreadMessageLoopProxy(), file,
-          close_file_callback_);
+          base::Bind(&DoNotifyCloseFile, file_open_id));
     }
   }
 
  private:
   webkit::ppapi::PluginDelegate::AsyncOpenFileSystemURLCallback callback_;
-  webkit::ppapi::PluginDelegate::NotifyCloseFileCallback close_file_callback_;
 };
 
-void DoNotifyCloseFile(const GURL& path, base::PlatformFileError /* unused */) {
-  ChildThread::current()->file_system_dispatcher()->NotifyCloseFile(path);
-}
-
 void CreateHostForInProcessModule(RenderViewImpl* render_view,
                                   webkit::ppapi::PluginModule* module,
                                   const webkit::WebPluginInfo& webplugin_info) {
@@ -340,6 +342,16 @@
   render_view->PpapiPluginCreated(host_impl);
 }
 
+template <typename HostType>
+const HostType* GetRendererResourceHost(
+    PP_Instance instance, PP_Resource resource) {
+  const ppapi::host::PpapiHost* ppapi_host =
+      RendererPpapiHost::GetForPPInstance(instance)->GetPpapiHost();
+  if (!resource || !ppapi_host)
+    return NULL;
+  return static_cast<HostType*>(ppapi_host->GetResourceHost(resource));
+}
+
 }  // namespace
 
 PepperPluginDelegateImpl::PepperPluginDelegateImpl(RenderViewImpl* render_view)
@@ -830,7 +842,7 @@
   // If accelerated compositing of plugins is disabled, fail to create a 3D
   // context, because it won't be visible. This allows graceful fallback in the
   // modules.
-  const webkit_glue::WebPreferences& prefs = render_view_->webkit_preferences();
+  const WebPreferences& prefs = render_view_->webkit_preferences();
   if (!prefs.accelerated_compositing_for_plugins_enabled)
     return NULL;
   return new PlatformContext3DImpl;
@@ -915,9 +927,9 @@
 
   scoped_refptr<PepperBrokerImpl> broker =
       static_cast<PepperBrokerImpl*>(plugin_module->GetBroker());
-  if (!broker.get()) {
+  if (!broker) {
     broker = CreateBroker(plugin_module);
-    if (!broker.get())
+    if (!broker)
       return NULL;
   }
 
@@ -1016,15 +1028,25 @@
   last_mouse_event_target_ = NULL;
 }
 
-bool PepperPluginDelegateImpl::OpenFileSystem(
-    const GURL& origin_url,
-    fileapi::FileSystemType type,
-    long long size,
-    fileapi::FileSystemCallbackDispatcher* dispatcher) {
-  FileSystemDispatcher* file_system_dispatcher =
-      ChildThread::current()->file_system_dispatcher();
-  return file_system_dispatcher->OpenFileSystem(
-      origin_url, type, size, true /* create */, dispatcher);
+bool PepperPluginDelegateImpl::IsFileSystemOpened(PP_Instance instance,
+                                                  PP_Resource resource) const {
+  const PepperFileSystemHost* host =
+      GetRendererResourceHost<PepperFileSystemHost>(instance, resource);
+  return host && host->IsOpened();
+}
+
+PP_FileSystemType PepperPluginDelegateImpl::GetFileSystemType(
+    PP_Instance instance, PP_Resource resource) const {
+  const PepperFileSystemHost* host =
+      GetRendererResourceHost<PepperFileSystemHost>(instance, resource);
+  return host ? host->GetType() : PP_FILESYSTEMTYPE_INVALID;
+}
+
+GURL PepperPluginDelegateImpl::GetFileSystemRootUrl(
+    PP_Instance instance, PP_Resource resource) const {
+  const PepperFileSystemHost* host =
+      GetRendererResourceHost<PepperFileSystemHost>(instance, resource);
+  return host ? host->GetRootUrl() : GURL();
 }
 
 bool PepperPluginDelegateImpl::MakeDirectory(
@@ -1045,6 +1067,14 @@
   return file_system_dispatcher->ReadMetadata(path, dispatcher);
 }
 
+bool PepperPluginDelegateImpl::ReadDirectoryEntries(
+    const GURL& path,
+    fileapi::FileSystemCallbackDispatcher* dispatcher) {
+  FileSystemDispatcher* file_system_dispatcher =
+      ChildThread::current()->file_system_dispatcher();
+  return file_system_dispatcher->ReadDirectory(path, dispatcher);
+}
+
 bool PepperPluginDelegateImpl::Touch(
     const GURL& path,
     const base::Time& last_access_time,
@@ -1115,8 +1145,7 @@
       ChildThread::current()->file_system_dispatcher();
   return file_system_dispatcher->OpenFile(path, flags,
       new AsyncOpenFileSystemURLCallbackTranslator(
-          callback,
-          base::Bind(&DoNotifyCloseFile, path)));
+          callback));
 }
 
 void PepperPluginDelegateImpl::SyncGetFileSystemPlatformPath(
@@ -1355,7 +1384,7 @@
 }
 
 void PepperPluginDelegateImpl::SampleGamepads(WebKit::WebGamepads* data) {
-  if (!gamepad_shared_memory_reader_.get())
+  if (!gamepad_shared_memory_reader_)
     gamepad_shared_memory_reader_.reset(new GamepadSharedMemoryReader);
   gamepad_shared_memory_reader_->SampleGamepads(*data);
 }
@@ -1377,11 +1406,12 @@
       PepperDeviceEnumerationEventHandler::FromPepperDeviceType(type),
       GURL());
 #else
-  MessageLoop::current()->PostTask(
+  base::MessageLoop::current()->PostTask(
       FROM_HERE,
       base::Bind(
           &PepperDeviceEnumerationEventHandler::OnDevicesEnumerationFailed,
-          device_enumeration_event_handler_->AsWeakPtr(), request_id));
+          device_enumeration_event_handler_->AsWeakPtr(),
+          request_id));
 #endif
 
   return request_id;
@@ -1394,12 +1424,12 @@
 #if defined(ENABLE_WEBRTC)
   // Need to post task since this function might be called inside the callback
   // of EnumerateDevices.
-  MessageLoop::current()->PostTask(
+  base::MessageLoop::current()->PostTask(
       FROM_HERE,
-      base::Bind(
-          &MediaStreamDispatcher::StopEnumerateDevices,
-          render_view_->media_stream_dispatcher()->AsWeakPtr(),
-          request_id, device_enumeration_event_handler_.get()->AsWeakPtr()));
+      base::Bind(&MediaStreamDispatcher::StopEnumerateDevices,
+                 render_view_->media_stream_dispatcher()->AsWeakPtr(),
+                 request_id,
+                 device_enumeration_event_handler_.get()->AsWeakPtr()));
 #endif
 }
 
@@ -1541,10 +1571,11 @@
       PepperDeviceEnumerationEventHandler::FromPepperDeviceType(type),
       GURL());
 #else
-  MessageLoop::current()->PostTask(
+  base::MessageLoop::current()->PostTask(
       FROM_HERE,
       base::Bind(&PepperDeviceEnumerationEventHandler::OnDeviceOpenFailed,
-                 device_enumeration_event_handler_->AsWeakPtr(), request_id));
+                 device_enumeration_event_handler_->AsWeakPtr(),
+                 request_id));
 #endif
 
   return request_id;
@@ -1619,4 +1650,10 @@
       should_close_source);
 }
 
+bool PepperPluginDelegateImpl::IsRunningInProcess(PP_Instance instance) const {
+  RendererPpapiHostImpl* host =
+      RendererPpapiHostImpl::GetForPPInstance(instance);
+  return host && host->IsRunningInProcess();
+}
+
 }  // namespace content
diff --git a/content/renderer/pepper/pepper_plugin_delegate_impl.h b/content/renderer/pepper/pepper_plugin_delegate_impl.h
index d8b2e17..2f178ef 100644
--- a/content/renderer/pepper/pepper_plugin_delegate_impl.h
+++ b/content/renderer/pepper/pepper_plugin_delegate_impl.h
@@ -19,6 +19,7 @@
 #include "content/public/renderer/render_view_observer.h"
 #include "content/renderer/mouse_lock_dispatcher.h"
 #include "content/renderer/render_view_pepper_helper.h"
+#include "ppapi/c/pp_file_info.h"
 #include "ppapi/shared_impl/private/ppb_tcp_server_socket_shared.h"
 #include "ppapi/shared_impl/private/tcp_socket_private_impl.h"
 #include "ui/base/ime/text_input_type.h"
@@ -204,11 +205,13 @@
       const GURL& path,
       int flags,
       const AsyncOpenFileSystemURLCallback& callback) OVERRIDE;
-  virtual bool OpenFileSystem(
-      const GURL& origin_url,
-      fileapi::FileSystemType type,
-      long long size,
-      fileapi::FileSystemCallbackDispatcher* dispatcher) OVERRIDE;
+  virtual bool IsFileSystemOpened(PP_Instance instance,
+                                  PP_Resource resource) const OVERRIDE;
+  virtual PP_FileSystemType GetFileSystemType(
+      PP_Instance instance,
+      PP_Resource resource) const OVERRIDE;
+  virtual GURL GetFileSystemRootUrl(PP_Instance instance,
+                                    PP_Resource resource) const OVERRIDE;
   virtual bool MakeDirectory(
       const GURL& path,
       bool recursive,
@@ -216,6 +219,9 @@
   virtual bool Query(
       const GURL& path,
       fileapi::FileSystemCallbackDispatcher* dispatcher) OVERRIDE;
+  virtual bool ReadDirectoryEntries(
+      const GURL& path,
+      fileapi::FileSystemCallbackDispatcher* dispatcher) OVERRIDE;
   virtual bool Touch(
       const GURL& path,
       const base::Time& last_access_time,
@@ -393,6 +399,8 @@
       base::ProcessId target_process_id,
       bool should_close_source) const OVERRIDE;
 
+  virtual bool IsRunningInProcess(PP_Instance instance) const OVERRIDE;
+
   // Pointer to the RenderView that owns us.
   RenderViewImpl* render_view_;
 
diff --git a/content/renderer/pepper/pepper_truetype_font_host.cc b/content/renderer/pepper/pepper_truetype_font_host.cc
index c94c1f6..ea9bb12 100644
--- a/content/renderer/pepper/pepper_truetype_font_host.cc
+++ b/content/renderer/pepper/pepper_truetype_font_host.cc
@@ -26,7 +26,7 @@
     : ResourceHost(host->GetPpapiHost(), instance, resource),
       renderer_ppapi_host_(host),
       font_(PepperTrueTypeFont::Create(desc)),
-      weak_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
+      weak_factory_(this) {
 }
 
 PepperTrueTypeFontHost::~PepperTrueTypeFontHost() {
diff --git a/content/renderer/pepper/pepper_truetype_font_linux.cc b/content/renderer/pepper/pepper_truetype_font_linux.cc
index f59df68..2e3326a 100644
--- a/content/renderer/pepper/pepper_truetype_font_linux.cc
+++ b/content/renderer/pepper/pepper_truetype_font_linux.cc
@@ -2,15 +2,158 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "base/compiler_specific.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/safe_numerics.h"
+#include "base/sys_byteorder.h"
+#include "content/public/common/child_process_sandbox_support_linux.h"
 #include "content/renderer/pepper/pepper_truetype_font.h"
+#include "ppapi/c/dev/ppb_truetype_font_dev.h"
+#include "ppapi/c/pp_errors.h"
 
 namespace content {
 
+namespace {
+
+class PepperTrueTypeFontLinux : public PepperTrueTypeFont {
+ public:
+  explicit PepperTrueTypeFontLinux(
+      const ppapi::proxy::SerializedTrueTypeFontDesc& desc);
+  virtual ~PepperTrueTypeFontLinux() OVERRIDE;
+
+  // PepperTrueTypeFont overrides.
+  virtual bool IsValid() OVERRIDE;
+  virtual int32_t Describe(
+      ppapi::proxy::SerializedTrueTypeFontDesc* desc) OVERRIDE;
+  virtual int32_t GetTableTags(std::vector<uint32_t>* tags) OVERRIDE;
+  virtual int32_t GetTable(uint32_t table_tag,
+                           int32_t offset,
+                           int32_t max_data_length,
+                           std::string* data) OVERRIDE;
+ private:
+  // Save creation parameters here and use these to implement Describe.
+  // TODO(bbudge) Modify content API to return results of font matching and
+  // fallback.
+  ppapi::proxy::SerializedTrueTypeFontDesc desc_;
+  int fd_;
+
+  DISALLOW_COPY_AND_ASSIGN(PepperTrueTypeFontLinux);
+};
+
+PepperTrueTypeFontLinux::PepperTrueTypeFontLinux(
+    const ppapi::proxy::SerializedTrueTypeFontDesc& desc) :
+    desc_(desc) {
+  // If no face is provided, convert family to the platform defaults. These
+  // names should be mapped by FontConfig to an appropriate default font.
+  if (desc_.family.empty()) {
+    switch (desc_.generic_family) {
+      case PP_TRUETYPEFONTFAMILY_SERIF:
+        desc_.family = "serif";
+        break;
+      case PP_TRUETYPEFONTFAMILY_SANSSERIF:
+        desc_.family = "sans-serif";
+        break;
+      case PP_TRUETYPEFONTFAMILY_CURSIVE:
+        desc_.family = "cursive";
+        break;
+      case PP_TRUETYPEFONTFAMILY_FANTASY:
+        desc_.family = "fantasy";
+        break;
+      case PP_TRUETYPEFONTFAMILY_MONOSPACE:
+        desc_.family = "monospace";
+        break;
+    }
+  }
+
+  fd_ = content::MatchFontWithFallback(
+            desc_.family.c_str(),
+            desc_.weight >= PP_TRUETYPEFONTWEIGHT_BOLD,
+            desc_.style & PP_TRUETYPEFONTSTYLE_ITALIC,
+            desc_.charset);
+}
+
+PepperTrueTypeFontLinux::~PepperTrueTypeFontLinux() {
+}
+
+bool PepperTrueTypeFontLinux::IsValid() {
+  return fd_ != -1;
+}
+
+int32_t PepperTrueTypeFontLinux::Describe(
+      ppapi::proxy::SerializedTrueTypeFontDesc* desc) {
+  *desc = desc_;
+  return PP_OK;
+}
+
+int32_t PepperTrueTypeFontLinux::GetTableTags(std::vector<uint32_t>* tags) {
+  // Get the 2 byte numTables field at an offset of 4 in the font.
+  uint8_t num_tables_buf[2];
+  size_t output_length = sizeof(num_tables_buf);
+  if (!content::GetFontTable(fd_,
+                             0 /* tag */,
+                             4 /* offset */,
+                             reinterpret_cast<uint8_t*>(&num_tables_buf),
+                             &output_length))
+    return PP_ERROR_FAILED;
+  DCHECK(output_length == sizeof(num_tables_buf));
+  // Font data is stored in big-endian order.
+  uint16_t num_tables = (num_tables_buf[0] << 8) | num_tables_buf[1];
+
+  // The font has a header, followed by n table entries in its directory.
+  static const size_t kFontHeaderSize = 12;
+  static const size_t kTableEntrySize = 16;
+  output_length = num_tables * kTableEntrySize;
+  scoped_ptr<uint8_t[]> table_entries(new uint8_t[output_length]);
+  // Get the table directory entries, which follow the font header.
+  if (!content::GetFontTable(fd_,
+                             0 /* tag */,
+                             kFontHeaderSize /* offset */,
+                             table_entries.get(),
+                             &output_length))
+    return PP_ERROR_FAILED;
+  DCHECK(output_length == num_tables * kTableEntrySize);
+
+  tags->resize(num_tables);
+  for (uint16_t i = 0; i < num_tables; i++) {
+    uint8_t* entry = table_entries.get() + i * kTableEntrySize;
+    uint32_t tag = static_cast<uint32_t>(entry[0]) << 24 |
+                   static_cast<uint32_t>(entry[1]) << 16 |
+                   static_cast<uint32_t>(entry[2]) << 8  |
+                   static_cast<uint32_t>(entry[3]);
+    (*tags)[i] = tag;
+  }
+
+  return num_tables;
+}
+
+int32_t PepperTrueTypeFontLinux::GetTable(uint32_t table_tag,
+                                          int32_t offset,
+                                          int32_t max_data_length,
+                                          std::string* data) {
+  // Get the size of the font data first.
+  size_t table_size = 0;
+  // Tags are byte swapped on Linux.
+  table_tag = base::ByteSwap(table_tag);
+  if (!content::GetFontTable(fd_, table_tag, offset, NULL, &table_size))
+    return PP_ERROR_FAILED;
+  // Only retrieve as much as the caller requested.
+  table_size = std::min(table_size, static_cast<size_t>(max_data_length));
+  data->resize(table_size);
+  if (!content::GetFontTable(fd_, table_tag, offset,
+                             reinterpret_cast<uint8_t*>(&(*data)[0]),
+                             &table_size))
+    return PP_ERROR_FAILED;
+
+  return base::checked_numeric_cast<int32_t>(table_size);
+}
+
+}  // namespace
+
 // static
 PepperTrueTypeFont* PepperTrueTypeFont::Create(
     const ppapi::proxy::SerializedTrueTypeFontDesc& desc) {
-  NOTIMPLEMENTED();
-  return 0;
+  return new PepperTrueTypeFontLinux(desc);
 }
 
 }  // namespace content
+
diff --git a/content/renderer/pepper/pepper_truetype_font_mac.mm b/content/renderer/pepper/pepper_truetype_font_mac.mm
index f59df68..b37c0fe 100644
--- a/content/renderer/pepper/pepper_truetype_font_mac.mm
+++ b/content/renderer/pepper/pepper_truetype_font_mac.mm
@@ -4,13 +4,408 @@
 
 #include "content/renderer/pepper/pepper_truetype_font.h"
 
+#import <ApplicationServices/ApplicationServices.h>
+
+#include <stdio.h>
+
+#include "base/compiler_specific.h"
+#include "base/mac/foundation_util.h"
+#include "base/mac/scoped_cftyperef.h"
+#include "base/mac/scoped_nsautorelease_pool.h"
+#include "base/safe_numerics.h"
+#include "base/strings/sys_string_conversions.h"
+#include "base/sys_byteorder.h"
+#include "ppapi/c/dev/ppb_truetype_font_dev.h"
+#include "ppapi/c/pp_errors.h"
+
 namespace content {
 
+namespace {
+
+static bool FindFloat(CFDictionaryRef dict, CFStringRef name, float* value) {
+  CFNumberRef num;
+  return
+      CFDictionaryGetValueIfPresent(dict, name,
+                                    reinterpret_cast<const void**>(&num)) &&
+      CFNumberIsFloatType(num) &&
+      CFNumberGetValue(num, kCFNumberFloatType, value);
+}
+
+float GetMacWeight(PP_TrueTypeFontWeight_Dev weight) {
+  // Map values from NORMAL (400) to HEAVY (900) to the range [0 .. 1], and
+  // values below NORMAL to the range [-0.6 .. 0]. NORMAL should map to 0.
+  float normal = PP_TRUETYPEFONTWEIGHT_NORMAL;
+  float heavy = PP_TRUETYPEFONTWEIGHT_HEAVY;
+  return (weight - normal) / (heavy - normal);
+}
+
+PP_TrueTypeFontWeight_Dev GetPepperWeight(float weight) {
+  // Perform the inverse mapping of GetMacWeight.
+  return static_cast<PP_TrueTypeFontWeight_Dev>(
+      weight * (PP_TRUETYPEFONTWEIGHT_HEAVY - PP_TRUETYPEFONTWEIGHT_NORMAL) +
+      PP_TRUETYPEFONTWEIGHT_NORMAL);
+}
+
+float GetMacWidth(PP_TrueTypeFontWidth_Dev width) {
+  // Map values from NORMAL (4) to ULTRA_EXPANDED (8) to the range [0 .. 1],
+  // and values below NORMAL to the range [-1 .. 0]. Normal should map to 0.
+  float normal = PP_TRUETYPEFONTWIDTH_NORMAL;
+  float ultra_expanded = PP_TRUETYPEFONTWIDTH_ULTRAEXPANDED;
+  return (width - normal) / (ultra_expanded - normal);
+}
+
+PP_TrueTypeFontWidth_Dev GetPepperWidth(float width) {
+  // Perform the inverse mapping of GetMacWeight.
+  return static_cast<PP_TrueTypeFontWidth_Dev>(
+      width *
+      (PP_TRUETYPEFONTWIDTH_ULTRAEXPANDED - PP_TRUETYPEFONTWIDTH_NORMAL) +
+      PP_TRUETYPEFONTWIDTH_NORMAL);
+}
+
+#define MAKE_TABLE_TAG(a, b, c, d) ((a) << 24) + ((b) << 16) + ((c) << 8) + (d)
+
+// TrueType font header and table entry structs. See
+// https://developer.apple.com/fonts/TTRefMan/RM06/Chap6.html
+struct FontHeader {
+  int32_t font_type;
+  uint16_t num_tables;
+  uint16_t search_range;
+  uint16_t entry_selector;
+  uint16_t range_shift;
+};
+static_assert(sizeof(FontHeader) == 12, "FontHeader wrong size");
+
+struct FontDirectoryEntry {
+  uint32_t tag;
+  uint32_t checksum;
+  uint32_t offset;
+  uint32_t logical_length;
+};
+static_assert(sizeof(FontDirectoryEntry) == 16,
+              "FontDirectoryEntry wrong size");
+
+uint32_t CalculateChecksum(char* table, int32_t table_length) {
+  uint32_t sum = 0;
+  uint32_t* current = reinterpret_cast<uint32_t*>(table);
+  uint32_t length = (table_length + 3) / 4;
+  // Raw font data is big-endian.
+  while (length-- > 0)
+    sum += base::NetToHost32(*current++);
+  return sum;
+}
+
+class PepperTrueTypeFontMac : public PepperTrueTypeFont {
+ public:
+  explicit PepperTrueTypeFontMac(
+      const ppapi::proxy::SerializedTrueTypeFontDesc& desc);
+  virtual ~PepperTrueTypeFontMac() OVERRIDE;
+
+  // PepperTrueTypeFont overrides.
+  virtual bool IsValid() OVERRIDE;
+  virtual int32_t Describe(
+      ppapi::proxy::SerializedTrueTypeFontDesc* desc) OVERRIDE;
+  virtual int32_t GetTableTags(std::vector<uint32_t>* tags) OVERRIDE;
+  virtual int32_t GetTable(uint32_t table_tag,
+                           int32_t offset,
+                           int32_t max_data_length,
+                           std::string* data) OVERRIDE;
+ private:
+  virtual int32_t GetEntireFont(int32_t offset,
+                                int32_t max_data_length,
+                                std::string* data);
+
+  base::mac::ScopedCFTypeRef<CTFontRef> font_ref_;
+
+  DISALLOW_COPY_AND_ASSIGN(PepperTrueTypeFontMac);
+};
+
+PepperTrueTypeFontMac::PepperTrueTypeFontMac(
+    const ppapi::proxy::SerializedTrueTypeFontDesc& desc) {
+  // Create attributes and traits dictionaries.
+  base::mac::ScopedCFTypeRef<CFMutableDictionaryRef> attributes_ref(
+      CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
+                                &kCFTypeDictionaryKeyCallBacks,
+                                &kCFTypeDictionaryValueCallBacks));
+
+  base::mac::ScopedCFTypeRef<CFMutableDictionaryRef> traits_ref(
+      CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
+                                &kCFTypeDictionaryKeyCallBacks,
+                                &kCFTypeDictionaryValueCallBacks));
+  if (!attributes_ref || !traits_ref)
+    return;
+
+  CFDictionaryAddValue(attributes_ref, kCTFontTraitsAttribute, traits_ref);
+
+  // Use symbolic traits to specify traits when possible.
+  CTFontSymbolicTraits symbolic_traits = 0;
+  if (desc.style & PP_TRUETYPEFONTSTYLE_ITALIC)
+    symbolic_traits |= kCTFontItalicTrait;
+  if (desc.weight == PP_TRUETYPEFONTWEIGHT_BOLD)
+    symbolic_traits |= kCTFontBoldTrait;
+  if (desc.width == PP_TRUETYPEFONTWIDTH_CONDENSED)
+    symbolic_traits |= kCTFontCondensedTrait;
+  else if (desc.width == PP_TRUETYPEFONTWIDTH_EXPANDED)
+    symbolic_traits |= kCTFontExpandedTrait;
+
+  base::mac::ScopedCFTypeRef<CFNumberRef> symbolic_traits_ref(
+      CFNumberCreate(kCFAllocatorDefault,
+                     kCFNumberSInt32Type,
+                     &symbolic_traits));
+  if (!symbolic_traits_ref)
+    return;
+  CFDictionaryAddValue(traits_ref, kCTFontSymbolicTrait, symbolic_traits_ref);
+
+  // Font family matching doesn't work using family classes in symbolic traits.
+  // Instead, map generic_family to font families that are always available.
+  std::string family(desc.family);
+  if (family.empty()) {
+    switch (desc.generic_family) {
+      case PP_TRUETYPEFONTFAMILY_SERIF:
+        family = "Times";
+        break;
+      case PP_TRUETYPEFONTFAMILY_SANSSERIF:
+        family = "Helvetica";
+        break;
+      case PP_TRUETYPEFONTFAMILY_CURSIVE:
+        family = "Apple Chancery";
+        break;
+      case PP_TRUETYPEFONTFAMILY_FANTASY:
+        family = "Papyrus";
+        break;
+      case PP_TRUETYPEFONTFAMILY_MONOSPACE:
+        family = "Courier";
+        break;
+    }
+  }
+
+  base::mac::ScopedCFTypeRef<CFStringRef> name_ref(
+      base::SysUTF8ToCFStringRef(family));
+  if (name_ref)
+    CFDictionaryAddValue(attributes_ref, kCTFontFamilyNameAttribute, name_ref);
+
+  if (desc.weight != PP_TRUETYPEFONTWEIGHT_NORMAL &&
+      desc.weight != PP_TRUETYPEFONTWEIGHT_BOLD) {
+    float weight = GetMacWeight(desc.weight);
+    base::mac::ScopedCFTypeRef<CFNumberRef> weight_trait_ref(
+        CFNumberCreate(kCFAllocatorDefault,
+                       kCFNumberFloat32Type,
+                       &weight));
+    if (weight_trait_ref)
+      CFDictionaryAddValue(traits_ref, kCTFontWeightTrait, weight_trait_ref);
+  }
+
+  if (desc.width != PP_TRUETYPEFONTWIDTH_NORMAL &&
+      desc.width != PP_TRUETYPEFONTWIDTH_CONDENSED &&
+      desc.width != PP_TRUETYPEFONTWIDTH_EXPANDED) {
+    float width = GetMacWidth(desc.width);
+    base::mac::ScopedCFTypeRef<CFNumberRef> width_trait_ref(
+        CFNumberCreate(kCFAllocatorDefault,
+                       kCFNumberFloat32Type,
+                       &width));
+    if (width_trait_ref)
+      CFDictionaryAddValue(traits_ref, kCTFontWidthTrait, width_trait_ref);
+  }
+
+  base::mac::ScopedCFTypeRef<CTFontDescriptorRef> desc_ref(
+      CTFontDescriptorCreateWithAttributes(attributes_ref));
+
+  if (desc_ref)
+    font_ref_.reset(CTFontCreateWithFontDescriptor(desc_ref, 0, NULL));
+}
+
+PepperTrueTypeFontMac::~PepperTrueTypeFontMac() {
+}
+
+bool PepperTrueTypeFontMac::IsValid() {
+  return font_ref_.get() != NULL;
+}
+
+int32_t PepperTrueTypeFontMac::Describe(
+    ppapi::proxy::SerializedTrueTypeFontDesc* desc) {
+  if (!IsValid())
+    return PP_ERROR_FAILED;
+
+  base::mac::ScopedCFTypeRef<CTFontDescriptorRef> desc_ref(
+      CTFontCopyFontDescriptor(font_ref_));
+
+  base::mac::ScopedCFTypeRef<CFStringRef> family_name_ref(
+      base::mac::CFCast<CFStringRef>(CTFontDescriptorCopyAttribute(
+          desc_ref, kCTFontFamilyNameAttribute)));
+  desc->family = base::SysCFStringRefToUTF8(family_name_ref);
+
+  base::mac::ScopedCFTypeRef<CFDictionaryRef> traits_ref(
+      base::mac::CFCast<CFDictionaryRef>(
+          CTFontDescriptorCopyAttribute(desc_ref, kCTFontTraitsAttribute)));
+
+  desc->style = PP_TRUETYPEFONTSTYLE_NORMAL;
+  CTFontSymbolicTraits symbolic_traits(CTFontGetSymbolicTraits(font_ref_));
+  if (symbolic_traits & kCTFontItalicTrait)
+    desc->style = static_cast<PP_TrueTypeFontStyle_Dev>(
+                      desc->style | PP_TRUETYPEFONTSTYLE_ITALIC);
+  if (symbolic_traits & kCTFontBoldTrait) {
+    desc->weight = PP_TRUETYPEFONTWEIGHT_BOLD;
+  } else {
+    float weight;
+    if (FindFloat(traits_ref, kCTFontWeightTrait, &weight))
+      desc->weight = GetPepperWeight(weight);
+  }
+  if (symbolic_traits & kCTFontCondensedTrait) {
+    desc->width = PP_TRUETYPEFONTWIDTH_CONDENSED;
+  } else if (symbolic_traits & kCTFontExpandedTrait) {
+    desc->width = PP_TRUETYPEFONTWIDTH_EXPANDED;
+  } else {
+    float width;
+    if (FindFloat(traits_ref, kCTFontWidthTrait, &width))
+      desc->width = GetPepperWidth(width);
+  }
+
+  // Character set isn't supported on Mac.
+  desc->charset = PP_TRUETYPEFONTCHARSET_DEFAULT;
+  return PP_OK;
+}
+
+int32_t PepperTrueTypeFontMac::GetTableTags(std::vector<uint32_t>* tags) {
+  base::mac::ScopedCFTypeRef<CFArrayRef> tag_array(
+      CTFontCopyAvailableTables(font_ref_, kCTFontTableOptionNoOptions));
+  if (!tag_array)
+    return PP_ERROR_FAILED;
+
+  // Items returned by CTFontCopyAvailableTables are not boxed. Whose bright
+  // idea was this?
+  CFIndex length = CFArrayGetCount(tag_array);
+  tags->resize(length);
+  for (CFIndex i = 0; i < length; ++i) {
+    (*tags)[i] =
+        reinterpret_cast<uintptr_t>(CFArrayGetValueAtIndex(tag_array, i));
+  }
+  return length;
+}
+
+int32_t PepperTrueTypeFontMac::GetTable(uint32_t table_tag,
+                                        int32_t offset,
+                                        int32_t max_data_length,
+                                        std::string* data) {
+  if (!table_tag)
+    return GetEntireFont(offset, max_data_length, data);
+
+  base::mac::ScopedCFTypeRef<CFDataRef> table_ref(
+      CTFontCopyTable(font_ref_, static_cast<CTFontTableTag>(table_tag),
+                      kCTFontTableOptionNoOptions));
+  if (!table_ref)
+    return PP_ERROR_FAILED;
+
+  CFIndex table_size = CFDataGetLength(table_ref);
+  CFIndex safe_offset =
+      std::min(base::checked_numeric_cast<CFIndex>(offset), table_size);
+  CFIndex safe_length =
+      std::min(table_size - safe_offset,
+               base::checked_numeric_cast<CFIndex>(max_data_length));
+  data->resize(safe_length);
+  CFDataGetBytes(table_ref, CFRangeMake(safe_offset, safe_length),
+                 reinterpret_cast<UInt8*>(&(*data)[0]));
+
+  return safe_length;
+}
+
+int32_t PepperTrueTypeFontMac::GetEntireFont(int32_t offset,
+                                             int32_t max_data_length,
+                                             std::string* data) {
+  // Reconstruct the font header, table directory, and tables.
+  std::vector<uint32_t> table_tags;
+  int32_t table_count = GetTableTags(&table_tags);
+  if (table_count < 0)
+    return table_count;  // PPAPI error code.
+
+  // Allocate enough room for the header and the table directory entries.
+  std::string font(sizeof(FontHeader) +
+                   sizeof(FontDirectoryEntry) * table_count, 0);
+  // Map the OS X font type value to a TrueType scalar type.
+  base::mac::ScopedCFTypeRef<CFNumberRef> font_type_ref(
+      base::mac::CFCast<CFNumberRef>(
+          CTFontCopyAttribute(font_ref_, kCTFontFormatAttribute)));
+  int32_t font_type;
+  CFNumberGetValue(font_type_ref, kCFNumberSInt32Type, &font_type);
+  switch (font_type) {
+    case kCTFontFormatOpenTypePostScript:
+      font_type = MAKE_TABLE_TAG('O', 'T', 'T', 'O');
+      break;
+    case kCTFontFormatTrueType:
+    case kCTFontFormatBitmap:
+      font_type = MAKE_TABLE_TAG('t', 'r', 'u', 'e');
+      break;
+    case kCTFontFormatPostScript:
+      font_type = MAKE_TABLE_TAG('t', 'y', 'p', '1');
+      break;
+    case kCTFontFormatOpenTypeTrueType:
+    case kCTFontFormatUnrecognized:
+    default:
+      font_type = MAKE_TABLE_TAG(0, 1, 0, 0);
+      break;
+  }
+
+  // Calculate the rest of the header values.
+  uint16_t num_tables = base::checked_numeric_cast<uint16_t>(table_count);
+  uint16_t entry_selector = 0;
+  uint16_t search_range = 1;
+  while (search_range < num_tables >> 1) {
+    entry_selector++;
+    search_range <<= 1;
+  }
+  search_range <<= 4;
+  uint16_t range_shift = (num_tables << 4) - search_range;
+
+  // Write the header, with values in big-endian order.
+  FontHeader* font_header = reinterpret_cast<FontHeader*>(&font[0]);
+  font_header->font_type = base::HostToNet32(font_type);
+  font_header->num_tables = base::HostToNet16(num_tables);
+  font_header->search_range = base::HostToNet16(search_range);
+  font_header->entry_selector = base::HostToNet16(entry_selector);
+  font_header->range_shift = base::HostToNet16(range_shift);
+
+  for (int32_t i = 0; i < table_count; i++) {
+    // Get the table data.
+    std::string table;
+    int32_t table_size = GetTable(table_tags[i],
+                                  0, std::numeric_limits<int32_t>::max(),
+                                  &table);
+    if (table_size < 0)
+      return table_size;  // PPAPI error code.
+
+    // Append it to the font data so far, and zero pad so tables stay aligned.
+    size_t table_offset = font.size();
+    font.append(table);
+    size_t padding = font.size() & 0x3;
+    font.append(padding, 0);
+
+    // Fill in the directory entry for this table.
+    FontDirectoryEntry* entry = reinterpret_cast<FontDirectoryEntry*>(
+        &font[0] + sizeof(FontHeader) + i * sizeof(FontDirectoryEntry));
+    entry->tag = base::HostToNet32(table_tags[i]);
+    entry->checksum = base::HostToNet32(
+                          CalculateChecksum(&font[table_offset], table_size));
+    entry->offset = base::HostToNet32(table_offset);
+    entry->logical_length = base::HostToNet32(table_size);
+    // TODO(bbudge) set the 'head' table checksumAdjustment.
+  }
+
+  // Extract a substring if the caller specified an offset or max data length.
+  int32_t font_size = base::checked_numeric_cast<int32_t>(font.size());
+  int32_t safe_offset = std::min(offset, font_size);
+  int32_t safe_length = std::min(font_size - safe_offset, max_data_length);
+  if (safe_offset || safe_length != font_size)
+    font = font.substr(safe_offset, safe_length);
+
+  data->clear();
+  data->swap(font);
+  return safe_length;
+}
+
+}  // namespace
+
 // static
 PepperTrueTypeFont* PepperTrueTypeFont::Create(
     const ppapi::proxy::SerializedTrueTypeFontDesc& desc) {
-  NOTIMPLEMENTED();
-  return 0;
+  return new PepperTrueTypeFontMac(desc);
 }
 
 }  // namespace content
diff --git a/content/renderer/pepper/pepper_truetype_font_win.cc b/content/renderer/pepper/pepper_truetype_font_win.cc
index f59df68..9134c22 100644
--- a/content/renderer/pepper/pepper_truetype_font_win.cc
+++ b/content/renderer/pepper/pepper_truetype_font_win.cc
@@ -4,13 +4,239 @@
 
 #include "content/renderer/pepper/pepper_truetype_font.h"
 
+#include <windows.h>
+#include <set>
+
+#include "base/compiler_specific.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/sys_byteorder.h"
+#include "base/utf_string_conversions.h"
+#include "base/win/scoped_hdc.h"
+#include "base/win/scoped_select_object.h"
+#include "content/public/renderer/render_thread.h"
+#include "ppapi/c/dev/ppb_truetype_font_dev.h"
+#include "ppapi/c/pp_errors.h"
+
 namespace content {
 
+namespace {
+
+class PepperTrueTypeFontWin : public PepperTrueTypeFont {
+ public:
+  explicit PepperTrueTypeFontWin(
+      const ppapi::proxy::SerializedTrueTypeFontDesc& desc);
+  virtual ~PepperTrueTypeFontWin();
+
+  // PepperTrueTypeFont overrides.
+  virtual bool IsValid() OVERRIDE;
+  virtual int32_t Describe(
+      ppapi::proxy::SerializedTrueTypeFontDesc* desc) OVERRIDE;
+  virtual int32_t GetTableTags(std::vector<uint32_t>* tags) OVERRIDE;
+  virtual int32_t GetTable(uint32_t table_tag,
+                           int32_t offset,
+                           int32_t max_data_length,
+                           std::string* data) OVERRIDE;
+ private:
+  DWORD GetFontData(HDC hdc,
+                    DWORD table,
+                    DWORD offset,
+                    LPVOID buffer,
+                    DWORD length);
+
+  HFONT font_;
+
+  DISALLOW_COPY_AND_ASSIGN(PepperTrueTypeFontWin);
+};
+
+PepperTrueTypeFontWin::PepperTrueTypeFontWin(
+    const ppapi::proxy::SerializedTrueTypeFontDesc& desc) {
+  DWORD pitch_and_family = DEFAULT_PITCH;
+  switch (desc.generic_family) {
+    case PP_TRUETYPEFONTFAMILY_SERIF:
+      pitch_and_family |= FF_ROMAN;
+      break;
+    case PP_TRUETYPEFONTFAMILY_SANSSERIF:
+      pitch_and_family |= FF_SWISS;
+      break;
+    case PP_TRUETYPEFONTFAMILY_CURSIVE:
+      pitch_and_family |= FF_SCRIPT;
+      break;
+    case PP_TRUETYPEFONTFAMILY_FANTASY:
+      pitch_and_family |= FF_DECORATIVE;
+      break;
+    case PP_TRUETYPEFONTFAMILY_MONOSPACE:
+      pitch_and_family |= FF_MODERN;
+      break;
+  }
+  // TODO(bbudge) support widths (extended, condensed).
+
+  font_ = CreateFont(0  /* height */,
+                     0  /* width */,
+                     0  /* escapement */,
+                     0  /* orientation */,
+                     desc.weight,  // our weight enum matches Windows.
+                     (desc.style & PP_TRUETYPEFONTSTYLE_ITALIC) ? 1 : 0,
+                     0  /* underline */,
+                     0  /* strikeout */,
+                     desc.charset,  // our charset enum matches Windows.
+                     OUT_OUTLINE_PRECIS,  // truetype and other outline fonts
+                     CLIP_DEFAULT_PRECIS,
+                     DEFAULT_QUALITY,
+                     pitch_and_family,
+                     UTF8ToUTF16(desc.family).c_str());
+}
+
+PepperTrueTypeFontWin::~PepperTrueTypeFontWin() {
+}
+
+bool PepperTrueTypeFontWin::IsValid() {
+  return font_ != NULL;
+}
+
+int32_t PepperTrueTypeFontWin::Describe(
+      ppapi::proxy::SerializedTrueTypeFontDesc* desc) {
+  LOGFONT font_desc;
+  if (!::GetObject(font_, sizeof(LOGFONT), &font_desc))
+    return PP_ERROR_FAILED;
+
+  switch (font_desc.lfPitchAndFamily & 0xF0) {  // Top 4 bits are family.
+    case FF_ROMAN:
+      desc->generic_family = PP_TRUETYPEFONTFAMILY_SERIF;
+      break;
+    case FF_SWISS:
+      desc->generic_family = PP_TRUETYPEFONTFAMILY_SANSSERIF;
+      break;
+    case FF_SCRIPT:
+      desc->generic_family = PP_TRUETYPEFONTFAMILY_CURSIVE;
+      break;
+    case FF_DECORATIVE:
+      desc->generic_family = PP_TRUETYPEFONTFAMILY_FANTASY;
+      break;
+    case FF_MODERN:
+      desc->generic_family = PP_TRUETYPEFONTFAMILY_MONOSPACE;
+      break;
+  }
+
+  desc->style = font_desc.lfItalic ? PP_TRUETYPEFONTSTYLE_ITALIC :
+                                     PP_TRUETYPEFONTSTYLE_NORMAL;
+  desc->weight = static_cast<PP_TrueTypeFontWeight_Dev>(font_desc.lfWeight);
+  desc->width = PP_TRUETYPEFONTWIDTH_NORMAL;
+  desc->charset =
+      static_cast<PP_TrueTypeFontCharset_Dev>(font_desc.lfCharSet);
+
+  // To get the face name, select the font and query for the name. GetObject
+  // doesn't fill in the name field of the LOGFONT structure.
+  base::win::ScopedCreateDC hdc(::CreateCompatibleDC(NULL));
+  if (hdc) {
+    base::win::ScopedSelectObject select_object(hdc, font_);
+    WCHAR name[LF_FACESIZE];
+    GetTextFace(hdc, LF_FACESIZE, name);
+    desc->family = UTF16ToUTF8(name);
+  }
+  return PP_OK;
+}
+
+DWORD PepperTrueTypeFontWin::GetFontData(HDC hdc,
+                                         DWORD table,
+                                         DWORD offset,
+                                         void* buffer,
+                                         DWORD length) {
+  // If this is a zero byte read, return a successful result.
+  if (buffer && !length)
+    return 0;
+
+  DWORD result = ::GetFontData(hdc, table, offset, buffer, length);
+  if (result == GDI_ERROR) {
+    // The font may not be cached by the OS, causing an attempt to read it in
+    // the renderer process to fail. Attempt to pre-cache it.
+    LOGFONTW logfont;
+    if (!::GetObject(font_, sizeof(LOGFONTW), &logfont))
+      return GDI_ERROR;
+    content::RenderThread* render_thread = content::RenderThread::Get();
+    if (!render_thread)
+      return GDI_ERROR;
+    render_thread->PreCacheFont(logfont);
+
+    result = ::GetFontData(hdc, table, offset, buffer, length);
+  }
+  return result;
+}
+
+int32_t PepperTrueTypeFontWin::GetTableTags(std::vector<uint32_t>* tags) {
+  base::win::ScopedCreateDC hdc(::CreateCompatibleDC(NULL));
+  if (!hdc)
+    return PP_ERROR_FAILED;
+
+  base::win::ScopedSelectObject select_object(hdc, font_);
+
+  // Get the whole font header.
+  static const DWORD kFontHeaderSize = 12;
+  uint8_t header_buf[kFontHeaderSize];
+  if (GetFontData(hdc, 0, 0, header_buf, kFontHeaderSize) == GDI_ERROR)
+    return PP_ERROR_FAILED;
+
+  // The numTables follows a 4 byte scalerType tag. Font data is stored in
+  // big-endian order.
+  DWORD num_tables = (header_buf[4] << 8) | header_buf[5];
+
+  // The size in bytes of an entry in the table directory.
+  static const DWORD kDirectoryEntrySize = 16;
+  DWORD directory_size = num_tables * kDirectoryEntrySize;
+  scoped_ptr<uint8_t[]> directory(new uint8_t[directory_size]);
+  // Get the table directory entries after the font header.
+  if (GetFontData(hdc, 0 /* tag */, kFontHeaderSize,
+                  directory.get(),
+                  directory_size) == GDI_ERROR)
+    return PP_ERROR_FAILED;
+
+  tags->resize(num_tables);
+  for (DWORD i = 0; i < num_tables; i++) {
+    const uint8_t* entry = directory.get() + i * kDirectoryEntrySize;
+    uint32_t tag = static_cast<uint32_t>(entry[0]) << 24 |
+                   static_cast<uint32_t>(entry[1]) << 16 |
+                   static_cast<uint32_t>(entry[2]) << 8  |
+                   static_cast<uint32_t>(entry[3]);
+    (*tags)[i] = tag;
+  }
+
+  return num_tables;
+}
+
+int32_t PepperTrueTypeFontWin::GetTable(uint32_t table_tag,
+                                        int32_t offset,
+                                        int32_t max_data_length,
+                                        std::string* data) {
+  base::win::ScopedCreateDC hdc(::CreateCompatibleDC(NULL));
+  if (!hdc)
+    return PP_ERROR_FAILED;
+
+  base::win::ScopedSelectObject select_object(hdc, font_);
+
+  // Tags are byte swapped on Windows.
+  table_tag = base::ByteSwap(table_tag);
+  // Get the size of the font table first.
+  DWORD table_size = GetFontData(hdc, table_tag, 0, NULL, 0);
+  if (table_size == GDI_ERROR)
+    return PP_ERROR_FAILED;
+
+  DWORD safe_offset = std::min(static_cast<DWORD>(offset), table_size);
+  DWORD safe_length = std::min(table_size - safe_offset,
+                               static_cast<DWORD>(max_data_length));
+  data->resize(safe_length);
+  table_size = GetFontData(hdc, table_tag, safe_offset,
+                           reinterpret_cast<uint8_t*>(&(*data)[0]),
+                           safe_length);
+  if (table_size == GDI_ERROR)
+    return PP_ERROR_FAILED;
+  return static_cast<int32_t>(table_size);
+}
+
+}  // namespace
+
 // static
 PepperTrueTypeFont* PepperTrueTypeFont::Create(
     const ppapi::proxy::SerializedTrueTypeFontDesc& desc) {
-  NOTIMPLEMENTED();
-  return 0;
+  return new PepperTrueTypeFontWin(desc);
 }
 
 }  // namespace content
diff --git a/content/renderer/pepper/pepper_video_capture_host.cc b/content/renderer/pepper/pepper_video_capture_host.cc
index f79a42e..de3642c 100644
--- a/content/renderer/pepper/pepper_video_capture_host.cc
+++ b/content/renderer/pepper/pepper_video_capture_host.cc
@@ -37,8 +37,7 @@
       renderer_ppapi_host_(host),
       buffer_count_hint_(0),
       status_(PP_VIDEO_CAPTURE_STATUS_STOPPED),
-      ALLOW_THIS_IN_INITIALIZER_LIST(
-          enumeration_helper_(this, this, PP_DEVICETYPE_DEV_VIDEOCAPTURE)) {
+      enumeration_helper_(this, this, PP_DEVICETYPE_DEV_VIDEOCAPTURE) {
 }
 
 PepperVideoCaptureHost::~PepperVideoCaptureHost() {
@@ -251,7 +250,7 @@
     const std::string& device_id,
     const PP_VideoCaptureDeviceInfo_Dev& requested_info,
     uint32_t buffer_count) {
-  if (platform_video_capture_.get())
+  if (platform_video_capture_)
     return PP_ERROR_FAILED;
 
   webkit::ppapi::PluginDelegate* plugin_delegate = GetPluginDelegate();
@@ -323,7 +322,7 @@
 }
 
 int32_t PepperVideoCaptureHost::Close() {
-  if (!platform_video_capture_.get())
+  if (!platform_video_capture_)
     return PP_OK;
 
   StopCapture();
@@ -361,7 +360,7 @@
 }
 
 void PepperVideoCaptureHost::DetachPlatformVideoCapture() {
-  if (platform_video_capture_.get()) {
+  if (platform_video_capture_) {
     platform_video_capture_->DetachEventHandler();
     platform_video_capture_ = NULL;
   }
diff --git a/content/renderer/pepper/pepper_video_destination_host.cc b/content/renderer/pepper/pepper_video_destination_host.cc
new file mode 100644
index 0000000..13760d6
--- /dev/null
+++ b/content/renderer/pepper/pepper_video_destination_host.cc
@@ -0,0 +1,88 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/pepper/pepper_video_destination_host.h"
+
+#include "content/public/renderer/renderer_ppapi_host.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/host/dispatch_host_message.h"
+#include "ppapi/host/host_message_context.h"
+#include "ppapi/host/ppapi_host.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/thunk/enter.h"
+#include "ppapi/thunk/ppb_image_data_api.h"
+#include "webkit/plugins/ppapi/ppb_image_data_impl.h"
+
+using ppapi::host::HostMessageContext;
+using ppapi::host::ReplyMessageContext;
+
+namespace content {
+
+PepperVideoDestinationHost::PepperVideoDestinationHost(
+    RendererPpapiHost* host,
+    PP_Instance instance,
+    PP_Resource resource)
+    : ResourceHost(host->GetPpapiHost(), instance, resource),
+      renderer_ppapi_host_(host),
+      weak_factory_(this) {
+}
+
+PepperVideoDestinationHost::~PepperVideoDestinationHost() {
+}
+
+int32_t PepperVideoDestinationHost::OnResourceMessageReceived(
+    const IPC::Message& msg,
+    HostMessageContext* context) {
+  IPC_BEGIN_MESSAGE_MAP(PepperVideoDestinationHost, msg)
+    PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_VideoDestination_Open,
+                                        OnHostMsgOpen)
+    PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_VideoDestination_PutFrame,
+                                      OnHostMsgPutFrame)
+    PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_VideoDestination_Close,
+                                        OnHostMsgClose)
+  IPC_END_MESSAGE_MAP()
+  return PP_ERROR_FAILED;
+}
+
+int32_t PepperVideoDestinationHost::OnHostMsgOpen(
+    HostMessageContext* context,
+    const std::string& stream_url) {
+  GURL gurl(stream_url);
+  if (!gurl.is_valid())
+    return PP_ERROR_BADARGUMENT;
+  // TODO(ronghuawu) Check that gurl is a valid MediaStream video track URL.
+  // TODO(ronghuawu) Open a MediaStream video track.
+  ReplyMessageContext reply_context = context->MakeReplyMessageContext();
+  reply_context.params.set_result(PP_OK);
+  host()->SendReply(reply_context,
+                    PpapiPluginMsg_VideoDestination_OpenReply());
+  return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t PepperVideoDestinationHost::OnHostMsgPutFrame(
+    HostMessageContext* context,
+    const ppapi::HostResource& image_data,
+    PP_TimeTicks timestamp) {
+  ppapi::thunk::EnterResourceNoLock<ppapi::thunk::PPB_ImageData_API> enter(
+      image_data.host_resource(), true);
+  if (enter.failed())
+    return PP_ERROR_BADRESOURCE;
+  webkit::ppapi::PPB_ImageData_Impl* image_resource =
+      static_cast<webkit::ppapi::PPB_ImageData_Impl*>(enter.object());
+
+  if (!webkit::ppapi::PPB_ImageData_Impl::IsImageDataFormatSupported(
+          image_resource->format()))
+    return PP_ERROR_BADARGUMENT;
+
+  // TODO(ronghuawu) write image data to MediaStream video track.
+  return PP_OK;
+}
+
+int32_t PepperVideoDestinationHost::OnHostMsgClose(
+    HostMessageContext* context) {
+  // TODO(ronghuawu) Close the video stream.
+  return PP_OK;
+}
+
+}  // namespace content
diff --git a/content/renderer/pepper/pepper_video_destination_host.h b/content/renderer/pepper/pepper_video_destination_host.h
new file mode 100644
index 0000000..54941cb
--- /dev/null
+++ b/content/renderer/pepper/pepper_video_destination_host.h
@@ -0,0 +1,48 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_RENDERER_PEPPER_PEPPER_VIDEO_DESTINATION_HOST_H_
+#define CONTENT_RENDERER_PEPPER_PEPPER_VIDEO_DESTINATION_HOST_H_
+
+#include "base/compiler_specific.h"
+#include "base/memory/weak_ptr.h"
+#include "content/common/content_export.h"
+#include "ppapi/c/pp_time.h"
+#include "ppapi/host/resource_host.h"
+
+namespace content {
+
+class RendererPpapiHost;
+
+class CONTENT_EXPORT PepperVideoDestinationHost
+    : public ppapi::host::ResourceHost {
+ public:
+  PepperVideoDestinationHost(RendererPpapiHost* host,
+                             PP_Instance instance,
+                             PP_Resource resource);
+
+  virtual ~PepperVideoDestinationHost();
+
+  virtual int32_t OnResourceMessageReceived(
+      const IPC::Message& msg,
+      ppapi::host::HostMessageContext* context) OVERRIDE;
+
+ private:
+  int32_t OnHostMsgOpen(ppapi::host::HostMessageContext* context,
+                        const std::string& stream_url);
+  int32_t OnHostMsgPutFrame(ppapi::host::HostMessageContext* context,
+                            const ppapi::HostResource& image_data,
+                            PP_TimeTicks timestamp);
+  int32_t OnHostMsgClose(ppapi::host::HostMessageContext* context);
+
+  RendererPpapiHost* renderer_ppapi_host_;
+
+  base::WeakPtrFactory<PepperVideoDestinationHost> weak_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(PepperVideoDestinationHost);
+};
+
+}  // namespace content
+
+#endif  // CONTENT_RENDERER_PEPPER_PEPPER_VIDEO_DESTINATION_HOST_H_
diff --git a/content/renderer/pepper/pepper_video_source_host.cc b/content/renderer/pepper/pepper_video_source_host.cc
new file mode 100644
index 0000000..1015ea0
--- /dev/null
+++ b/content/renderer/pepper/pepper_video_source_host.cc
@@ -0,0 +1,116 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/pepper/pepper_video_source_host.h"
+
+#include "base/bind.h"
+#include "content/public/renderer/renderer_ppapi_host.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/host/dispatch_host_message.h"
+#include "ppapi/host/host_message_context.h"
+#include "ppapi/host/ppapi_host.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/proxy/ppb_image_data_proxy.h"
+#include "ppapi/shared_impl/scoped_pp_resource.h"
+#include "ppapi/thunk/enter.h"
+#include "ppapi/thunk/ppb_image_data_api.h"
+#include "skia/ext/platform_canvas.h"
+#include "webkit/plugins/ppapi/ppb_image_data_impl.h"
+
+using ppapi::host::HostMessageContext;
+using ppapi::host::ReplyMessageContext;
+
+namespace content {
+
+PepperVideoSourceHost::PepperVideoSourceHost(
+    RendererPpapiHost* host,
+    PP_Instance instance,
+    PP_Resource resource)
+    : ResourceHost(host->GetPpapiHost(), instance, resource),
+      renderer_ppapi_host_(host),
+      weak_factory_(this),
+      last_timestamp_(0) {
+}
+
+PepperVideoSourceHost::~PepperVideoSourceHost() {
+}
+
+int32_t PepperVideoSourceHost::OnResourceMessageReceived(
+    const IPC::Message& msg,
+    HostMessageContext* context) {
+  IPC_BEGIN_MESSAGE_MAP(PepperVideoSourceHost, msg)
+    PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_VideoSource_Open,
+                                      OnHostMsgOpen)
+    PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_VideoSource_GetFrame,
+                                        OnHostMsgGetFrame)
+    PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_VideoSource_Close,
+                                        OnHostMsgClose)
+  IPC_END_MESSAGE_MAP()
+  return PP_ERROR_FAILED;
+}
+
+int32_t PepperVideoSourceHost::OnHostMsgOpen(HostMessageContext* context,
+                                             const std::string& stream_url) {
+  GURL gurl(stream_url);
+  if (!gurl.is_valid())
+    return PP_ERROR_BADARGUMENT;
+  // TODO(ronghuawu) Check that gurl is a valid MediaStream video track URL.
+  // TODO(ronghuawu) Open a MediaStream video track.
+  ReplyMessageContext reply_context = context->MakeReplyMessageContext();
+  reply_context.params.set_result(PP_OK);
+  host()->SendReply(reply_context, PpapiPluginMsg_VideoSource_OpenReply());
+  return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t PepperVideoSourceHost::OnHostMsgGetFrame(
+    HostMessageContext* context) {
+  ReplyMessageContext reply_context = context->MakeReplyMessageContext();
+  // TODO(ronghuawu) Wait until a frame with timestamp > last_timestamp_ is
+  // available.
+  // Create an image data resource to hold the frame pixels.
+  PP_ImageDataDesc desc;
+  IPC::PlatformFileForTransit image_handle;
+  uint32_t byte_count;
+  ppapi::ScopedPPResource resource(
+      ppapi::ScopedPPResource::PassRef(),
+      ppapi::proxy::PPB_ImageData_Proxy::CreateImageData(
+          pp_instance(),
+          webkit::ppapi::PPB_ImageData_Impl::GetNativeImageDataFormat(),
+          PP_MakeSize(0, 0),
+          false /* init_to_zero */,
+          false /* is_nacl_plugin */,
+          &desc, &image_handle, &byte_count));
+  if (!resource.get())
+    return PP_ERROR_FAILED;
+
+  ppapi::thunk::EnterResourceNoLock<ppapi::thunk::PPB_ImageData_API>
+      enter_resource(resource, false);
+  if (enter_resource.failed())
+    return PP_ERROR_FAILED;
+
+  webkit::ppapi::PPB_ImageData_Impl* image_data =
+      static_cast<webkit::ppapi::PPB_ImageData_Impl*>(enter_resource.object());
+  webkit::ppapi::ImageDataAutoMapper mapper(image_data);
+  if (!mapper.is_valid())
+    return PP_ERROR_FAILED;
+
+  // TODO(ronghuawu) Copy frame pixels to canvas.
+
+  ppapi::HostResource image_data_resource;
+  image_data_resource.SetHostResource(pp_instance(), resource.get());
+  double timestamp = 0;
+  reply_context.params.set_result(PP_OK);
+  host()->SendReply(
+      reply_context,
+      PpapiPluginMsg_VideoSource_GetFrameReply(image_data_resource, timestamp));
+  last_timestamp_ = timestamp;
+  return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t PepperVideoSourceHost::OnHostMsgClose(HostMessageContext* context) {
+  // TODO(ronghuawu) Close the video stream.
+  return PP_OK;
+}
+
+}  // namespace content
diff --git a/content/renderer/pepper/pepper_video_source_host.h b/content/renderer/pepper/pepper_video_source_host.h
new file mode 100644
index 0000000..c2a873f
--- /dev/null
+++ b/content/renderer/pepper/pepper_video_source_host.h
@@ -0,0 +1,47 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_RENDERER_PEPPER_PEPPER_VIDEO_SOURCE_HOST_H_
+#define CONTENT_RENDERER_PEPPER_PEPPER_VIDEO_SOURCE_HOST_H_
+
+#include "base/compiler_specific.h"
+#include "base/memory/weak_ptr.h"
+#include "content/common/content_export.h"
+#include "ppapi/c/pp_time.h"
+#include "ppapi/host/resource_host.h"
+
+namespace content {
+
+class RendererPpapiHost;
+
+class CONTENT_EXPORT PepperVideoSourceHost : public ppapi::host::ResourceHost {
+ public:
+  PepperVideoSourceHost(RendererPpapiHost* host,
+                        PP_Instance instance,
+                        PP_Resource resource);
+
+  virtual ~PepperVideoSourceHost();
+
+  virtual int32_t OnResourceMessageReceived(
+      const IPC::Message& msg,
+      ppapi::host::HostMessageContext* context) OVERRIDE;
+
+ private:
+  int32_t OnHostMsgOpen(ppapi::host::HostMessageContext* context,
+                        const std::string& stream_url);
+  int32_t OnHostMsgGetFrame(ppapi::host::HostMessageContext* context);
+  int32_t OnHostMsgClose(ppapi::host::HostMessageContext* context);
+
+  RendererPpapiHost* renderer_ppapi_host_;
+
+  base::WeakPtrFactory<PepperVideoSourceHost> weak_factory_;
+
+  PP_TimeTicks last_timestamp_;
+
+  DISALLOW_COPY_AND_ASSIGN(PepperVideoSourceHost);
+};
+
+}  // namespace content
+
+#endif  // CONTENT_RENDERER_PEPPER_PEPPER_VIDEO_SOURCE_HOST_H_
diff --git a/content/renderer/pepper/pepper_websocket_host.cc b/content/renderer/pepper/pepper_websocket_host.cc
index d473e84..e2ab15a 100644
--- a/content/renderer/pepper/pepper_websocket_host.cc
+++ b/content/renderer/pepper/pepper_websocket_host.cc
@@ -43,7 +43,7 @@
 }
 
 PepperWebSocketHost::~PepperWebSocketHost() {
-  if (websocket_.get())
+  if (websocket_)
     websocket_->disconnect();
 }
 
@@ -67,7 +67,7 @@
 
 void PepperWebSocketHost::didConnect() {
   std::string protocol;
-  if (websocket_.get())
+  if (websocket_)
     protocol = websocket_->subprotocol().utf8();
   connecting_ = false;
   connect_reply_.params.set_result(PP_OK);
@@ -169,7 +169,7 @@
   }
 
   // Disconnect.
-  if (websocket_.get())
+  if (websocket_)
     websocket_->disconnect();
 }
 
@@ -233,7 +233,7 @@
   WebDocument document = container->element().document();
   websocket_.reset(WebSocket::create(document, this));
   DCHECK(websocket_.get());
-  if (!websocket_.get())
+  if (!websocket_)
     return PP_ERROR_NOTSUPPORTED;
 
   // Set receiving binary object type.
@@ -249,7 +249,7 @@
     ppapi::host::HostMessageContext* context,
     int32_t code,
     const std::string& reason) {
-  if (!websocket_.get())
+  if (!websocket_)
     return PP_ERROR_FAILED;
   close_reply_ = context->MakeReplyMessageContext();
   initiating_close_ = true;
@@ -261,7 +261,7 @@
 int32_t PepperWebSocketHost::OnHostMsgSendText(
     ppapi::host::HostMessageContext* context,
     const std::string& message) {
-  if (websocket_.get()) {
+  if (websocket_) {
     WebString web_message = WebString::fromUTF8(message);
     websocket_->sendText(web_message);
   }
@@ -282,7 +282,7 @@
 int32_t PepperWebSocketHost::OnHostMsgFail(
     ppapi::host::HostMessageContext* context,
     const std::string& message) {
-  if (websocket_.get())
+  if (websocket_)
     websocket_->fail(WebString::fromUTF8(message));
   return PP_OK;
 }
diff --git a/content/renderer/pepper/renderer_ppapi_host_impl.cc b/content/renderer/pepper/renderer_ppapi_host_impl.cc
index 50b4fc7..4971d51 100644
--- a/content/renderer/pepper/renderer_ppapi_host_impl.cc
+++ b/content/renderer/pepper/renderer_ppapi_host_impl.cc
@@ -6,6 +6,8 @@
 
 #include "base/files/file_path.h"
 #include "base/logging.h"
+#include "base/process_util.h"
+#include "content/common/sandbox_util.h"
 #include "content/renderer/pepper/pepper_graphics_2d_host.h"
 #include "content/renderer/pepper/pepper_in_process_resource_creation.h"
 #include "content/renderer/pepper/pepper_in_process_router.h"
@@ -245,9 +247,13 @@
     base::PlatformFile handle,
     bool should_close_source) {
   if (!dispatcher_) {
-    if (should_close_source)
-      base::ClosePlatformFile(handle);
-    return IPC::InvalidPlatformFileForTransit();
+    DCHECK(is_running_in_process_);
+    // Duplicate the file handle for in process mode so this function
+    // has the same semantics for both in process mode and out of
+    // process mode (i.e., the remote side must cloes the handle).
+    return BrokerGetFileHandleForProcess(handle,
+                                         base::GetCurrentProcId(),
+                                         should_close_source);
   }
   return dispatcher_->ShareHandleWithRemote(handle, should_close_source);
 }
diff --git a/content/renderer/plugin_channel_host.cc b/content/renderer/plugin_channel_host.cc
index dfdffb0..f9b1829 100644
--- a/content/renderer/plugin_channel_host.cc
+++ b/content/renderer/plugin_channel_host.cc
@@ -29,7 +29,7 @@
 #if defined(OS_MACOSX)
 #include "base/debug/crash_logging.h"
 #include "base/debug/stack_trace.h"
-#include "base/sys_string_conversions.h"
+#include "base/strings/sys_string_conversions.h"
 
 namespace {
 
diff --git a/content/renderer/render_process_impl.cc b/content/renderer/render_process_impl.cc
index bbcb312..8256947 100644
--- a/content/renderer/render_process_impl.cc
+++ b/content/renderer/render_process_impl.cc
@@ -37,9 +37,9 @@
 namespace content {
 
 RenderProcessImpl::RenderProcessImpl()
-    : ALLOW_THIS_IN_INITIALIZER_LIST(shared_mem_cache_cleaner_(
+    : shared_mem_cache_cleaner_(
           FROM_HERE, base::TimeDelta::FromSeconds(5),
-          this, &RenderProcessImpl::ClearTransportDIBCache)),
+          this, &RenderProcessImpl::ClearTransportDIBCache),
       transport_dib_next_sequence_number_(0),
       enabled_bindings_(0) {
   in_process_plugins_ = InProcessPlugins();
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc
index c35a2c5..2896a54 100644
--- a/content/renderer/render_thread_impl.cc
+++ b/content/renderer/render_thread_impl.cc
@@ -84,7 +84,6 @@
 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDatabase.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/WebIDBFactory.h"
 #include "third_party/WebKit/Source/WebKit/chromium/public/WebKit.h"
 #include "third_party/WebKit/Source/WebKit/chromium/public/WebNetworkStateNotifier.h"
 #include "third_party/WebKit/Source/WebKit/chromium/public/WebPopupMenu.h"
@@ -180,7 +179,7 @@
     return ".docs";
   if (host == "plus.google.com")
     return ".plus";
-  return "";
+  return std::string();
 }
 
 void* CreateHistogram(
@@ -207,12 +206,12 @@
 }
 
 #if defined(ENABLE_WEBRTC)
-const unsigned char* GetCategoryEnabled(const char* name) {
-  return TRACE_EVENT_API_GET_CATEGORY_ENABLED(name);
+const unsigned char* GetCategoryGroupEnabled(const char* category_group) {
+  return TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(category_group);
 }
 
 void AddTraceEvent(char phase,
-                   const unsigned char* category_enabled,
+                   const unsigned char* category_group_enabled,
                    const char* name,
                    unsigned long long id,
                    int num_args,
@@ -220,8 +219,9 @@
                    const unsigned char* arg_types,
                    const unsigned long long* arg_values,
                    unsigned char flags) {
-  TRACE_EVENT_API_ADD_TRACE_EVENT(phase, category_enabled, name, id, num_args,
-                                  arg_names, arg_types, arg_values, flags);
+  TRACE_EVENT_API_ADD_TRACE_EVENT(phase, category_group_enabled, name, id,
+                                  num_args, arg_names, arg_types, arg_values,
+                                  NULL, flags);
 }
 #endif
 
@@ -363,7 +363,7 @@
   AddFilter(db_message_filter_.get());
 
 #if defined(ENABLE_WEBRTC)
-  webrtc::SetupEventTracer(&GetCategoryEnabled, &AddTraceEvent);
+  webrtc::SetupEventTracer(&GetCategoryGroupEnabled, &AddTraceEvent);
 
   peer_connection_tracker_.reset(new PeerConnectionTracker());
   AddObserver(peer_connection_tracker_.get());
@@ -405,15 +405,18 @@
 }
 
 RenderThreadImpl::~RenderThreadImpl() {
+}
+
+void RenderThreadImpl::Shutdown() {
   FOR_EACH_OBSERVER(
       RenderProcessObserver, observers_, OnRenderProcessShutdown());
 
   // Wait for all databases to be closed.
-  if (web_database_observer_impl_.get())
+  if (web_database_observer_impl_)
     web_database_observer_impl_->WaitForAllDatabasesToClose();
 
   // Shutdown in reverse of the initialization order.
-  if (devtools_agent_message_filter_.get()) {
+  if (devtools_agent_message_filter_) {
     RemoveFilter(devtools_agent_message_filter_.get());
     devtools_agent_message_filter_ = NULL;
   }
@@ -430,20 +433,21 @@
   db_message_filter_ = NULL;
 
   // Shutdown the file thread if it's running.
-  if (file_thread_.get())
+  if (file_thread_)
     file_thread_->Stop();
 
-  if (compositor_output_surface_filter_.get()) {
+  if (compositor_output_surface_filter_) {
     RemoveFilter(compositor_output_surface_filter_.get());
     compositor_output_surface_filter_ = NULL;
   }
 
-  if (input_handler_manager_.get()) {
+  compositor_thread_.reset();
+  if (input_handler_manager_) {
     RemoveFilter(input_handler_manager_->GetMessageFilter());
     input_handler_manager_.reset();
   }
 
-  if (webkit_platform_support_.get())
+  if (webkit_platform_support_)
     WebKit::shutdown();
 
   lazy_tls.Pointer()->Set(NULL);
@@ -501,10 +505,10 @@
     if (notify_webkit_of_modal_loop)
       WebView::willEnterModalLoop();
 
-    RenderWidget* widget =
-        static_cast<RenderWidget*>(ResolveRoute(msg->routing_id()));
-    if (widget) {
-      render_view_id = widget->routing_id();
+    RenderViewImpl* render_view =
+        RenderViewImpl::FromRoutingID(msg->routing_id());
+    if (render_view) {
+      render_view_id = msg->routing_id();
       PluginChannelHost::Broadcast(
           new PluginMsg_SignalModalDialogEvent(render_view_id));
     }
@@ -618,8 +622,100 @@
   ScheduleIdleHandler(kLongIdleHandlerDelayMs);
 }
 
+static void AdjustRuntimeFeatureDefaultsForPlatform() {
+#if defined(OS_ANDROID) && !defined(GOOGLE_TV)
+  WebRuntimeFeatures::enableMediaSource(false);
+#endif
+
+#if defined(OS_ANDROID)
+  WebRuntimeFeatures::enableWebAudio(false);
+  // Web Speech API Speech recognition is not implemented on Android yet.
+  WebRuntimeFeatures::enableScriptedSpeech(false);
+  // Android does not support the Gamepad API.
+  WebRuntimeFeatures::enableGamepad(false);
+  // input[type=week] in Android is incomplete. crbug.com/135938
+  WebRuntimeFeatures::enableInputTypeWeek(false);
+#endif
+}
+
+static void AdjustRuntimeFeaturesFromArgs(const CommandLine& command_line) {
+  if (command_line.HasSwitch(switches::kDisableDatabases))
+    WebRuntimeFeatures::enableDatabase(false);
+
+  if (command_line.HasSwitch(switches::kDisableApplicationCache))
+    WebRuntimeFeatures::enableApplicationCache(false);
+
+  if (command_line.HasSwitch(switches::kDisableDesktopNotifications))
+    WebRuntimeFeatures::enableNotifications(false);
+
+  if (command_line.HasSwitch(switches::kDisableLocalStorage))
+    WebRuntimeFeatures::enableLocalStorage(false);
+
+  if (command_line.HasSwitch(switches::kDisableSessionStorage))
+    WebRuntimeFeatures::enableSessionStorage(false);
+
+  if (command_line.HasSwitch(switches::kDisableGeolocation))
+    WebRuntimeFeatures::enableGeolocation(false);
+
+#if !defined(OS_ANDROID) || defined(GOOGLE_TV)
+  if (command_line.HasSwitch(switches::kDisableMediaSource))
+    WebRuntimeFeatures::enableMediaSource(false);
+#endif
+
+#if defined(OS_ANDROID)
+  if (command_line.HasSwitch(switches::kDisableWebRTC))
+    WebRuntimeFeatures::enableMediaStream(false);
+#endif
+
+#if defined(OS_ANDROID)
+  if (command_line.HasSwitch(switches::kDisableWebRTC))
+    WebRuntimeFeatures::enablePeerConnection(false);
+#endif
+
+  if (command_line.HasSwitch(switches::kDisableFullScreen))
+    WebRuntimeFeatures::enableFullScreenAPI(false);
+
+  if (command_line.HasSwitch(switches::kDisableEncryptedMedia))
+    WebRuntimeFeatures::enableEncryptedMedia(false);
+
+#if defined(OS_ANDROID)
+  if (command_line.HasSwitch(switches::kEnableWebAudio))
+    WebRuntimeFeatures::enableWebAudio(true);
+#else
+  if (command_line.HasSwitch(switches::kDisableWebAudio))
+    WebRuntimeFeatures::enableWebAudio(false);
+#endif
+
+  if (command_line.HasSwitch(switches::kEnableWebMIDI))
+    WebRuntimeFeatures::enableWebMIDI(true);
+
+  if (command_line.HasSwitch(switches::kEnableDeviceMotion))
+      WebRuntimeFeatures::enableDeviceMotion(true);
+
+  if (command_line.HasSwitch(switches::kDisableDeviceOrientation))
+    WebRuntimeFeatures::enableDeviceOrientation(false);
+
+  if (command_line.HasSwitch(switches::kDisableSpeechInput))
+    WebRuntimeFeatures::enableSpeechInput(false);
+
+  if (command_line.HasSwitch(switches::kDisableFileSystem))
+    WebRuntimeFeatures::enableFileSystem(false);
+
+  if (command_line.HasSwitch(switches::kDisableJavaScriptI18NAPI))
+    WebRuntimeFeatures::enableJavaScriptI18NAPI(false);
+
+  if (command_line.HasSwitch(switches::kEnableExperimentalWebSocket))
+    WebRuntimeFeatures::enableExperimentalWebSocket(true);
+
+  if (command_line.HasSwitch(switches::kEnableExperimentalCanvasFeatures))
+    WebRuntimeFeatures::enableExperimentalCanvasFeatures(true);
+
+  if (command_line.HasSwitch(switches::kEnableSpeechSynthesis))
+    WebRuntimeFeatures::enableSpeechSynthesis(true);
+}
+
 void RenderThreadImpl::EnsureWebKitInitialized() {
-  if (webkit_platform_support_.get())
+  if (webkit_platform_support_)
     return;
 
   webkit_platform_support_.reset(new RendererWebKitPlatformSupportImpl);
@@ -633,7 +729,7 @@
 
   bool enable = command_line.HasSwitch(switches::kEnableThreadedCompositing);
   if (enable) {
-    MessageLoop* override_loop =
+    base::MessageLoop* override_loop =
         GetContentClient()->renderer()->OverrideCompositorMessageLoop();
     if (override_loop) {
       compositor_message_loop_proxy_ = override_loop->message_loop_proxy();
@@ -672,104 +768,24 @@
       new WebDatabaseObserverImpl(sync_message_filter()));
   WebKit::WebDatabase::setObserver(web_database_observer_impl_.get());
 
-  WebRuntimeFeatures::enableSockets(
-      !command_line.HasSwitch(switches::kDisableWebSockets));
+  WebRuntimeFeatures::enableStableFeatures(true);
 
-  WebRuntimeFeatures::enableDatabase(
-      !command_line.HasSwitch(switches::kDisableDatabases));
+  if (command_line.HasSwitch(switches::kEnableExperimentalWebKitFeatures))
+    WebRuntimeFeatures::enableExperimentalFeatures(true);
 
-  WebRuntimeFeatures::enableDataTransferItems(
-      !command_line.HasSwitch(switches::kDisableDataTransferItems));
+  AdjustRuntimeFeatureDefaultsForPlatform();
+  AdjustRuntimeFeaturesFromArgs(command_line);
 
-  WebRuntimeFeatures::enableApplicationCache(
-      !command_line.HasSwitch(switches::kDisableApplicationCache));
+  // Enabled by default for testing.
+  // TODO(urvang): Go back to using the command-line option after a few days.
+  // https://code.google.com/p/chromium/issues/detail?id=234437
+  WebRuntimeFeatures::enableWebPInAcceptHeader(true);
 
-  WebRuntimeFeatures::enableNotifications(
-      !command_line.HasSwitch(switches::kDisableDesktopNotifications));
-
-  WebRuntimeFeatures::enableLocalStorage(
-      !command_line.HasSwitch(switches::kDisableLocalStorage));
-  WebRuntimeFeatures::enableSessionStorage(
-      !command_line.HasSwitch(switches::kDisableSessionStorage));
-
-  WebRuntimeFeatures::enableIndexedDatabase(true);
-
-  WebRuntimeFeatures::enableGeolocation(
-      !command_line.HasSwitch(switches::kDisableGeolocation));
-
-  WebKit::WebRuntimeFeatures::enableMediaSource(
-      !command_line.HasSwitch(switches::kDisableMediaSource));
-
-  WebRuntimeFeatures::enableMediaPlayer(
-      media::IsMediaLibraryInitialized());
-
-#if defined(OS_ANDROID)
-  WebKit::WebRuntimeFeatures::enableMediaStream(
-      !command_line.HasSwitch(switches::kDisableWebRTC));
-  WebKit::WebRuntimeFeatures::enablePeerConnection(
-      !command_line.HasSwitch(switches::kDisableWebRTC));
-#else
-  WebKit::WebRuntimeFeatures::enableMediaStream(true);
-  WebKit::WebRuntimeFeatures::enablePeerConnection(true);
-#endif
-
-  WebKit::WebRuntimeFeatures::enableFullScreenAPI(
-      !command_line.HasSwitch(switches::kDisableFullScreen));
-
-  WebKit::WebRuntimeFeatures::enableEncryptedMedia(
-      !command_line.HasSwitch(switches::kDisableEncryptedMedia));
-
-#if defined(OS_ANDROID)
-  WebRuntimeFeatures::enableWebAudio(
-      command_line.HasSwitch(switches::kEnableWebAudio) &&
-      media::IsMediaLibraryInitialized());
-#else
-  WebRuntimeFeatures::enableWebAudio(
-      !command_line.HasSwitch(switches::kDisableWebAudio) &&
-      media::IsMediaLibraryInitialized());
-#endif
-
-  WebRuntimeFeatures::enableDeviceMotion(
-      command_line.HasSwitch(switches::kEnableDeviceMotion));
-
-  WebRuntimeFeatures::enableDeviceOrientation(
-      !command_line.HasSwitch(switches::kDisableDeviceOrientation));
-
-  WebRuntimeFeatures::enableSpeechInput(
-      !command_line.HasSwitch(switches::kDisableSpeechInput));
-
-#if defined(OS_ANDROID)
-  // Web Speech API Speech recognition is not implemented on Android yet.
-  WebRuntimeFeatures::enableScriptedSpeech(false);
-#else
-  WebRuntimeFeatures::enableScriptedSpeech(true);
-#endif
-
-  WebRuntimeFeatures::enableFileSystem(
-      !command_line.HasSwitch(switches::kDisableFileSystem));
-
-  WebRuntimeFeatures::enableJavaScriptI18NAPI(
-      !command_line.HasSwitch(switches::kDisableJavaScriptI18NAPI));
-
-  WebRuntimeFeatures::enableGamepad(true);
-
-  WebRuntimeFeatures::enableQuota(true);
-
-  WebRuntimeFeatures::enableShadowDOM(true);
-
-  if (command_line.HasSwitch(switches::kEnableExperimentalWebKitFeatures)) {
-    WebRuntimeFeatures::enableStyleScoped(true);
-    WebRuntimeFeatures::enableCustomDOMElements(true);
-    WebRuntimeFeatures::enableCSSExclusions(true);
-    WebRuntimeFeatures::enableExperimentalContentSecurityPolicyFeatures(true);
-    WebRuntimeFeatures::enableCSSRegions(true);
-    WebRuntimeFeatures::enableDialogElement(true);
-    WebRuntimeFeatures::enableFontLoadEvents(true);
+  if (!media::IsMediaLibraryInitialized()) {
+    WebRuntimeFeatures::enableMediaPlayer(false);
+    WebRuntimeFeatures::enableWebAudio(false);
   }
 
-  WebRuntimeFeatures::enableSeamlessIFrames(
-      command_line.HasSwitch(switches::kEnableExperimentalWebKitFeatures));
-
   FOR_EACH_OBSERVER(RenderProcessObserver, observers_, WebKitInitialized());
 
   devtools_agent_message_filter_ = new DevToolsAgentFilter();
@@ -802,7 +818,7 @@
       new ChildProcessHostMsg_SyncAllocateSharedMemory(size, &handle);
 
   // Allow calling this from the compositor thread.
-  if (MessageLoop::current() == message_loop())
+  if (base::MessageLoop::current() == message_loop())
     success = ChildThread::Send(message);
   else
     success = sync_message_filter()->Send(message);
@@ -923,7 +939,7 @@
 void RenderThreadImpl::OnGpuVDAContextLoss() {
   RenderThreadImpl* self = RenderThreadImpl::current();
   DCHECK(self);
-  if (!self->gpu_vda_context3d_.get())
+  if (!self->gpu_vda_context3d_)
     return;
   if (self->compositor_message_loop_proxy()) {
     self->compositor_message_loop_proxy()->DeleteSoon(
@@ -935,12 +951,12 @@
 
 WebGraphicsContext3DCommandBufferImpl*
 RenderThreadImpl::GetGpuVDAContext3D() {
-  if (!gpu_vda_context3d_.get()) {
+  if (!gpu_vda_context3d_) {
     gpu_vda_context3d_.reset(
         WebGraphicsContext3DCommandBufferImpl::CreateOffscreenContext(
             this, WebKit::WebGraphicsContext3D::Attributes(),
             GURL("chrome://gpu/RenderThreadImpl::GetGpuVDAContext3D")));
-    if (gpu_vda_context3d_.get())
+    if (gpu_vda_context3d_)
       gpu_vda_context3d_->setContextLostCallback(context_lost_cb_.get());
   }
   return gpu_vda_context3d_.get();
@@ -990,7 +1006,7 @@
 }
 
 AudioRendererMixerManager* RenderThreadImpl::GetAudioRendererMixerManager() {
-  if (!audio_renderer_mixer_manager_.get()) {
+  if (!audio_renderer_mixer_manager_) {
     audio_renderer_mixer_manager_.reset(new AudioRendererMixerManager(
         GetAudioHardwareConfig()));
   }
@@ -1045,7 +1061,8 @@
 }
 
 bool RenderThreadImpl::IsIOThread() {
-  return MessageLoop::current() == ChildProcess::current()->io_message_loop();
+  return base::MessageLoop::current() ==
+         ChildProcess::current()->io_message_loop();
 }
 
 MessageLoop* RenderThreadImpl::GetMainLoop() {
@@ -1080,7 +1097,7 @@
       &route_id);
 
   // Allow calling this from the compositor thread.
-  if (MessageLoop::current() == message_loop())
+  if (base::MessageLoop::current() == message_loop())
     ChildThread::Send(message);
   else
     sync_message_filter()->Send(message);
@@ -1169,7 +1186,7 @@
     CauseForGpuLaunch cause_for_gpu_launch) {
   TRACE_EVENT0("gpu", "RenderThreadImpl::EstablishGpuChannelSync");
 
-  if (gpu_channel_.get()) {
+  if (gpu_channel_) {
     // Do nothing if we already have a GPU channel or are already
     // establishing one.
     if (gpu_channel_->state() == GpuChannelHost::kUnconnected ||
@@ -1231,7 +1248,7 @@
 MediaStreamDependencyFactory*
 RenderThreadImpl::GetMediaStreamDependencyFactory() {
 #if defined(ENABLE_WEBRTC)
-  if (!media_stream_factory_.get()) {
+  if (!media_stream_factory_) {
     media_stream_factory_.reset(new MediaStreamDependencyFactory(
         vc_manager_, p2p_socket_dispatcher_));
   }
@@ -1240,7 +1257,7 @@
 }
 
 GpuChannelHost* RenderThreadImpl::GetGpuChannel() {
-  if (!gpu_channel_.get())
+  if (!gpu_channel_)
     return NULL;
 
   if (gpu_channel_->state() != GpuChannelHost::kConnected)
@@ -1278,8 +1295,8 @@
 
 scoped_refptr<base::MessageLoopProxy>
 RenderThreadImpl::GetFileThreadMessageLoopProxy() {
-  DCHECK(message_loop() == MessageLoop::current());
-  if (!file_thread_.get()) {
+  DCHECK(message_loop() == base::MessageLoop::current());
+  if (!file_thread_) {
     file_thread_.reset(new base::Thread("Renderer::FILE"));
     file_thread_->Start();
   }
diff --git a/content/renderer/render_thread_impl.h b/content/renderer/render_thread_impl.h
index 9eed9b8..be9b176 100644
--- a/content/renderer/render_thread_impl.h
+++ b/content/renderer/render_thread_impl.h
@@ -107,6 +107,7 @@
   // Constructor that's used when running in single process mode.
   explicit RenderThreadImpl(const std::string& channel_name);
   virtual ~RenderThreadImpl();
+  virtual void Shutdown() OVERRIDE;
 
   // When initializing WebKit, ensure that any schemes needed for the content
   // module are registered properly.  Static to allow sharing with tests.
@@ -114,7 +115,7 @@
 
   // RenderThread implementation:
   virtual bool Send(IPC::Message* msg) OVERRIDE;
-  virtual MessageLoop* GetMessageLoop() OVERRIDE;
+  virtual base::MessageLoop* GetMessageLoop() OVERRIDE;
   virtual IPC::SyncChannel* GetChannel() OVERRIDE;
   virtual std::string GetLocale() OVERRIDE;
   virtual IPC::SyncMessageFilter* GetSyncMessageFilter() OVERRIDE;
@@ -157,7 +158,7 @@
   // GpuChannelHostFactory implementation:
   virtual bool IsMainThread() OVERRIDE;
   virtual bool IsIOThread() OVERRIDE;
-  virtual MessageLoop* GetMainLoop() OVERRIDE;
+  virtual base::MessageLoop* GetMainLoop() OVERRIDE;
   virtual scoped_refptr<base::MessageLoopProxy> GetIOLoopProxy() OVERRIDE;
   virtual base::WaitableEvent* GetShutDownEvent() OVERRIDE;
   virtual scoped_ptr<base::SharedMemory> AllocateSharedMemory(
diff --git a/content/renderer/render_thread_impl_browsertest.cc b/content/renderer/render_thread_impl_browsertest.cc
new file mode 100644
index 0000000..d8dc67b
--- /dev/null
+++ b/content/renderer/render_thread_impl_browsertest.cc
@@ -0,0 +1,62 @@
+// Copyright 2013 The Chromium Authors. 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 "content/public/common/content_switches.h"
+#include "content/public/renderer/content_renderer_client.h"
+#include "content/renderer/render_process_impl.h"
+#include "content/renderer/render_thread_impl.h"
+#include "content/test/mock_render_process.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+namespace {
+
+class RenderThreadImplBrowserTest : public testing::Test {
+ public:
+  virtual ~RenderThreadImplBrowserTest() {}
+};
+
+class DummyListener : public IPC::Listener {
+ public:
+  virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
+    return true;
+  }
+};
+
+void CheckRenderThreadInputHandlerManager(RenderThreadImpl* thread) {
+  ASSERT_TRUE(thread->input_handler_manager());
+}
+
+// Check that InputHandlerManager outlives compositor thread because it uses
+// raw pointers to post tasks.
+TEST_F(RenderThreadImplBrowserTest,
+    InputHandlerManagerDestroyedAfterCompositorThread) {
+  CommandLine::ForCurrentProcess()->AppendSwitch(
+      switches::kEnableThreadedCompositing);
+
+  ContentRendererClient content_renderer_client;
+  SetRendererClientForTesting(&content_renderer_client);
+  base::MessageLoopForIO message_loop_;
+
+  std::string channel_id = IPC::Channel::GenerateVerifiedChannelID(
+      std::string());
+  DummyListener dummy_listener;
+  IPC::Channel channel(channel_id, IPC::Channel::MODE_SERVER, &dummy_listener);
+  ASSERT_TRUE(channel.Connect());
+
+  scoped_ptr<MockRenderProcess> mock_process(new MockRenderProcess);
+  // Owned by mock_process.
+  RenderThreadImpl* thread = new RenderThreadImpl(channel_id);
+  thread->EnsureWebKitInitialized();
+
+  ASSERT_TRUE(thread->input_handler_manager());
+
+  thread->compositor_message_loop_proxy()->PostTask(
+      FROM_HERE,
+      base::Bind(&CheckRenderThreadInputHandlerManager, thread));
+}
+
+}  // namespace
+}  // namespace content
diff --git a/content/renderer/render_view_browsertest.cc b/content/renderer/render_view_browsertest.cc
index 6e39cc0..35b784b 100644
--- a/content/renderer/render_view_browsertest.cc
+++ b/content/renderer/render_view_browsertest.cc
@@ -12,6 +12,8 @@
 #include "content/public/browser/web_ui_controller_factory.h"
 #include "content/public/common/bindings_policy.h"
 #include "content/public/common/url_constants.h"
+#include "content/public/renderer/document_state.h"
+#include "content/public/renderer/navigation_state.h"
 #include "content/public/test/render_view_test.h"
 #include "content/renderer/render_view_impl.h"
 #include "content/shell/shell_content_browser_client.h"
@@ -315,13 +317,16 @@
   WebUITestWebUIControllerFactory factory;
   WebUIControllerFactory::RegisterFactory(&factory);
 
+  DocumentState state;
+  state.set_navigation_state(NavigationState::CreateContentInitiated());
+
   // Navigations to normal HTTP URLs can be handled locally.
   WebKit::WebURLRequest request(GURL("http://foo.com"));
   WebKit::WebNavigationPolicy policy = view()->decidePolicyForNavigation(
       GetMainFrame(),
+      &state,
       request,
       WebKit::WebNavigationTypeLinkClicked,
-      WebKit::WebNode(),
       WebKit::WebNavigationPolicyCurrentTab,
       false);
   EXPECT_EQ(WebKit::WebNavigationPolicyCurrentTab, policy);
@@ -331,9 +336,9 @@
   form_request.setHTTPMethod("POST");
   policy = view()->decidePolicyForNavigation(
       GetMainFrame(),
+      &state,
       form_request,
       WebKit::WebNavigationTypeFormSubmitted,
-      WebKit::WebNode(),
       WebKit::WebNavigationPolicyCurrentTab,
       false);
   EXPECT_EQ(WebKit::WebNavigationPolicyIgnore, policy);
@@ -342,9 +347,9 @@
   WebKit::WebURLRequest popup_request(GURL("chrome://foo"));
   policy = view()->decidePolicyForNavigation(
       GetMainFrame(),
+      &state,
       popup_request,
       WebKit::WebNavigationTypeLinkClicked,
-      WebKit::WebNode(),
       WebKit::WebNavigationPolicyNewForegroundTab,
       false);
   EXPECT_EQ(WebKit::WebNavigationPolicyIgnore, policy);
@@ -354,13 +359,16 @@
   // Enable bindings to simulate a WebUI view.
   view()->OnAllowBindings(BINDINGS_POLICY_WEB_UI);
 
+  DocumentState state;
+  state.set_navigation_state(NavigationState::CreateContentInitiated());
+
   // Navigations to normal HTTP URLs will be sent to browser process.
   WebKit::WebURLRequest request(GURL("http://foo.com"));
   WebKit::WebNavigationPolicy policy = view()->decidePolicyForNavigation(
       GetMainFrame(),
+      &state,
       request,
       WebKit::WebNavigationTypeLinkClicked,
-      WebKit::WebNode(),
       WebKit::WebNavigationPolicyCurrentTab,
       false);
   EXPECT_EQ(WebKit::WebNavigationPolicyIgnore, policy);
@@ -369,9 +377,9 @@
   WebKit::WebURLRequest webui_request(GURL("chrome://foo"));
   policy = view()->decidePolicyForNavigation(
       GetMainFrame(),
+      &state,
       webui_request,
       WebKit::WebNavigationTypeLinkClicked,
-      WebKit::WebNode(),
       WebKit::WebNavigationPolicyCurrentTab,
       false);
   EXPECT_EQ(WebKit::WebNavigationPolicyIgnore, policy);
@@ -381,9 +389,9 @@
   data_request.setHTTPMethod("POST");
   policy = view()->decidePolicyForNavigation(
       GetMainFrame(),
+      &state,
       data_request,
       WebKit::WebNavigationTypeFormSubmitted,
-      WebKit::WebNode(),
       WebKit::WebNavigationPolicyCurrentTab,
       false);
   EXPECT_EQ(WebKit::WebNavigationPolicyIgnore, policy);
@@ -398,9 +406,9 @@
   RenderViewImpl* new_view = RenderViewImpl::FromWebView(new_web_view);
   policy = new_view->decidePolicyForNavigation(
       new_web_view->mainFrame(),
+      &state,
       popup_request,
       WebKit::WebNavigationTypeLinkClicked,
-      WebKit::WebNode(),
       WebKit::WebNavigationPolicyNewForegroundTab,
       false);
   EXPECT_EQ(WebKit::WebNavigationPolicyIgnore, policy);
@@ -1395,6 +1403,15 @@
   error.reason = net::ERR_FILE_NOT_FOUND;
   error.unreachableURL = GURL("http://foo");
   WebFrame* web_frame = GetMainFrame();
+
+  // Start a load that will reach provisional state synchronously,
+  // but won't complete synchronously.
+  ViewMsg_Navigate_Params params;
+  params.page_id = -1;
+  params.navigation_type = ViewMsg_Navigate_Type::NORMAL;
+  params.url = GURL("data:text/html,test data");
+  view()->OnNavigate(params);
+
   // An error occurred.
   view()->didFailProvisionalLoad(web_frame, error);
   // Frame should exit view-source mode.
@@ -1408,6 +1425,15 @@
   error.reason = net::ERR_ABORTED;
   error.unreachableURL = GURL("http://foo");
   WebFrame* web_frame = GetMainFrame();
+
+  // Start a load that will reach provisional state synchronously,
+  // but won't complete synchronously.
+  ViewMsg_Navigate_Params params;
+  params.page_id = -1;
+  params.navigation_type = ViewMsg_Navigate_Type::NORMAL;
+  params.url = GURL("data:text/html,test data");
+  view()->OnNavigate(params);
+
   // A cancellation occurred.
   view()->didFailProvisionalLoad(web_frame, error);
   // Frame should stay in view-source mode.
diff --git a/content/renderer/render_view_browsertest_mac.mm b/content/renderer/render_view_browsertest_mac.mm
index ed9908a..ab4af5d 100644
--- a/content/renderer/render_view_browsertest_mac.mm
+++ b/content/renderer/render_view_browsertest_mac.mm
@@ -8,6 +8,7 @@
 #include "content/public/test/render_view_test.h"
 #include "content/renderer/render_view_impl.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "webkit/glue/webpreferences.h"
 
 #include <Cocoa/Cocoa.h>
 #include <Carbon/Carbon.h>  // for the kVK_* constants.
@@ -83,7 +84,7 @@
   );
   #undef HTML
 
-  webkit_glue::WebPreferences prefs;
+  WebPreferences prefs;
   prefs.enable_scroll_animator = false;
 
   RenderViewImpl* view = static_cast<RenderViewImpl*>(view_);
diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc
index b1a51cf..2150615 100644
--- a/content/renderer/render_view_impl.cc
+++ b/content/renderer/render_view_impl.cc
@@ -13,7 +13,6 @@
 #include "base/command_line.h"
 #include "base/compiler_specific.h"
 #include "base/debug/trace_event.h"
-#include "base/json/json_reader.h"
 #include "base/json/json_writer.h"
 #include "base/lazy_instance.h"
 #include "base/memory/scoped_ptr.h"
@@ -22,21 +21,21 @@
 #include "base/path_service.h"
 #include "base/process_util.h"
 #include "base/string_number_conversions.h"
-#include "base/string_piece.h"
 #include "base/string_util.h"
+#include "base/strings/string_piece.h"
 #include "base/strings/string_split.h"
-#include "base/sys_string_conversions.h"
+#include "base/strings/sys_string_conversions.h"
 #include "base/time.h"
 #include "base/utf_string_conversions.h"
 #include "content/common/appcache/appcache_dispatcher.h"
 #include "content/common/child_thread.h"
 #include "content/common/clipboard_messages.h"
-#include "content/common/content_constants_internal.h"
 #include "content/common/database_messages.h"
 #include "content/common/drag_messages.h"
 #include "content/common/fileapi/file_system_dispatcher.h"
 #include "content/common/fileapi/webfilesystem_callback_dispatcher.h"
 #include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h"
+#include "content/common/input_messages.h"
 #include "content/common/java_bridge_messages.h"
 #include "content/common/pepper_messages.h"
 #include "content/common/pepper_plugin_registry.h"
@@ -51,6 +50,7 @@
 #include "content/public/common/content_constants.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/common/context_menu_params.h"
+#include "content/public/common/favicon_url.h"
 #include "content/public/common/file_chooser_params.h"
 #include "content/public/common/ssl_status.h"
 #include "content/public/common/three_d_api_types.h"
@@ -71,16 +71,16 @@
 #include "content/renderer/device_orientation_dispatcher.h"
 #include "content/renderer/devtools/devtools_agent.h"
 #include "content/renderer/disambiguation_popup_helper.h"
-#include "content/renderer/do_not_track_bindings.h"
 #include "content/renderer/dom_automation_controller.h"
 #include "content/renderer/dom_storage/webstoragenamespace_impl.h"
 #include "content/renderer/external_popup_menu.h"
-#include "content/renderer/favicon_helper.h"
 #include "content/renderer/geolocation_dispatcher.h"
 #include "content/renderer/gpu/input_handler_manager.h"
 #include "content/renderer/gpu/render_widget_compositor.h"
 #include "content/renderer/idle_user_detector.h"
+#include "content/renderer/image_loading_helper.h"
 #include "content/renderer/input_tag_speech_dispatcher.h"
+#include "content/renderer/internal_document_state_data.h"
 #include "content/renderer/java/java_bridge_dispatcher.h"
 #include "content/renderer/load_progress_tracker.h"
 #include "content/renderer/media/audio_device_factory.h"
@@ -89,9 +89,9 @@
 #include "content/renderer/media/media_stream_dispatcher.h"
 #include "content/renderer/media/media_stream_impl.h"
 #include "content/renderer/media/render_media_log.h"
-#include "content/renderer/media/renderer_audio_output_device.h"
 #include "content/renderer/media/renderer_gpu_video_decoder_factories.h"
 #include "content/renderer/media/rtc_peer_connection_handler.h"
+#include "content/renderer/media/video_capture_impl_manager.h"
 #include "content/renderer/mhtml_generator.h"
 #include "content/renderer/notification_provider.h"
 #include "content/renderer/pepper/pepper_plugin_delegate_impl.h"
@@ -111,6 +111,7 @@
 #include "content/renderer/web_ui_extension_data.h"
 #include "content/renderer/webplugin_delegate_proxy.h"
 #include "content/renderer/websharedworker_proxy.h"
+#include "media/audio/audio_output_device.h"
 #include "media/base/audio_renderer_mixer_input.h"
 #include "media/base/filter_collection.h"
 #include "media/base/media_switches.h"
@@ -181,7 +182,7 @@
 #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
 #include "third_party/WebKit/Source/WebKit/chromium/public/WebWindowFeatures.h"
 #include "third_party/WebKit/Source/WebKit/chromium/public/default/WebRenderTheme.h"
-#include "ui/base/ui_base_switches.h"
+#include "ui/base/ui_base_switches_util.h"
 #include "ui/gfx/native_widget_types.h"
 #include "ui/gfx/point.h"
 #include "ui/gfx/rect.h"
@@ -209,6 +210,8 @@
 #include "webkit/plugins/npapi/webplugin_impl.h"
 
 #if defined(OS_ANDROID)
+#include <cpu-features.h>
+
 #include "content/common/android/device_telephony_info.h"
 #include "content/common/gpu/client/context_provider_command_buffer.h"
 #include "content/renderer/android/address_detector.h"
@@ -221,9 +224,7 @@
 #include "third_party/WebKit/Source/Platform/chromium/public/WebFloatRect.h"
 #include "third_party/WebKit/Source/WebKit/chromium/public/WebHitTestResult.h"
 #include "ui/gfx/rect_f.h"
-#include "webkit/media/android/media_player_bridge_manager_impl.h"
 #include "webkit/media/android/webmediaplayer_android.h"
-#include "webkit/media/android/webmediaplayer_impl_android.h"
 #include "webkit/media/android/webmediaplayer_manager_android.h"
 #elif defined(OS_WIN)
 // TODO(port): these files are currently Windows only because they concern:
@@ -326,7 +327,6 @@
 
 using webkit_glue::AltErrorPageResourceFetcher;
 using webkit_glue::ResourceFetcher;
-using webkit_glue::WebPreferences;
 using webkit_glue::WebURLResponseExtraDataImpl;
 
 #if defined(OS_ANDROID)
@@ -375,14 +375,6 @@
 static RenderViewImpl* (*g_create_render_view_impl)(RenderViewImplParams*) =
     NULL;
 
-static WebKit::WebFrame* FindFrameByID(WebKit::WebFrame* root, int frame_id) {
-  for (WebFrame* frame = root; frame; frame = frame->traverseNext(false)) {
-    if (frame->identifier() == frame_id)
-      return frame;
-  }
-  return NULL;
-}
-
 static void GetRedirectChain(WebDataSource* ds, std::vector<GURL>* result) {
   // Replace any occurrences of swappedout:// with about:blank.
   const WebURL& blank_url = GURL(chrome::kAboutBlankURL);
@@ -397,13 +389,14 @@
   }
 }
 
-// If |data_source| is non-null and has a DocumentState associated with it,
-// the AltErrorPageResourceFetcher is reset.
+// If |data_source| is non-null and has an InternalDocumentStateData associated
+// with it, the AltErrorPageResourceFetcher is reset.
 static void StopAltErrorPageFetcher(WebDataSource* data_source) {
   if (data_source) {
-    DocumentState* document_state = DocumentState::FromDataSource(data_source);
-    if (document_state)
-      document_state->set_alt_error_page_fetcher(NULL);
+    InternalDocumentStateData* internal_data =
+        InternalDocumentStateData::FromDataSource(data_source);
+    if (internal_data)
+      internal_data->set_alt_error_page_fetcher(NULL);
   }
 }
 
@@ -542,8 +535,22 @@
           switches::kEnableHighDpiCompositingForFixedPosition))
     return true;
 
-  // Default, when no switches are specified, is disabled.
-  return false;
+  // Default, when no switch is specified, is to be enabled only for high-DPI.
+  return device_scale_factor > 1.0f;
+}
+
+static FaviconURL::IconType ToFaviconType(WebKit::WebIconURL::Type type) {
+  switch (type) {
+    case WebKit::WebIconURL::TypeFavicon:
+      return FaviconURL::FAVICON;
+    case WebKit::WebIconURL::TypeTouch:
+      return FaviconURL::TOUCH_ICON;
+    case WebKit::WebIconURL::TypeTouchPrecomposed:
+      return FaviconURL::TOUCH_PRECOMPOSED_ICON;
+    case WebKit::WebIconURL::TypeInvalid:
+      return FaviconURL::INVALID_ICON;
+  }
+  return FaviconURL::INVALID_ICON;
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -595,6 +602,15 @@
   return item.httpBody().identifier();
 }
 
+bool TouchEnabled() {
+// Based on the definition of chrome::kEnableTouchIcon.
+#if defined(OS_ANDROID)
+  return true;
+#else
+  return false;
+#endif
+}
+
 }  // namespace
 
 RenderViewImpl::RenderViewImpl(RenderViewImplParams* params)
@@ -621,7 +637,7 @@
       cached_is_main_frame_pinned_to_right_(false),
       cached_has_main_frame_horizontal_scrollbar_(false),
       cached_has_main_frame_vertical_scrollbar_(false),
-      ALLOW_THIS_IN_INITIALIZER_LIST(cookie_jar_(this)),
+      cookie_jar_(this),
       notification_provider_(NULL),
       geolocation_dispatcher_(NULL),
       input_tag_speech_dispatcher_(NULL),
@@ -635,28 +651,23 @@
       renderer_accessibility_(NULL),
       java_bridge_dispatcher_(NULL),
       mouse_lock_dispatcher_(NULL),
-      favicon_helper_(NULL),
 #if defined(OS_ANDROID)
       body_background_color_(SK_ColorWHITE),
-      update_frame_info_scheduled_(false),
       expected_content_intent_id_(0),
       media_player_proxy_(NULL),
+#endif
+#if defined(OS_WIN)
+      focused_plugin_id_(-1),
+#endif
       enumeration_completion_id_(0),
-      ALLOW_THIS_IN_INITIALIZER_LIST(
-          load_progress_tracker_(new LoadProgressTracker(this))),
+#if defined(OS_ANDROID)
+      load_progress_tracker_(new LoadProgressTracker(this)),
 #endif
       session_storage_namespace_id_(params->session_storage_namespace_id),
       decrement_shared_popup_at_destruction_(false),
       handling_select_range_(false),
       next_snapshot_id_(0),
-      allow_partial_swap_(params->allow_partial_swap),
-#if defined(OS_WIN)
-      focused_plugin_id_(-1),
-#endif
-      updating_frame_tree_(false),
-      pending_frame_tree_update_(false),
-      target_process_id_(0),
-      target_routing_id_(0) {
+      allow_partial_swap_(params->allow_partial_swap) {
 }
 
 void RenderViewImpl::Initialize(RenderViewImplParams* params) {
@@ -729,12 +740,15 @@
   webview()->settings()->setAcceleratedCompositingForFixedPositionEnabled(
       ShouldUseFixedPositionCompositing(device_scale_factor_));
 
-  webkit_preferences_.Apply(webview());
+  webkit_glue::ApplyWebPreferences(webkit_preferences_, webview());
   webview()->initializeMainFrame(this);
 
-  if (command_line.HasSwitch(switches::kEnableTouchDragDrop))
+  if (switches::IsTouchDragDropEnabled())
     webview()->settings()->setTouchDragDropEnabled(true);
 
+  if (switches::IsTouchEditingEnabled())
+    webview()->settings()->setTouchEditingEnabled(true);
+
   if (!params->frame_name.empty())
     webview()->mainFrame()->setName(params->frame_name);
   webview()->settings()->setMinimumTimerInterval(
@@ -762,7 +776,8 @@
   // along with the RenderView automatically.
   devtools_agent_ = new DevToolsAgent(this);
   mouse_lock_dispatcher_ = new RenderViewMouseLockDispatcher(this);
-  favicon_helper_ = new FaviconHelper(this);
+
+  new ImageLoadingHelper(this);
 
   // Create renderer_accessibility_ if needed.
   OnSetAccessibilityMode(params->accessibility_mode);
@@ -982,31 +997,35 @@
   bool handled = true;
   bool msg_is_ok = true;
   IPC_BEGIN_MESSAGE_MAP_EX(RenderViewImpl, message, msg_is_ok)
+    IPC_MESSAGE_HANDLER(InputMsg_Copy, OnCopy)
+    IPC_MESSAGE_HANDLER(InputMsg_Cut, OnCut)
+    IPC_MESSAGE_HANDLER(InputMsg_Delete, OnDelete)
+    IPC_MESSAGE_HANDLER(InputMsg_ExecuteEditCommand, OnExecuteEditCommand)
+    IPC_MESSAGE_HANDLER(InputMsg_MoveCaret, OnMoveCaret)
+    IPC_MESSAGE_HANDLER(InputMsg_Paste, OnPaste)
+    IPC_MESSAGE_HANDLER(InputMsg_PasteAndMatchStyle, OnPasteAndMatchStyle)
+    IPC_MESSAGE_HANDLER(InputMsg_Redo, OnRedo)
+    IPC_MESSAGE_HANDLER(InputMsg_Replace, OnReplace)
+    IPC_MESSAGE_HANDLER(InputMsg_ReplaceMisspelling, OnReplaceMisspelling)
+    IPC_MESSAGE_HANDLER(InputMsg_ScrollFocusedEditableNodeIntoRect,
+                        OnScrollFocusedEditableNodeIntoRect)
+    IPC_MESSAGE_HANDLER(InputMsg_SelectAll, OnSelectAll)
+    IPC_MESSAGE_HANDLER(InputMsg_SelectRange, OnSelectRange)
+    IPC_MESSAGE_HANDLER(InputMsg_SetEditCommandsForNextKeyEvent,
+                        OnSetEditCommandsForNextKeyEvent)
+    IPC_MESSAGE_HANDLER(InputMsg_Undo, OnUndo)
+    IPC_MESSAGE_HANDLER(InputMsg_Unselect, OnUnselect)
     IPC_MESSAGE_HANDLER(ViewMsg_Navigate, OnNavigate)
     IPC_MESSAGE_HANDLER(ViewMsg_Stop, OnStop)
     IPC_MESSAGE_HANDLER(ViewMsg_ReloadFrame, OnReloadFrame)
-    IPC_MESSAGE_HANDLER(ViewMsg_Undo, OnUndo)
-    IPC_MESSAGE_HANDLER(ViewMsg_Redo, OnRedo)
-    IPC_MESSAGE_HANDLER(ViewMsg_Cut, OnCut)
-    IPC_MESSAGE_HANDLER(ViewMsg_Copy, OnCopy)
-    IPC_MESSAGE_HANDLER(ViewMsg_Paste, OnPaste)
-    IPC_MESSAGE_HANDLER(ViewMsg_PasteAndMatchStyle, OnPasteAndMatchStyle)
-    IPC_MESSAGE_HANDLER(ViewMsg_Replace, OnReplace)
-    IPC_MESSAGE_HANDLER(ViewMsg_ReplaceMisspelling, OnReplaceMisspelling)
-    IPC_MESSAGE_HANDLER(ViewMsg_Delete, OnDelete)
     IPC_MESSAGE_HANDLER(ViewMsg_SetName, OnSetName)
-    IPC_MESSAGE_HANDLER(ViewMsg_SelectAll, OnSelectAll)
-    IPC_MESSAGE_HANDLER(ViewMsg_Unselect, OnUnselect)
     IPC_MESSAGE_HANDLER(ViewMsg_SetEditableSelectionOffsets,
                         OnSetEditableSelectionOffsets)
     IPC_MESSAGE_HANDLER(ViewMsg_SetCompositionFromExistingText,
                         OnSetCompositionFromExistingText)
     IPC_MESSAGE_HANDLER(ViewMsg_ExtendSelectionAndDelete,
                         OnExtendSelectionAndDelete)
-    IPC_MESSAGE_HANDLER(ViewMsg_SelectRange, OnSelectRange)
-    IPC_MESSAGE_HANDLER(ViewMsg_MoveCaret, OnMoveCaret)
     IPC_MESSAGE_HANDLER(ViewMsg_CopyImageAt, OnCopyImageAt)
-    IPC_MESSAGE_HANDLER(ViewMsg_ExecuteEditCommand, OnExecuteEditCommand)
     IPC_MESSAGE_HANDLER(ViewMsg_Find, OnFind)
     IPC_MESSAGE_HANDLER(ViewMsg_StopFinding, OnStopFinding)
     IPC_MESSAGE_HANDLER(ViewMsg_Zoom, OnZoom)
@@ -1029,8 +1048,6 @@
                         OnDragSourceSystemDragEnded)
     IPC_MESSAGE_HANDLER(ViewMsg_AllowBindings, OnAllowBindings)
     IPC_MESSAGE_HANDLER(ViewMsg_SetInitialFocus, OnSetInitialFocus)
-    IPC_MESSAGE_HANDLER(ViewMsg_ScrollFocusedEditableNodeIntoRect,
-                        OnScrollFocusedEditableNodeIntoRect)
     IPC_MESSAGE_HANDLER(ViewMsg_UpdateTargetURL_ACK, OnUpdateTargetURLAck)
     IPC_MESSAGE_HANDLER(ViewMsg_UpdateWebPreferences, OnUpdateWebPreferences)
     IPC_MESSAGE_HANDLER(ViewMsg_TimezoneChange, OnUpdateTimezone)
@@ -1059,10 +1076,6 @@
                         OnOrientationChangeEvent)
     IPC_MESSAGE_HANDLER(ViewMsg_PluginActionAt, OnPluginActionAt)
     IPC_MESSAGE_HANDLER(ViewMsg_SetActive, OnSetActive)
-    IPC_MESSAGE_HANDLER(ViewMsg_SetNavigationStartTime,
-                        OnSetNavigationStartTime)
-    IPC_MESSAGE_HANDLER(ViewMsg_SetEditCommandsForNextKeyEvent,
-                        OnSetEditCommandsForNextKeyEvent)
     IPC_MESSAGE_HANDLER(ViewMsg_CustomContextMenuAction,
                         OnCustomContextMenuAction)
     IPC_MESSAGE_HANDLER(ViewMsg_AsyncOpenFile_ACK, OnAsyncFileOpened)
@@ -1076,6 +1089,7 @@
         ViewMsg_GetSerializedHtmlDataForCurrentPageWithLocalLinks,
         OnGetSerializedHtmlDataForCurrentPageWithLocalLinks)
     IPC_MESSAGE_HANDLER(ViewMsg_ContextMenuClosed, OnContextMenuClosed)
+    IPC_MESSAGE_HANDLER(ViewMsg_ShowContextMenu, OnShowContextMenu)
     // TODO(viettrungluu): Move to a separate message filter.
     IPC_MESSAGE_HANDLER(ViewMsg_SetHistoryLengthAndPrune,
                         OnSetHistoryLengthAndPrune)
@@ -1083,18 +1097,17 @@
     IPC_MESSAGE_HANDLER(JavaBridgeMsg_Init, OnJavaBridgeInit)
     IPC_MESSAGE_HANDLER(ViewMsg_SetAccessibilityMode, OnSetAccessibilityMode)
     IPC_MESSAGE_HANDLER(ViewMsg_DisownOpener, OnDisownOpener)
-    IPC_MESSAGE_HANDLER(ViewMsg_UpdateFrameTree, OnUpdatedFrameTree)
 #if defined(OS_ANDROID)
-    IPC_MESSAGE_HANDLER(ViewMsg_ActivateNearestFindResult,
+    IPC_MESSAGE_HANDLER(InputMsg_ActivateNearestFindResult,
                         OnActivateNearestFindResult)
     IPC_MESSAGE_HANDLER(ViewMsg_FindMatchRects, OnFindMatchRects)
     IPC_MESSAGE_HANDLER(ViewMsg_SelectPopupMenuItems, OnSelectPopupMenuItems)
     IPC_MESSAGE_HANDLER(ViewMsg_UndoScrollFocusedEditableNodeIntoView,
                         OnUndoScrollFocusedEditableNodeIntoRect)
-    IPC_MESSAGE_HANDLER(ViewMsg_EnableHidingTopControls,
-                        OnEnableHidingTopControls)
+    IPC_MESSAGE_HANDLER(ViewMsg_UpdateTopControlsState,
+                        OnUpdateTopControlsState)
 #elif defined(OS_MACOSX)
-    IPC_MESSAGE_HANDLER(ViewMsg_CopyToFindPboard, OnCopyToFindPboard)
+    IPC_MESSAGE_HANDLER(InputMsg_CopyToFindPboard, OnCopyToFindPboard)
     IPC_MESSAGE_HANDLER(ViewMsg_PluginImeCompositionCompleted,
                         OnPluginImeCompositionCompleted)
     IPC_MESSAGE_HANDLER(ViewMsg_SelectPopupMenuItem, OnSelectPopupMenuItem)
@@ -1149,6 +1162,11 @@
     SetSwappedOut(false);
   }
 
+  if (params.should_clear_history_list) {
+    CHECK_EQ(params.pending_history_list_offset, -1);
+    CHECK_EQ(params.current_history_list_offset, -1);
+    CHECK_EQ(params.current_history_list_length, 0);
+  }
   history_list_offset_ = params.current_history_list_offset;
   history_list_length_ = params.current_history_list_length;
   if (history_list_length_ >= 0)
@@ -1258,6 +1276,21 @@
     }
 
     frame->loadRequest(request);
+
+    // If this is a cross-process navigation, the browser process will send
+    // along the proper navigation start value.
+    if (!params.browser_navigation_start.is_null() &&
+        frame->provisionalDataSource()) {
+      // browser_navigation_start is likely before this process existed, so we
+      // can't use InterProcessTimeTicksConverter. Instead, the best we can do
+      // is just ensure we don't report a bogus value in the future.
+      base::TimeTicks navigation_start = std::min(
+          base::TimeTicks::Now(), params.browser_navigation_start);
+      double navigation_start_seconds =
+          (navigation_start - base::TimeTicks()).InSecondsF();
+      frame->provisionalDataSource()->setNavigationStartTime(
+          navigation_start_seconds);
+    }
   }
 
   // In case LoadRequest failed before DidCreateDataSource was called.
@@ -1329,15 +1362,6 @@
   webview()->copyImageAt(WebPoint(x, y));
 }
 
-void RenderViewImpl::OnExecuteEditCommand(const std::string& name,
-    const std::string& value) {
-  if (!webview() || !webview()->focusedFrame())
-    return;
-
-  webview()->focusedFrame()->executeCommand(
-      WebString::fromUTF8(name), WebString::fromUTF8(value));
-}
-
 void RenderViewImpl::OnUpdateTargetURLAck() {
   // Check if there is a targeturl waiting to be sent.
   if (target_url_status_ == TARGET_PENDING) {
@@ -1348,18 +1372,15 @@
   target_url_status_ = TARGET_NONE;
 }
 
-void RenderViewImpl::OnUndo() {
+void RenderViewImpl::OnCopy() {
   if (!webview())
     return;
 
-  webview()->focusedFrame()->executeCommand(WebString::fromUTF8("Undo"));
-}
-
-void RenderViewImpl::OnRedo() {
-  if (!webview())
-    return;
-
-  webview()->focusedFrame()->executeCommand(WebString::fromUTF8("Redo"));
+  base::AutoReset<bool> handling_select_range(&handling_select_range_, true);
+  WebNode current_node = context_menu_node_.isNull() ?
+      GetFocusedNode() : context_menu_node_;
+  webview()->focusedFrame()->executeCommand(WebString::fromUTF8("Copy"),
+                                            current_node);
 }
 
 void RenderViewImpl::OnCut() {
@@ -1367,40 +1388,43 @@
     return;
 
   base::AutoReset<bool> handling_select_range(&handling_select_range_, true);
-  webview()->focusedFrame()->executeCommand(WebString::fromUTF8("Cut"));
+  webview()->focusedFrame()->executeCommand(WebString::fromUTF8("Cut"),
+                                            GetFocusedNode());
 }
 
-void RenderViewImpl::OnCopy() {
+void RenderViewImpl::OnDelete() {
   if (!webview())
     return;
 
-  base::AutoReset<bool> handling_select_range(&handling_select_range_, true);
-  webview()->focusedFrame()->executeCommand(WebString::fromUTF8("Copy"),
-                                            context_menu_node_);
+  webview()->focusedFrame()->executeCommand(WebString::fromUTF8("Delete"),
+                                            GetFocusedNode());
 }
 
-#if defined(OS_MACOSX)
-void RenderViewImpl::OnCopyToFindPboard() {
+void RenderViewImpl::OnExecuteEditCommand(const std::string& name,
+    const std::string& value) {
+  if (!webview() || !webview()->focusedFrame())
+    return;
+
+  webview()->focusedFrame()->executeCommand(
+      WebString::fromUTF8(name), WebString::fromUTF8(value));
+}
+
+void RenderViewImpl::OnMoveCaret(const gfx::Point& point) {
   if (!webview())
     return;
 
-  // Since the find pasteboard supports only plain text, this can be simpler
-  // than the |OnCopy()| case.
-  WebFrame* frame = webview()->focusedFrame();
-  if (frame->hasSelection()) {
-    string16 selection = frame->selectionAsText();
-    RenderThread::Get()->Send(
-        new ClipboardHostMsg_FindPboardWriteStringAsync(selection));
-  }
+  Send(new ViewHostMsg_MoveCaret_ACK(routing_id_));
+
+  webview()->focusedFrame()->moveCaretSelectionTowardsWindowPoint(point);
 }
-#endif
 
 void RenderViewImpl::OnPaste() {
   if (!webview())
     return;
 
   base::AutoReset<bool> handling_select_range(&handling_select_range_, true);
-  webview()->focusedFrame()->executeCommand(WebString::fromUTF8("Paste"));
+  webview()->focusedFrame()->executeCommand(WebString::fromUTF8("Paste"),
+                                            GetFocusedNode());
 }
 
 void RenderViewImpl::OnPasteAndMatchStyle() {
@@ -1409,7 +1433,15 @@
 
   base::AutoReset<bool> handling_select_range(&handling_select_range_, true);
   webview()->focusedFrame()->executeCommand(
-      WebString::fromUTF8("PasteAndMatchStyle"));
+      WebString::fromUTF8("PasteAndMatchStyle"), GetFocusedNode());
+}
+
+void RenderViewImpl::OnRedo() {
+  if (!webview())
+    return;
+
+  webview()->focusedFrame()->executeCommand(WebString::fromUTF8("Redo"),
+                                            GetFocusedNode());
 }
 
 void RenderViewImpl::OnReplace(const string16& text) {
@@ -1434,18 +1466,15 @@
   frame->replaceMisspelledRange(text);
 }
 
-void RenderViewImpl::OnDelete() {
-  if (!webview())
-    return;
-
-  webview()->focusedFrame()->executeCommand(WebString::fromUTF8("Delete"));
-}
-
-void RenderViewImpl::OnSetName(const std::string& name) {
-  if (!webview())
-    return;
-
-  webview()->mainFrame()->setName(WebString::fromUTF8(name));
+void RenderViewImpl::OnScrollFocusedEditableNodeIntoRect(
+    const gfx::Rect& rect) {
+  WebKit::WebNode node = GetFocusedNode();
+  if (!node.isNull()) {
+    if (IsEditableNode(node)) {
+      webview()->saveScrollAndScaleState();
+      webview()->scrollFocusedNodeIntoRect(rect);
+    }
+  }
 }
 
 void RenderViewImpl::OnSelectAll() {
@@ -1454,7 +1483,31 @@
 
   base::AutoReset<bool> handling_select_range(&handling_select_range_, true);
   webview()->focusedFrame()->executeCommand(
-      WebString::fromUTF8("SelectAll"));
+      WebString::fromUTF8("SelectAll"), GetFocusedNode());
+}
+
+void RenderViewImpl::OnSelectRange(const gfx::Point& start,
+                                   const gfx::Point& end) {
+  if (!webview())
+    return;
+
+  Send(new ViewHostMsg_SelectRange_ACK(routing_id_));
+
+  base::AutoReset<bool> handling_select_range(&handling_select_range_, true);
+  webview()->focusedFrame()->selectRange(start, end);
+}
+
+void RenderViewImpl::OnSetEditCommandsForNextKeyEvent(
+    const EditCommands& edit_commands) {
+  edit_commands_ = edit_commands;
+}
+
+void RenderViewImpl::OnUndo() {
+  if (!webview())
+    return;
+
+  webview()->focusedFrame()->executeCommand(WebString::fromUTF8("Undo"),
+                                            GetFocusedNode());
 }
 
 void RenderViewImpl::OnUnselect() {
@@ -1462,7 +1515,31 @@
     return;
 
   base::AutoReset<bool> handling_select_range(&handling_select_range_, true);
-  webview()->focusedFrame()->executeCommand(WebString::fromUTF8("Unselect"));
+  webview()->focusedFrame()->executeCommand(WebString::fromUTF8("Unselect"),
+                                            GetFocusedNode());
+}
+
+#if defined(OS_MACOSX)
+void RenderViewImpl::OnCopyToFindPboard() {
+  if (!webview())
+    return;
+
+  // Since the find pasteboard supports only plain text, this can be simpler
+  // than the |OnCopy()| case.
+  WebFrame* frame = webview()->focusedFrame();
+  if (frame->hasSelection()) {
+    string16 selection = frame->selectionAsText();
+    RenderThread::Get()->Send(
+        new ClipboardHostMsg_FindPboardWriteStringAsync(selection));
+  }
+}
+#endif
+
+void RenderViewImpl::OnSetName(const std::string& name) {
+  if (!webview())
+    return;
+
+  webview()->mainFrame()->setName(WebString::fromUTF8(name));
 }
 
 void RenderViewImpl::OnSetEditableSelectionOffsets(int start, int end) {
@@ -1496,26 +1573,6 @@
   UpdateTextInputState(DO_NOT_SHOW_IME);
 }
 
-void RenderViewImpl::OnSelectRange(const gfx::Point& start,
-                                   const gfx::Point& end) {
-  if (!webview())
-    return;
-
-  Send(new ViewHostMsg_SelectRange_ACK(routing_id_));
-
-  base::AutoReset<bool> handling_select_range(&handling_select_range_, true);
-  webview()->focusedFrame()->selectRange(start, end);
-}
-
-void RenderViewImpl::OnMoveCaret(const gfx::Point& point) {
-  if (!webview())
-    return;
-
-  Send(new ViewHostMsg_MoveCaret_ACK(routing_id_));
-
-  webview()->focusedFrame()->moveCaretSelectionTowardsWindowPoint(point);
-}
-
 void RenderViewImpl::OnSetHistoryLengthAndPrune(int history_length,
                                                 int32 minimum_page_id) {
   DCHECK_GE(history_length, 0);
@@ -1554,17 +1611,6 @@
 }
 #endif
 
-void RenderViewImpl::OnScrollFocusedEditableNodeIntoRect(
-    const gfx::Rect& rect) {
-  WebKit::WebNode node = GetFocusedNode();
-  if (!node.isNull()) {
-    if (IsEditableNode(node)) {
-      webview()->saveScrollAndScaleState();
-      webview()->scrollFocusedNodeIntoRect(rect);
-    }
-  }
-}
-
 #if defined(OS_ANDROID)
 void RenderViewImpl::OnUndoScrollFocusedEditableNodeIntoRect() {
   const WebNode node = GetFocusedNode();
@@ -1586,6 +1632,8 @@
 
   DocumentState* document_state = DocumentState::FromDataSource(ds);
   NavigationState* navigation_state = document_state->navigation_state();
+  InternalDocumentStateData* internal_data =
+      InternalDocumentStateData::FromDocumentState(document_state);
 
   ViewHostMsg_FrameNavigate_Params params;
   params.http_status_code = response.httpStatusCode();
@@ -1600,16 +1648,7 @@
     params.was_fetched_via_proxy = extra_data->was_fetched_via_proxy();
   }
   params.was_within_same_page = navigation_state->was_within_same_page();
-  if (!document_state->security_info().empty()) {
-    // SSL state specified in the request takes precedence over the one in the
-    // response.
-    // So far this is only intended for error pages that are not expected to be
-    // over ssl, so we should not get any clash.
-    DCHECK(response.securityInfo().isEmpty());
-    params.security_info = document_state->security_info();
-  } else {
-    params.security_info = response.securityInfo();
-  }
+  params.security_info = response.securityInfo();
 
   // Set the URL to be displayed in the browser UI to the user.
   params.url = GetLoadingUrl(frame);
@@ -1622,12 +1661,10 @@
   params.should_update_history = !ds->hasUnreachableURL() &&
       !response.isMultipartPayload() && (response.httpStatusCode() != 404);
 
-  params.searchable_form_url = document_state->searchable_form_url();
-  params.searchable_form_encoding =
-      document_state->searchable_form_encoding();
+  params.searchable_form_url = internal_data->searchable_form_url();
+  params.searchable_form_encoding = internal_data->searchable_form_encoding();
 
-  const PasswordForm* password_form_data =
-      document_state->password_form_data();
+  const PasswordForm* password_form_data = document_state->password_form_data();
   if (password_form_data)
     params.password_form = *password_form_data;
 
@@ -1715,12 +1752,14 @@
     }
 
     // Send the user agent override back.
-    params.is_overriding_user_agent =
-        document_state->is_overriding_user_agent();
+    params.is_overriding_user_agent = internal_data->is_overriding_user_agent();
 
     // Track the URL of the original request.
     params.original_request_url = original_request.url();
 
+    params.history_list_was_cleared =
+        navigation_state->history_list_was_cleared();
+
     // Save some histogram data so we can compute the average memory used per
     // page load of the glyphs.
     UMA_HISTOGRAM_COUNTS_10000("Memory.GlyphPagesPerLoad",
@@ -1742,6 +1781,9 @@
     else
       params.transition = PAGE_TRANSITION_AUTO_SUBFRAME;
 
+    DCHECK(!navigation_state->history_list_was_cleared());
+    params.history_list_was_cleared = false;
+
     Send(new ViewHostMsg_FrameNavigate(routing_id_, params));
   }
 
@@ -1839,7 +1881,7 @@
     error_html = &html;
   } else {
     GetContentClient()->renderer()->GetNavigationErrorStrings(
-        failed_request, error, &alt_html, NULL);
+        frame, failed_request, error, &alt_html, NULL);
     error_html = &alt_html;
   }
 
@@ -1934,7 +1976,7 @@
 
   WebUserGestureIndicator::consumeUserGesture();
 
-  webkit_glue::WebPreferences transferred_preferences = webkit_preferences_;
+  WebPreferences transferred_preferences = webkit_preferences_;
 
   // Unless accelerated compositing has been explicitly disabled from the
   // command line (e.g. via the blacklist or about:flags) re-enable it for
@@ -1990,7 +2032,7 @@
   // By returning NULL in that case, we instruct WebKit to cancel that new
   // popup.  So from the user perspective, only the first one will show, and
   // will have to close the first one before another one can be shown.
-  if (external_popup_menu_.get())
+  if (external_popup_menu_)
     return NULL;
   external_popup_menu_.reset(
       new ExternalPopupMenu(this, popup_menu_info, popup_menu_client));
@@ -2094,11 +2136,6 @@
 
   is_loading_ = false;
 
-  if (pending_frame_tree_update_) {
-    pending_frame_tree_update_ = false;
-    SendUpdatedFrameTree(NULL);
-  }
-
   // NOTE: For now we're doing the safest thing, and sending out notification
   // when done loading. This currently isn't an issue as the favicon is only
   // displayed when done loading. Ideally we would send notification when
@@ -2109,6 +2146,8 @@
   if (load_progress_tracker_ != NULL)
     load_progress_tracker_->DidStopLoading();
 
+  DidStopLoadingIcons();
+
   FOR_EACH_OBSERVER(RenderViewObserver, observers_, DidStopLoading());
 }
 
@@ -2419,10 +2458,6 @@
   Send(new ViewHostMsg_DidChangeNumWheelEvents(routing_id_, num_handlers));
 }
 
-void RenderViewImpl::hasTouchEventHandlers(bool has_handlers) {
-  Send(new ViewHostMsg_HasTouchEventHandlers(routing_id_, has_handlers));
-}
-
 void RenderViewImpl::didUpdateLayout() {
   // We don't always want to set up a timer, only if we've been put in that
   // mode by getting a |ViewMsg_EnablePreferredSizeChangedMode|
@@ -2602,7 +2637,7 @@
 
 #if defined(ENABLE_PLUGINS)
   if (UTF16ToASCII(params.mimeType) == kBrowserPluginMimeType) {
-    return browser_plugin_manager()->CreateBrowserPlugin(this, frame, params);
+    return GetBrowserPluginManager()->CreateBrowserPlugin(this, frame, params);
   }
 
   webkit::WebPluginInfo info;
@@ -2655,6 +2690,11 @@
   const CommandLine* cmd_line = CommandLine::ForCurrentProcess();
 #if defined(ENABLE_WEBRTC)
   if (MediaStreamImpl::CheckMediaStream(url)) {
+#if defined(OS_ANDROID) && defined(ARCH_CPU_ARMEL)
+    bool found_neon =
+        (android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_NEON) != 0;
+    UMA_HISTOGRAM_BOOLEAN("Platform.WebRtcNEONFound", found_neon);
+#endif  // defined(OS_ANDROID) && defined(ARCH_CPU_ARMEL)
     EnsureMediaStreamImpl();
     return new webkit_media::WebMediaPlayerMS(
         frame, client, AsWeakPtr(), media_stream_impl_, new RenderMediaLog());
@@ -2681,31 +2721,21 @@
     media_player_proxy_ = new WebMediaPlayerProxyImplAndroid(
         this, media_player_manager_.get());
   }
-  return new webkit_media::WebMediaPlayerImplAndroid(
+  return new webkit_media::WebMediaPlayerAndroid(
       frame,
       client,
       media_player_manager_.get(),
       media_player_proxy_,
       new StreamTextureFactoryImpl(
-          context_provider->Context3d(), gpu_channel_host, routing_id_));
+          context_provider->Context3d(), gpu_channel_host, routing_id_),
+      new RenderMediaLog());
 #endif
 
   scoped_refptr<media::AudioRendererSink> sink;
   if (!cmd_line->HasSwitch(switches::kDisableAudio)) {
-    if (!cmd_line->HasSwitch(switches::kDisableRendererSideMixing)) {
-      sink = RenderThreadImpl::current()->GetAudioRendererMixerManager()->
-          CreateInput(routing_id_);
-      DVLOG(1) << "Using AudioRendererMixerManager-provided sink: " << sink;
-    } else {
-      scoped_refptr<RendererAudioOutputDevice> device =
-          AudioDeviceFactory::NewOutputDevice();
-      // The RenderView creating AudioRendererSink will be the source of
-      // the audio (WebMediaPlayer is always associated with a document in a
-      // frame at the time RenderAudioSourceProvider is instantiated).
-      device->SetSourceRenderView(routing_id_);
-      sink = device;
-      DVLOG(1) << "Using AudioDeviceFactory-provided sink: " << sink;
-    }
+    sink = RenderThreadImpl::current()->GetAudioRendererMixerManager()->
+        CreateInput(routing_id_);
+    DVLOG(1) << "Using AudioRendererMixerManager-provided sink: " << sink;
   }
 
   scoped_refptr<media::GpuVideoDecoder::Factories> gpu_factories;
@@ -2750,19 +2780,14 @@
 }
 
 void RenderViewImpl::didCreateFrame(WebFrame* parent, WebFrame* child) {
-  if (!updating_frame_tree_)
-    SendUpdatedFrameTree(NULL);
 }
 
 void RenderViewImpl::didDisownOpener(WebKit::WebFrame* frame) {
-  // We should only hear this from the top-level frame, because subframes do not
-  // have openers.
-  CHECK(!frame->parent());
-
-  // We only need to notify the browser if the active frame clears its opener.
-  // We can ignore cases where a swapped out frame clears its opener after
-  // hearing about it from the browser.
-  if (is_swapped_out_)
+  // We only need to notify the browser if the active, top-level frame clears
+  // its opener.  We can ignore cases where a swapped out frame clears its
+  // opener after hearing about it from the browser, and the browser does not
+  // (yet) care about subframe openers.
+  if (is_swapped_out_ || frame->parent())
     return;
 
   // Notify WebContents and all its swapped out RenderViews.
@@ -2772,15 +2797,6 @@
 void RenderViewImpl::frameDetached(WebFrame* frame) {
   Send(new ViewHostMsg_FrameDetached(routing_id_, frame->identifier()));
 
-  if (is_loading_) {
-    pending_frame_tree_update_ = true;
-    // Make sure observers are notified, even if we return right away.
-    FOR_EACH_OBSERVER(RenderViewObserver, observers_, FrameDetached(frame));
-    return;
-  }
-  if (!updating_frame_tree_)
-    SendUpdatedFrameTree(frame);
-
   FOR_EACH_OBSERVER(RenderViewObserver, observers_, FrameDetached(frame));
 }
 
@@ -2821,18 +2837,7 @@
 }
 
 SSLStatus RenderViewImpl::GetSSLStatusOfFrame(WebKit::WebFrame* frame) const {
-  SSLStatus ssl_status;
-
-  DocumentState* doc_state = DocumentState::FromDataSource(frame->dataSource());
-  if (doc_state && !doc_state->security_info().empty()) {
-    DeserializeSecurityInfo(doc_state->security_info(),
-                            &ssl_status.cert_id,
-                            &ssl_status.cert_status,
-                            &ssl_status.security_bits,
-                            &ssl_status.connection_status);
-  }
-
-  return ssl_status;
+  return SSLStatus();
 }
 
 void RenderViewImpl::loadURLExternally(
@@ -2851,8 +2856,9 @@
 }
 
 WebNavigationPolicy RenderViewImpl::decidePolicyForNavigation(
-    WebFrame* frame, const WebURLRequest& request, WebNavigationType type,
-    const WebNode&, WebNavigationPolicy default_policy, bool is_redirect) {
+    WebFrame* frame, WebDataSource::ExtraData* extraData,
+    const WebURLRequest& request, WebNavigationType type,
+    WebNavigationPolicy default_policy, bool is_redirect) {
   if (request.url() != GURL(kSwappedOutURL) &&
       GetContentClient()->renderer()->HandleNavigation(frame, request, type,
                                                        default_policy,
@@ -2894,8 +2900,7 @@
 
   // A content initiated navigation may have originated from a link-click,
   // script, drag-n-drop operation, etc.
-  bool is_content_initiated =
-      DocumentState::FromDataSource(frame->provisionalDataSource())->
+  bool is_content_initiated = static_cast<DocumentState*>(extraData)->
           navigation_state()->is_content_initiated();
 
   // Experimental:
@@ -3047,6 +3052,14 @@
   return default_policy;
 }
 
+WebNavigationPolicy RenderViewImpl::decidePolicyForNavigation(
+    WebFrame* frame, const WebURLRequest& request, WebNavigationType type,
+    WebNavigationPolicy default_policy, bool is_redirect) {
+  return decidePolicyForNavigation(frame,
+                                   frame->provisionalDataSource()->extraData(),
+                                   request, type, default_policy, is_redirect);
+}
+
 bool RenderViewImpl::canHandleRequest(
     WebFrame* frame, const WebURLRequest& request) {
   // We allow WebKit to think that everything can be handled even though
@@ -3090,14 +3103,16 @@
   DocumentState* document_state =
       DocumentState::FromDataSource(frame->provisionalDataSource());
   NavigationState* navigation_state = document_state->navigation_state();
+  InternalDocumentStateData* internal_data =
+      InternalDocumentStateData::FromDocumentState(document_state);
 
   if (navigation_state->transition_type() == PAGE_TRANSITION_LINK)
     navigation_state->set_transition_type(PAGE_TRANSITION_FORM_SUBMIT);
 
   // Save these to be processed when the ensuing navigation is committed.
   WebSearchableFormData web_searchable_form_data(form);
-  document_state->set_searchable_form_url(web_searchable_form_data.url());
-  document_state->set_searchable_form_encoding(
+  internal_data->set_searchable_form_url(web_searchable_form_data.url());
+  internal_data->set_searchable_form_encoding(
       web_searchable_form_data.encoding().utf8());
   scoped_ptr<PasswordForm> password_form_data =
       CreatePasswordForm(form);
@@ -3107,7 +3122,7 @@
   // from the form contents already stored by |willSendSubmitEvent| into the
   // dataSource's NavigationState (as opposed to the provisionalDataSource's,
   // which is what we're storing into now.)
-  if (password_form_data.get()) {
+  if (password_form_data) {
     DocumentState* old_document_state =
         DocumentState::FromDataSource(frame->dataSource());
     if (old_document_state) {
@@ -3176,8 +3191,12 @@
     DocumentState* old_document_state =
         DocumentState::FromDataSource(webview()->mainFrame()->dataSource());
     if (old_document_state) {
-      document_state->set_is_overriding_user_agent(
-          old_document_state->is_overriding_user_agent());
+      InternalDocumentStateData* internal_data =
+          InternalDocumentStateData::FromDocumentState(document_state);
+      InternalDocumentStateData* old_internal_data =
+          InternalDocumentStateData::FromDocumentState(old_document_state);
+      internal_data->set_is_overriding_user_agent(
+          old_internal_data->is_overriding_user_agent());
     }
   }
 
@@ -3245,6 +3264,9 @@
   const ViewMsg_Navigate_Params& params = *pending_navigation_params_.get();
   document_state->set_request_time(params.request_time);
 
+  InternalDocumentStateData* internal_data =
+      InternalDocumentStateData::FromDocumentState(document_state);
+
   if (!params.url.SchemeIs(chrome::kJavaScriptScheme) &&
       params.navigation_type == ViewMsg_Navigate_Type::RESTORE) {
     // We're doing a load of a page that was restored from the last session. By
@@ -3252,7 +3274,7 @@
     // can result in stale data for pages that are set to expire. We explicitly
     // override that by setting the policy here so that as necessary we load
     // from the network.
-    document_state->set_cache_policy_override(
+    internal_data->set_cache_policy_override(
         WebURLRequest::UseProtocolCachePolicy);
   }
 
@@ -3263,9 +3285,9 @@
   else
     document_state->set_load_type(DocumentState::NORMAL_LOAD);
 
-  document_state->set_referrer_policy(params.referrer.policy);
-  document_state->set_is_overriding_user_agent(params.is_overriding_user_agent);
-  document_state->set_must_reset_scroll_and_scale_state(
+  internal_data->set_referrer_policy(params.referrer.policy);
+  internal_data->set_is_overriding_user_agent(params.is_overriding_user_agent);
+  internal_data->set_must_reset_scroll_and_scale_state(
       params.navigation_type ==
           ViewMsg_Navigate_Type::RELOAD_ORIGINAL_REQUEST_URL);
   document_state->set_can_load_local_resources(params.can_load_local_resources);
@@ -3282,6 +3304,7 @@
     navigation_state = NavigationState::CreateBrowserInitiated(
         params.page_id,
         params.pending_history_list_offset,
+        params.should_clear_history_list,
         params.transition);
     navigation_state->set_transferred_request_child_id(
         params.transferred_request_child_id);
@@ -3321,11 +3344,9 @@
         webview()->setFixedLayoutSize(WebSize(width, height));
     }
   }
-
-  if (command_line.HasSwitch(switches::kEnablePinch))
-    webview()->setPageScaleFactorLimits(1, 4);
-  else
-    webview()->setPageScaleFactorLimits(1, 1);
+  float maxPageScaleFactor =
+      command_line.HasSwitch(switches::kEnablePinch) ? 4.f : 1.f ;
+  webview()->setPageScaleFactorLimits(1, maxPageScaleFactor);
 }
 
 void RenderViewImpl::didStartProvisionalLoad(WebFrame* frame) {
@@ -3357,6 +3378,23 @@
     navigation_gesture_ = WebUserGestureIndicator::isProcessingUserGesture() ?
         NavigationGestureUser : NavigationGestureAuto;
 
+    // If the navigation is not triggered by a user gesture, e.g. by some ajax
+    // callback, then inherit the submitted password form from the previous
+    // state. This fixes the no password save issue for ajax login, tracked in
+    // [http://crbug/43219]. Note that there are still some sites that this
+    // fails for because they use some element other than a submit button to
+    // trigger submission.
+    if (navigation_gesture_ == NavigationGestureAuto) {
+      DocumentState* old_document_state = DocumentState::FromDataSource(
+          frame->dataSource());
+      const content::PasswordForm* old_password_form =
+          old_document_state->password_form_data();
+      if (old_password_form) {
+        document_state->set_password_form_data(
+            make_scoped_ptr(new content::PasswordForm(*old_password_form)));
+      }
+    }
+
     // Make sure redirect tracking state is clear for the new load.
     completed_client_redirect_src_ = Referrer();
   } else if (frame->parent()->isLoading()) {
@@ -3419,6 +3457,7 @@
   params.is_main_frame = !frame->parent();
   params.error_code = error.reason;
   GetContentClient()->renderer()->GetNavigationErrorStrings(
+      frame,
       failed_request,
       error,
       NULL,
@@ -3463,6 +3502,8 @@
         navigation_state->pending_page_id();
     pending_navigation_params_->pending_history_list_offset =
         navigation_state->pending_history_list_offset();
+    pending_navigation_params_->should_clear_history_list =
+        navigation_state->history_list_was_cleared();
     pending_navigation_params_->transition =
         navigation_state->transition_type();
     pending_navigation_params_->request_time =
@@ -3480,9 +3521,9 @@
 void RenderViewImpl::didReceiveDocumentData(
     WebFrame* frame, const char* data, size_t data_len,
     bool& prevent_default) {
-  DocumentState* document_state =
-      DocumentState::FromDataSource(frame->dataSource());
-  document_state->set_use_error_page(false);
+  InternalDocumentStateData* internal_data =
+      InternalDocumentStateData::FromDataSource(frame->dataSource());
+  internal_data->set_use_error_page(false);
 }
 
 void RenderViewImpl::didCommitProvisionalLoad(WebFrame* frame,
@@ -3490,13 +3531,15 @@
   DocumentState* document_state =
       DocumentState::FromDataSource(frame->dataSource());
   NavigationState* navigation_state = document_state->navigation_state();
+  InternalDocumentStateData* internal_data =
+      InternalDocumentStateData::FromDocumentState(document_state);
 
   if (document_state->commit_load_time().is_null())
     document_state->set_commit_load_time(Time::Now());
 
-  if (document_state->must_reset_scroll_and_scale_state()) {
+  if (internal_data->must_reset_scroll_and_scale_state()) {
     webview()->resetScrollAndScaleState();
-    document_state->set_must_reset_scroll_and_scale_state(false);
+    internal_data->set_must_reset_scroll_and_scale_state(false);
   }
 
   if (is_new_navigation) {
@@ -3585,7 +3628,7 @@
                     DidClearWindowObject(frame));
 
   if (enabled_bindings_ & BINDINGS_POLICY_DOM_AUTOMATION) {
-    if (!dom_automation_controller_.get())
+    if (!dom_automation_controller_)
       dom_automation_controller_.reset(new DomAutomationController());
     dom_automation_controller_->set_message_sender(
         static_cast<RenderView*>(this));
@@ -3593,8 +3636,6 @@
     dom_automation_controller_->BindToJavascript(frame,
                                                  "domAutomationController");
   }
-
-  InjectDoNotTrackBindings(frame);
 }
 
 void RenderViewImpl::didCreateDocumentElement(WebFrame* frame) {
@@ -3617,8 +3658,21 @@
   UpdateEncoding(frame, frame->view()->pageEncoding().utf8());
 }
 
-void RenderViewImpl::didChangeIcon(WebFrame* frame, WebIconURL::Type type) {
-  favicon_helper_->DidChangeIcon(frame, type);
+void RenderViewImpl::didChangeIcon(WebFrame* frame,
+                                   WebIconURL::Type icon_type) {
+  if (frame->parent())
+    return;
+
+  if (!TouchEnabled() && icon_type != WebIconURL::TypeFavicon)
+    return;
+
+  WebVector<WebIconURL> icon_urls = frame->iconURLs(icon_type);
+  std::vector<FaviconURL> urls;
+  for (size_t i = 0; i < icon_urls.size(); i++) {
+    urls.push_back(FaviconURL(icon_urls[i].iconURL(),
+                              ToFaviconType(icon_urls[i].iconType())));
+  }
+  SendUpdateFaviconURL(urls);
 }
 
 void RenderViewImpl::didFinishDocumentLoad(WebFrame* frame) {
@@ -3652,6 +3706,7 @@
   const WebURLRequest& failed_request = ds->request();
   string16 error_description;
   GetContentClient()->renderer()->GetNavigationErrorStrings(
+      frame,
       failed_request,
       error,
       NULL,
@@ -3728,6 +3783,8 @@
   PageTransition transition_type = PAGE_TRANSITION_LINK;
   DocumentState* document_state = DocumentState::FromDataSource(data_source);
   DCHECK(document_state);
+  InternalDocumentStateData* internal_data =
+      InternalDocumentStateData::FromDocumentState(document_state);
   NavigationState* navigation_state = document_state->navigation_state();
   transition_type = navigation_state->transition_type();
 
@@ -3742,13 +3799,13 @@
     request.setURL(WebURL(new_url));
   }
 
-  if (document_state->is_cache_policy_override_set())
-    request.setCachePolicy(document_state->cache_policy_override());
+  if (internal_data->is_cache_policy_override_set())
+    request.setCachePolicy(internal_data->cache_policy_override());
 
   WebKit::WebReferrerPolicy referrer_policy;
-  if (document_state && document_state->is_referrer_policy_set()) {
-    referrer_policy = document_state->referrer_policy();
-    document_state->clear_referrer_policy();
+  if (internal_data->is_referrer_policy_set()) {
+    referrer_policy = internal_data->referrer_policy();
+    internal_data->clear_referrer_policy();
   } else {
     referrer_policy = frame->document().referrerPolicy();
   }
@@ -3841,18 +3898,20 @@
     document_state->set_was_fetched_via_proxy(
         extra_data->was_fetched_via_proxy());
   }
-  document_state->set_http_status_code(http_status_code);
+  InternalDocumentStateData* internal_data =
+      InternalDocumentStateData::FromDocumentState(document_state);
+  internal_data->set_http_status_code(http_status_code);
   // Whether or not the http status code actually corresponds to an error is
   // only checked when the page is done loading, if |use_error_page| is
   // still true.
-  document_state->set_use_error_page(true);
+  internal_data->set_use_error_page(true);
 }
 
 void RenderViewImpl::didFinishResourceLoad(
     WebFrame* frame, unsigned identifier) {
-  DocumentState* document_state =
-      DocumentState::FromDataSource(frame->dataSource());
-  if (!document_state->use_error_page())
+  InternalDocumentStateData* internal_data =
+      InternalDocumentStateData::FromDataSource(frame->dataSource());
+  if (!internal_data->use_error_page())
     return;
 
   // Do not show error page when DevTools is attached.
@@ -3860,7 +3919,7 @@
     return;
 
   // Display error page, if appropriate.
-  int http_status_code = document_state->http_status_code();
+  int http_status_code = internal_data->http_status_code();
   if (http_status_code == 404) {
     // On 404s, try a remote search page as a fallback.
     const GURL& document_url = frame->document().url();
@@ -3873,9 +3932,10 @@
       original_error.reason = 404;
       original_error.unreachableURL = document_url;
 
-      document_state->set_alt_error_page_fetcher(
+      internal_data->set_alt_error_page_fetcher(
           new AltErrorPageResourceFetcher(
-              error_page_url, frame, original_error,
+              error_page_url, frame, frame->dataSource()->request(),
+              original_error,
               base::Bind(&RenderViewImpl::AltErrorPageFinished,
                          base::Unretained(this))));
       return;
@@ -3977,73 +4037,12 @@
                                                       preferred_size_));
 }
 
-// The browser process needs to know the shape of the tree, as well as the names
-// and ids of all frames. This allows it to properly route JavaScript messages
-// across processes and frames. The serialization format is described in the
-// comments of the ViewMsg_FrameTreeUpdated message.
-// This function sends those updates to the browser and updates the RVH
-// corresponding to this object. It must be called on any events that modify
-// the tree structure or the names of any frames.
-void RenderViewImpl::SendUpdatedFrameTree(
-    WebKit::WebFrame* exclude_frame_subtree) {
-  // TODO(nasko): Frame tree updates are causing issues with postMessage, as
-  // described in http://crbug.com/153701. Disable them until a proper fix is
-  // in place.
-}
-
-BrowserPluginManager* RenderViewImpl::browser_plugin_manager() {
+BrowserPluginManager* RenderViewImpl::GetBrowserPluginManager() {
   if (!browser_plugin_manager_)
     browser_plugin_manager_ = BrowserPluginManager::Create(this);
   return browser_plugin_manager_;
 }
 
-void RenderViewImpl::CreateFrameTree(WebKit::WebFrame* frame,
-                                     base::DictionaryValue* frame_tree) {
-  // TODO(nasko): Remove once http://crbug.com/153701 is fixed.
-  DCHECK(false);
-  NavigateToSwappedOutURL(frame);
-
-  string16 name;
-  if (frame_tree->GetString(kFrameTreeNodeNameKey, &name) && !name.empty())
-    frame->setName(name);
-
-  int remote_id;
-  if (frame_tree->GetInteger(kFrameTreeNodeIdKey, &remote_id))
-    active_frame_id_map_.insert(std::pair<int, int>(frame->identifier(),
-                                                    remote_id));
-
-  base::ListValue* children;
-  if (!frame_tree->GetList(kFrameTreeNodeSubtreeKey, &children))
-    return;
-
-  // Create an invisible iframe tree in the swapped out page.
-  base::DictionaryValue* child;
-  for (size_t i = 0; i < children->GetSize(); ++i) {
-    if (!children->GetDictionary(i, &child))
-      continue;
-    WebElement element = frame->document().createElement("iframe");
-    element.setAttribute("width", "0");
-    element.setAttribute("height", "0");
-    element.setAttribute("frameBorder", "0");
-    if (frame->document().body().appendChild(element)) {
-      WebFrame* subframe = WebFrame::fromFrameOwnerElement(element);
-      if (subframe)
-        CreateFrameTree(subframe, child);
-    } else {
-      LOG(ERROR) << "Failed to append created iframe element.";
-    }
-  }
-}
-
-WebKit::WebFrame* RenderViewImpl::GetFrameByRemoteID(int remote_frame_id) {
-  std::map<int, int>::const_iterator it = active_frame_id_map_.begin();
-  for (; it != active_frame_id_map_.end(); ++it) {
-    if (it->second == remote_frame_id)
-      return FindFrameByID(webview()->mainFrame(), it->first);
-  }
-  return NULL;
-}
-
 void RenderViewImpl::EnsureMediaStreamImpl() {
   if (!RenderThreadImpl::current())  // Will be NULL during unit tests.
     return;
@@ -4061,7 +4060,6 @@
     media_stream_impl_ = new MediaStreamImpl(
         this,
         media_stream_dispatcher_,
-        RenderThreadImpl::current()->video_capture_impl_manager(),
         RenderThreadImpl::current()->GetMediaStreamDependencyFactory());
   }
 #endif
@@ -4124,11 +4122,15 @@
   }
 }
 
-#if defined(OS_ANDROID)
 void RenderViewImpl::didFirstVisuallyNonEmptyLayout(WebFrame* frame) {
   if (frame != webview()->mainFrame())
     return;
 
+  InternalDocumentStateData* data =
+      InternalDocumentStateData::FromDataSource(frame->dataSource());
+  data->set_did_first_visually_non_empty_layout(true);
+
+#if defined(OS_ANDROID)
   // Update body background color if necessary.
   SkColor bg_color = webwidget_->backgroundColor();
 
@@ -4141,8 +4143,8 @@
     body_background_color_ = bg_color;
     Send(new ViewHostMsg_DidChangeBodyBackgroundColor(routing_id_, bg_color));
   }
-}
 #endif
+}
 
 void RenderViewImpl::SendFindReply(int request_id,
                                    int match_count,
@@ -4297,21 +4299,6 @@
   RenderViewImpl* source_view = FromWebView(sourceFrame->view());
   if (source_view)
     params.source_routing_id = source_view->routing_id();
-  params.source_frame_id = sourceFrame->identifier();
-
-  // Include the process, route, and frame IDs of the target frame. This allows
-  // the browser to detect races between this message being sent and the target
-  // frame no longer being valid.
-  params.target_process_id = target_process_id_;
-  params.target_routing_id = target_routing_id_;
-
-  std::map<int, int>::iterator it = active_frame_id_map_.find(
-      targetFrame->identifier());
-  if (it != active_frame_id_map_.end()) {
-    params.target_frame_id = it->second;
-  } else {
-    params.target_frame_id = 0;
-  }
 
   Send(new ViewHostMsg_RouteMessageEvent(routing_id_, params));
   return true;
@@ -4346,12 +4333,17 @@
   else
     data_source = main_frame->dataSource();
 
-  DocumentState* document_state =
-      data_source ? DocumentState::FromDataSource(data_source) : NULL;
-  if (document_state && document_state->is_overriding_user_agent())
+  InternalDocumentStateData* internal_data = data_source ?
+      InternalDocumentStateData::FromDataSource(data_source) : NULL;
+  if (internal_data && internal_data->is_overriding_user_agent())
     return WebString::fromUTF8(renderer_preferences_.user_agent_override);
-  else
-    return WebKit::WebString();
+  return WebKit::WebString();
+}
+
+WebString RenderViewImpl::doNotTrackValue(WebFrame* frame) {
+  if (renderer_preferences_.enable_do_not_track)
+    return WebString::fromUTF8("1");
+  return WebString();
 }
 
 bool RenderViewImpl::allowWebGL(WebFrame* frame, bool default_value) {
@@ -4695,6 +4687,7 @@
     selection_range_ = range;
     Send(new ViewHostMsg_SelectionChanged(routing_id_, text, offset, range));
   }
+  UpdateSelectionBounds();
 }
 
 GURL RenderViewImpl::GetAlternateErrorPageURL(const GURL& failed_url,
@@ -4811,7 +4804,8 @@
 
     if (!result) {
       // don't leave text selected as you move to the next frame.
-      search_frame->executeCommand(WebString::fromUTF8("Unselect"));
+      search_frame->executeCommand(WebString::fromUTF8("Unselect"),
+                                   GetFocusedNode());
 
       // Find the next frame, but skip the invisible ones.
       do {
@@ -4824,7 +4818,8 @@
                search_frame != focused_frame);
 
       // Make sure selection doesn't affect the search operation in new frame.
-      search_frame->executeCommand(WebString::fromUTF8("Unselect"));
+      search_frame->executeCommand(WebString::fromUTF8("Unselect"),
+                                   GetFocusedNode());
 
       // If we have multiple frames and we have wrapped back around to the
       // focused frame, we need to search it once more allowing wrap within
@@ -4897,8 +4892,10 @@
   }
 
   bool clear_selection = action == STOP_FIND_ACTION_CLEAR_SELECTION;
-  if (clear_selection)
-    view->focusedFrame()->executeCommand(WebString::fromUTF8("Unselect"));
+  if (clear_selection) {
+    view->focusedFrame()->executeCommand(WebString::fromUTF8("Unselect"),
+                                         GetFocusedNode());
+  }
 
   WebFrame* frame = view->mainFrame();
   while (frame) {
@@ -5075,24 +5072,20 @@
                                          const string16& jscript,
                                          int id,
                                          bool notify_result) {
-  TRACE_EVENT_INSTANT0("test_tracing", "OnScriptEvalRequest");
+  TRACE_EVENT_INSTANT0("test_tracing", "OnScriptEvalRequest",
+                       TRACE_EVENT_SCOPE_THREAD);
   EvaluateScript(frame_xpath, jscript, id, notify_result);
 }
 
 void RenderViewImpl::OnPostMessageEvent(
     const ViewMsg_PostMessage_Params& params) {
-  // Find the target frame of this message. The source tags the message with
-  // |target_frame_id|, so use it to locate the frame.
-  // TODO(nasko): Lookup based on the frame id, once http://crbug.com/153701
-  // is fixed and we can rely on having frame tree updates again.
+  // TODO(nasko): Support sending to subframes.
   WebFrame* frame = webview()->mainFrame();
 
   // Find the source frame if it exists.
   WebFrame* source_frame = NULL;
   if (params.source_routing_id != MSG_ROUTING_NONE) {
     RenderViewImpl* source_view = FromRoutingID(params.source_routing_id);
-    // TODO(nasko): Lookup based on the frame id, once http://crbug.com/153701
-    // is fixed and we can rely on having frame tree updates again.
     if (source_view)
       source_frame = source_view->webview()->mainFrame();
   }
@@ -5198,7 +5191,7 @@
 
 void RenderViewImpl::OnUpdateWebPreferences(const WebPreferences& prefs) {
   webkit_preferences_ = prefs;
-  webkit_preferences_.Apply(webview());
+  webkit_glue::ApplyWebPreferences(webkit_preferences_, webview());
 }
 
 void RenderViewImpl::OnUpdateTimezone() {
@@ -5546,6 +5539,9 @@
   if (!error_page_url.is_valid())
     return false;
 
+  WebDataSource* ds = frame->provisionalDataSource();
+  const WebURLRequest& failed_request = ds->request();
+
   // Load an empty page first so there is an immediate response to the error,
   // and then kick off a request for the alternate error page.
   frame->loadHTMLString(std::string(),
@@ -5556,23 +5552,24 @@
   // Now, create a fetcher for the error page and associate it with the data
   // source we just created via the LoadHTMLString call.  That way if another
   // navigation occurs, the fetcher will get destroyed.
-  DocumentState* document_state =
-      DocumentState::FromDataSource(frame->provisionalDataSource());
-  document_state->set_alt_error_page_fetcher(
+  InternalDocumentStateData* internal_data =
+      InternalDocumentStateData::FromDataSource(frame->provisionalDataSource());
+  internal_data->set_alt_error_page_fetcher(
       new AltErrorPageResourceFetcher(
-          error_page_url, frame, error,
+          error_page_url, frame, failed_request, error,
           base::Bind(&RenderViewImpl::AltErrorPageFinished,
                      base::Unretained(this))));
   return true;
 }
 
 void RenderViewImpl::AltErrorPageFinished(WebFrame* frame,
+                                          const WebURLRequest& original_request,
                                           const WebURLError& original_error,
                                           const std::string& html) {
   // Here, we replace the blank page we loaded previously.
   // If we failed to download the alternate error page, LoadNavigationErrorPage
   // will simply display a default error page.
-  LoadNavigationErrorPage(frame, WebURLRequest(), original_error, html, true);
+  LoadNavigationErrorPage(frame, original_request, original_error, html, true);
 }
 
 void RenderViewImpl::OnMoveOrResizeStarted() {
@@ -5627,6 +5624,14 @@
   if (!main_frame->provisionalDataSource()) {
     WebDataSource* ds = main_frame->dataSource();
     DocumentState* document_state = DocumentState::FromDataSource(ds);
+    InternalDocumentStateData* data =
+        InternalDocumentStateData::FromDocumentState(document_state);
+    if (data->did_first_visually_non_empty_layout() &&
+        !data->did_first_visually_non_empty_paint()) {
+      data->set_did_first_visually_non_empty_paint(true);
+      Send(new ViewHostMsg_DidFirstVisuallyNonEmptyPaint(routing_id_,
+                                                         page_id_));
+    }
 
     // TODO(jar): The following code should all be inside a method, probably in
     // NavigatorState.
@@ -5697,26 +5702,6 @@
 #endif
 }
 
-void RenderViewImpl::OnSetNavigationStartTime(
-    const base::TimeTicks& browser_navigation_start) {
-  // Only the initial navigation can be a cross-renderer navigation. If we've
-  // already navigated away from that page, we can ignore this message.
-  if (page_id_ != -1)
-    return;
-
-  if (!webview() || !webview()->mainFrame() ||
-      !webview()->mainFrame()->provisionalDataSource())
-    return;
-
-  // browser_navigation_start is likely before this process existed, so we can't
-  // use InterProcessTimeTicksConverter. Instead, the best we can do is just
-  // ensure we don't report a bogus value in the future.
-  base::TimeTicks navigation_start = std::min(base::TimeTicks::Now(),
-                                              browser_navigation_start);
-  webview()->mainFrame()->provisionalDataSource()->setNavigationStartTime(
-      (navigation_start - base::TimeTicks()).InSecondsF());
-}
-
 #if defined(OS_MACOSX)
 void RenderViewImpl::OnSetWindowVisibility(bool visible) {
   // Inform plugins that their container has changed visibility.
@@ -5749,11 +5734,6 @@
 }
 #endif  // OS_MACOSX
 
-void RenderViewImpl::OnSetEditCommandsForNextKeyEvent(
-    const EditCommands& edit_commands) {
-  edit_commands_ = edit_commands;
-}
-
 void RenderViewImpl::Close() {
   // We need to grab a pointer to the doomed WebView before we destroy it.
   WebView* doomed = webview();
@@ -5811,6 +5791,11 @@
   // only be freed once the tab is destroyed or if the user navigates away
   // via WebMediaPlayerAndroid::Destroy
   media_player_manager_->ReleaseMediaResources();
+
+#if defined(ENABLE_WEBRTC)
+  RenderThreadImpl::current()->video_capture_impl_manager()->
+      SuspendDevices(true);
+#endif
 #endif
 
   if (webview()) {
@@ -5835,6 +5820,11 @@
 void RenderViewImpl::OnWasShown(bool needs_repainting) {
   RenderWidget::OnWasShown(needs_repainting);
 
+#if defined(OS_ANDROID) && defined(ENABLE_WEBRTC)
+  RenderThreadImpl::current()->video_capture_impl_manager()->
+      SuspendDevices(false);
+#endif
+
   if (webview()) {
     webview()->settings()->setMinimumTimerInterval(
         webkit_glue::kForegroundTabTimerInterval);
@@ -5887,7 +5877,7 @@
   pepper_helper_->OnSetFocus(enable);
   // Notify all BrowserPlugins of the RenderView's focus state.
   if (browser_plugin_manager_)
-    browser_plugin_manager()->UpdateFocusState();
+    browser_plugin_manager_->UpdateFocusState();
 }
 
 void RenderViewImpl::PpapiPluginFocusChanged() {
@@ -6030,6 +6020,9 @@
   }
   if (auto_resize_mode_)
     AutoResizeCompositor();
+
+  if (browser_plugin_manager_)
+    browser_plugin_manager_->UpdateDeviceScaleFactor(device_scale_factor_);
 }
 
 ui::TextInputType RenderViewImpl::GetTextInputType() {
@@ -6293,10 +6286,12 @@
 
 void RenderViewImpl::scheduleContentIntent(const WebURL& intent) {
   // Introduce a short delay so that the user can notice the content.
-  MessageLoop::current()->PostDelayedTask(
+  base::MessageLoop::current()->PostDelayedTask(
       FROM_HERE,
-      base::Bind(&RenderViewImpl::LaunchAndroidContentIntent, AsWeakPtr(),
-          intent, expected_content_intent_id_),
+      base::Bind(&RenderViewImpl::LaunchAndroidContentIntent,
+                 AsWeakPtr(),
+                 intent,
+                 expected_content_intent_id_),
       base::TimeDelta::FromMilliseconds(kContentIntentDelayMilliseconds));
 }
 
@@ -6372,7 +6367,7 @@
   // a select faster than it takes for the show-select-popup IPC message to make
   // it to the browser UI thread.  Ignore the extra-messages.
   // TODO(jcivelli): http:/b/5793321 Implement a better fix, as detailed in bug.
-  if (!external_popup_menu_.get())
+  if (!external_popup_menu_)
     return;
 
   external_popup_menu_->DidSelectItems(canceled, selected_indices);
@@ -6396,6 +6391,11 @@
   }
 }
 
+void RenderViewImpl::OnShowContextMenu() {
+  if (webview())
+    webview()->showContextMenu();
+}
+
 void RenderViewImpl::OnEnableViewSourceMode() {
   if (!webview())
     return;
@@ -6421,32 +6421,6 @@
     main_frame->setOpener(NULL);
 }
 
-void RenderViewImpl::OnUpdatedFrameTree(
-    int process_id,
-    int route_id,
-    const std::string& frame_tree) {
-  // TODO(nasko): Remove once http://crbug.com/153701 is fixed.
-  DCHECK(false);
-  // We should only act on this message if we are swapped out.  It's possible
-  // for this to happen due to races.
-  if (!is_swapped_out_)
-    return;
-
-  base::DictionaryValue* frames = NULL;
-  scoped_ptr<base::Value> tree(base::JSONReader::Read(frame_tree));
-  if (tree.get() && tree->IsType(base::Value::TYPE_DICTIONARY))
-    tree->GetAsDictionary(&frames);
-
-  updating_frame_tree_ = true;
-  active_frame_id_map_.clear();
-
-  target_process_id_ = process_id;
-  target_routing_id_ = route_id;
-  CreateFrameTree(webview()->mainFrame(), frames);
-
-  updating_frame_tree_ = false;
-}
-
 #if defined(OS_ANDROID)
 bool RenderViewImpl::didTapMultipleTargets(
     const WebKit::WebGestureEvent& event,
@@ -6470,7 +6444,7 @@
     scoped_ptr<skia::PlatformCanvas> canvas(
         RenderProcess::current()->GetDrawingCanvas(&transport_dib,
                                                    gfx::Rect(canvas_size)));
-    if (!canvas.get())
+    if (!canvas)
       return false;
 
     // TODO(trchen): Cleanup the device scale factor mess.
@@ -6537,4 +6511,28 @@
   FOR_EACH_OBSERVER(RenderViewObserver, observers_, DidCommitCompositorFrame());
 }
 
+void RenderViewImpl::SendUpdateFaviconURL(const std::vector<FaviconURL>& urls) {
+  if (!urls.empty())
+    Send(new ViewHostMsg_UpdateFaviconURL(routing_id_, page_id_, urls));
+}
+
+void RenderViewImpl::DidStopLoadingIcons() {
+  int icon_types = WebIconURL::TypeFavicon;
+  if (TouchEnabled())
+    icon_types |= WebIconURL::TypeTouchPrecomposed | WebIconURL::TypeTouch;
+
+  WebVector<WebIconURL> icon_urls =
+      webview()->mainFrame()->iconURLs(icon_types);
+
+  std::vector<FaviconURL> urls;
+  for (size_t i = 0; i < icon_urls.size(); i++) {
+    WebURL url = icon_urls[i].iconURL();
+    if (!url.isEmpty())
+      urls.push_back(FaviconURL(url,
+                                ToFaviconType(icon_urls[i].iconType())));
+  }
+  SendUpdateFaviconURL(urls);
+}
+
+
 }  // namespace content
diff --git a/content/renderer/render_view_impl.h b/content/renderer/render_view_impl.h
index a778fb4..09092c0 100644
--- a/content/renderer/render_view_impl.h
+++ b/content/renderer/render_view_impl.h
@@ -19,7 +19,6 @@
 #include "base/observer_list.h"
 #include "base/process.h"
 #include "base/timer.h"
-#include "base/values.h"
 #include "build/build_config.h"
 #include "content/common/content_export.h"
 #include "content/common/drag_event_source_info.h"
@@ -41,6 +40,7 @@
 #include "third_party/WebKit/Source/Platform/chromium/public/WebFileSystem.h"
 #include "third_party/WebKit/Source/Platform/chromium/public/WebGraphicsContext3D.h"
 #include "third_party/WebKit/Source/WebKit/chromium/public/WebConsoleMessage.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebDataSource.h"
 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrameClient.h"
 #include "third_party/WebKit/Source/WebKit/chromium/public/WebHistoryItem.h"
 #include "third_party/WebKit/Source/WebKit/chromium/public/WebIconURL.h"
@@ -97,7 +97,6 @@
 
 #if defined(OS_ANDROID)
 namespace webkit_media {
-class MediaPlayerBridgeManagerImpl;
 class WebMediaPlayerManagerAndroid;
 }
 #endif
@@ -169,6 +168,7 @@
 class SpeechRecognitionDispatcher;
 class WebPluginDelegateProxy;
 struct CustomContextMenuContext;
+struct FaviconURL;
 struct FileChooserParams;
 struct RenderViewImplParams;
 
@@ -211,7 +211,7 @@
   static RenderViewImpl* Create(
       int32 opener_id,
       const RendererPreferences& renderer_prefs,
-      const webkit_glue::WebPreferences& webkit_prefs,
+      const WebPreferences& webkit_prefs,
       SharedRenderViewCounter* counter,
       int32 routing_id,
       int32 surface_id,
@@ -240,14 +240,10 @@
 
   int history_list_offset() const { return history_list_offset_; }
 
-  const webkit_glue::WebPreferences& webkit_preferences() const {
+  const WebPreferences& webkit_preferences() const {
     return webkit_preferences_;
   }
 
-  bool enable_do_not_track() const {
-    return renderer_preferences_.enable_do_not_track;
-  }
-
   void set_send_content_state_immediately(bool value) {
     send_content_state_immediately_ = value;
   }
@@ -267,7 +263,7 @@
 #endif
 
   // Lazily initialize this view's BrowserPluginManager and return it.
-  BrowserPluginManager* browser_plugin_manager();
+  BrowserPluginManager* GetBrowserPluginManager();
 
   // Functions to add and remove observers for this object.
   void AddObserver(RenderViewObserver* observer);
@@ -466,7 +462,6 @@
   virtual void focusPrevious();
   virtual void focusedNodeChanged(const WebKit::WebNode& node);
   virtual void numberOfWheelEventHandlersChanged(unsigned num_handlers);
-  virtual void hasTouchEventHandlers(bool has_handlers);
   virtual void didUpdateLayout();
 #if defined(OS_ANDROID)
   virtual bool didTapMultipleTargets(
@@ -538,11 +533,20 @@
                                  const WebKit::WebURLRequest& request,
                                  WebKit::WebNavigationPolicy policy,
                                  const WebKit::WebString& suggested_name);
+
+  // The WebDataSource::ExtraData* is assumed to be a DocumentState* subclass.
+  virtual WebKit::WebNavigationPolicy decidePolicyForNavigation(
+      WebKit::WebFrame* frame,
+      WebKit::WebDataSource::ExtraData* extraData,
+      const WebKit::WebURLRequest& request,
+      WebKit::WebNavigationType type,
+      WebKit::WebNavigationPolicy default_policy,
+      bool is_redirect);
+  // DEPRECATED.
   virtual WebKit::WebNavigationPolicy decidePolicyForNavigation(
       WebKit::WebFrame* frame,
       const WebKit::WebURLRequest& request,
       WebKit::WebNavigationType type,
-      const WebKit::WebNode&,
       WebKit::WebNavigationPolicy default_policy,
       bool is_redirect);
   virtual bool canHandleRequest(WebKit::WebFrame* frame,
@@ -629,9 +633,7 @@
                                         int world_id);
   virtual void didChangeScrollOffset(WebKit::WebFrame* frame);
   virtual void willInsertBody(WebKit::WebFrame* frame) OVERRIDE;
-#if defined(OS_ANDROID)
   virtual void didFirstVisuallyNonEmptyLayout(WebKit::WebFrame*) OVERRIDE;
-#endif
   virtual void didChangeContentsSize(WebKit::WebFrame* frame,
                                      const WebKit::WebSize& size);
   virtual void reportFindInPageMatchCount(int request_id,
@@ -669,6 +671,7 @@
   virtual WebKit::WebString userAgentOverride(
       WebKit::WebFrame* frame,
       const WebKit::WebURL& url) OVERRIDE;
+  virtual WebKit::WebString doNotTrackValue(WebKit::WebFrame* frame) OVERRIDE;
   virtual bool allowWebGL(WebKit::WebFrame* frame, bool default_value) OVERRIDE;
   virtual void didLoseWebGLContext(
       WebKit::WebFrame* frame,
@@ -687,9 +690,8 @@
   virtual int GetRoutingID() const OVERRIDE;
   virtual int GetPageId() const OVERRIDE;
   virtual gfx::Size GetSize() const OVERRIDE;
-  virtual webkit_glue::WebPreferences& GetWebkitPreferences() OVERRIDE;
-  virtual void SetWebkitPreferences(
-      const webkit_glue::WebPreferences& preferences) OVERRIDE;
+  virtual WebPreferences& GetWebkitPreferences() OVERRIDE;
+  virtual void SetWebkitPreferences(const WebPreferences& preferences) OVERRIDE;
   virtual WebKit::WebView* GetWebView() OVERRIDE;
   virtual WebKit::WebNode GetFocusedNode() const OVERRIDE;
   virtual WebKit::WebNode GetContextMenuNode() const OVERRIDE;
@@ -826,6 +828,10 @@
   FRIEND_TEST_ALL_PREFIXES(ExternalPopupMenuTest, ShowPopupThenNavigate);
   FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest, DecideNavigationPolicyForWebUI);
   FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest,
+                           DidFailProvisionalLoadWithErrorForError);
+  FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest,
+                           DidFailProvisionalLoadWithErrorForCancellation);
+  FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest,
                            DontIgnoreBackAfterNavEntryLimit);
   FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest, ImeComposition);
   FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest, InsertCharacters);
@@ -905,7 +911,24 @@
   // IPC message handlers ------------------------------------------------------
   //
   // The documentation for these functions should be in
-  // render_messages_internal.h for the message that the function is handling.
+  // content/common/*_messages.h for the message that the function is handling.
+
+  void OnCopy();
+  void OnCut();
+  void OnDelete();
+  void OnExecuteEditCommand(const std::string& name, const std::string& value);
+  void OnMoveCaret(const gfx::Point& point);
+  void OnPaste();
+  void OnPasteAndMatchStyle();
+  void OnRedo();
+  void OnReplace(const string16& text);
+  void OnReplaceMisspelling(const string16& text);
+  void OnScrollFocusedEditableNodeIntoRect(const gfx::Rect& rect);
+  void OnSelectAll();
+  void OnSelectRange(const gfx::Point& start, const gfx::Point& end);
+  void OnSetEditCommandsForNextKeyEvent(const EditCommands& edit_commands);
+  void OnUndo();
+  void OnUnselect();
 
   void OnAllowBindings(int enabled_bindings_flags);
   void OnAllowScriptToClose(bool script_can_close);
@@ -920,14 +943,12 @@
   void OnClearFocusedNode();
   void OnClosePage();
   void OnContextMenuClosed(const CustomContextMenuContext& custom_context);
-  void OnCopy();
+  void OnShowContextMenu();
   void OnCopyImageAt(int x, int y);
-  void OnCut();
   void OnCSSInsertRequest(const string16& frame_xpath,
                           const std::string& css);
   void OnCustomContextMenuAction(const CustomContextMenuContext& custom_context,
       unsigned action);
-  void OnDelete();
   void OnSetName(const std::string& name);
   void OnDeterminePageLanguage();
   void OnDisableScrollbarsForSmallWindows(
@@ -956,7 +977,6 @@
   void OnDisableAutoResize(const gfx::Size& new_size);
   void OnEnumerateDirectoryResponse(int id,
                                     const std::vector<base::FilePath>& paths);
-  void OnExecuteEditCommand(const std::string& name, const std::string& value);
   void OnExtendSelectionAndDelete(int before, int after);
   void OnFileChooserResponse(
       const std::vector<ui::SelectedFileInfo>& files);
@@ -976,22 +996,14 @@
                         const WebKit::WebPluginAction& action);
   void OnMoveOrResizeStarted();
   void OnNavigate(const ViewMsg_Navigate_Params& params);
-  void OnPaste();
-  void OnPasteAndMatchStyle();
   void OnPostMessageEvent(const ViewMsg_PostMessage_Params& params);
-  void OnRedo();
   void OnReleaseDisambiguationPopupDIB(TransportDIB::Handle dib_handle);
   void OnReloadFrame();
-  void OnReplace(const string16& text);
-  void OnReplaceMisspelling(const string16& text);
   void OnResetPageEncodingToDefault();
   void OnScriptEvalRequest(const string16& frame_xpath,
                            const string16& jscript,
                            int id,
                            bool notify_result);
-  void OnSelectAll();
-  void OnSelectRange(const gfx::Point& start, const gfx::Point& end);
-  void OnMoveCaret(const gfx::Point& point);
   void OnSetAccessibilityMode(AccessibilityMode new_mode);
   void OnSetActive(bool active);
   void OnSetAltErrorPageURL(const GURL& gurl);
@@ -999,29 +1011,23 @@
   void OnSetCompositionFromExistingText(
       int start, int end,
       const std::vector<WebKit::WebCompositionUnderline>& underlines);
+  void OnExitFullscreen();
   void OnSetEditableSelectionOffsets(int start, int end);
-  void OnSetNavigationStartTime(
-      const base::TimeTicks& browser_navigation_start);
-  void OnSetWebUIProperty(const std::string& name, const std::string& value);
-  void OnSetEditCommandsForNextKeyEvent(const EditCommands& edit_commands);
   void OnSetHistoryLengthAndPrune(int history_length, int32 minimum_page_id);
   void OnSetInitialFocus(bool reverse);
-  void OnScrollFocusedEditableNodeIntoRect(const gfx::Rect& rect);
   void OnSetPageEncoding(const std::string& encoding_name);
   void OnSetRendererPrefs(const RendererPreferences& renderer_prefs);
+  void OnSetWebUIProperty(const std::string& name, const std::string& value);
   void OnSetZoomLevel(double zoom_level);
   void OnSetZoomLevelForLoadingURL(const GURL& url, double zoom_level);
-  void OnExitFullscreen();
   void OnShouldClose();
   void OnStop();
   void OnStopFinding(StopFindAction action);
   void OnSwapOut(const ViewMsg_SwapOut_Params& params);
   void OnThemeChanged();
-  void OnUndo();
   void OnUpdateTargetURLAck();
   void OnUpdateTimezone();
-  void OnUpdateWebPreferences(const webkit_glue::WebPreferences& prefs);
-  void OnUnselect();
+  void OnUpdateWebPreferences(const WebPreferences& prefs);
 
   void OnZoom(PageZoom zoom);
   void OnZoomFactor(PageZoom zoom, int zoom_center_x, int zoom_center_y);
@@ -1031,9 +1037,6 @@
   void OnJavaBridgeInit();
 
   void OnDisownOpener();
-  void OnUpdatedFrameTree(int process_id,
-                          int route_id,
-                          const std::string& frame_tree);
 
 #if defined(OS_ANDROID)
   void OnActivateNearestFindResult(int request_id, float x, float y);
@@ -1041,7 +1044,9 @@
   void OnSelectPopupMenuItems(bool canceled,
                               const std::vector<int>& selected_indices);
   void OnUndoScrollFocusedEditableNodeIntoRect();
-  void OnEnableHidingTopControls(bool enable);
+  void OnUpdateTopControlsState(bool enable_hiding,
+                                bool enable_showing,
+                                bool animate);
 #elif defined(OS_MACOSX)
   void OnCopyToFindPboard();
   void OnPluginImeCompositionCompleted(const string16& text, int plugin_id);
@@ -1064,34 +1069,13 @@
                         float scaling_increment);
 
   void AltErrorPageFinished(WebKit::WebFrame* frame,
+                            const WebKit::WebURLRequest& original_request,
                             const WebKit::WebURLError& original_error,
                             const std::string& html);
 
   // Check whether the preferred size has changed.
   void CheckPreferredSize();
 
-  // This method walks the entire frame tree for this RenderView and sends an
-  // update to the browser process as described in the
-  // ViewHostMsg_FrameTreeUpdated comments. If |exclude_frame_subtree|
-  // frame is non-NULL, the subtree starting at that frame not included in the
-  // serialized form.
-  // This is used when a frame is going to be removed from the tree.
-  void SendUpdatedFrameTree(WebKit::WebFrame* exclude_frame_subtree);
-
-  // Recursively creates a DOM frame tree starting with |frame|, based on
-  // |frame_tree|. For each node, the frame is navigated to the swapped out URL,
-  // the name (if present) is set on it, and all the subframes are created
-  // and added to the DOM.
-  void CreateFrameTree(WebKit::WebFrame* frame,
-                       base::DictionaryValue* frame_tree);
-
-  // If this is a swapped out RenderView, which maintains a copy of the frame
-  // tree of an active RenderView, we keep a map from frame ids in this view to
-  // the frame ids of the active view for each corresponding frame.
-  // This method returns the frame in this RenderView that corresponds to the
-  // frame in the active RenderView specified by |remote_frame_id|.
-  WebKit::WebFrame* GetFrameByRemoteID(int remote_frame_id);
-
   void EnsureMediaStreamImpl();
 
   // This callback is triggered when DownloadFavicon completes, either
@@ -1184,6 +1168,13 @@
   // If |url| is empty, show |fallback_url|.
   void UpdateTargetURL(const GURL& url, const GURL& fallback_url);
 
+  // Tells the browser what the new list of favicons for the webpage is.
+  void SendUpdateFaviconURL(const std::vector<FaviconURL>& urls);
+
+  // Invoked from DidStopLoading(). Sends the current list of loaded favicons to
+  // the browser.
+  void DidStopLoadingIcons();
+
   // Coordinate conversion -----------------------------------------------------
 
   gfx::RectF ClientRectToPhysicalWindowRect(const gfx::RectF& rect) const;
@@ -1195,7 +1186,7 @@
 
   // Settings ------------------------------------------------------------------
 
-  webkit_glue::WebPreferences webkit_preferences_;
+  WebPreferences webkit_preferences_;
   RendererPreferences renderer_preferences_;
 
   HostZoomLevels host_zoom_levels_;
@@ -1416,9 +1407,6 @@
   // Mouse Lock dispatcher attached to this view.
   MouseLockDispatcher* mouse_lock_dispatcher_;
 
-  // Helper class to handle favicon changes.
-  FaviconHelper* favicon_helper_;
-
 #if defined(OS_ANDROID)
   // Android Specific ---------------------------------------------------------
 
@@ -1427,9 +1415,6 @@
   // have the actual content.
   SkColor body_background_color_;
 
-  // True if SendUpdateFrameInfo is pending.
-  bool update_frame_info_scheduled_;
-
   // Expected id of the next content intent launched. Used to prevent scheduled
   // intents to be launched if aborted.
   size_t expected_content_intent_id_;
@@ -1445,14 +1430,22 @@
   // The media player manager for managing all the media players on this view.
   scoped_ptr<webkit_media::WebMediaPlayerManagerAndroid> media_player_manager_;
 
-  // Resource manager for all the android media player objects if they are
-  // created in the renderer process.
-  scoped_ptr<webkit_media::MediaPlayerBridgeManagerImpl> media_bridge_manager_;
-
   // A date/time picker object for date and time related input elements.
   scoped_ptr<RendererDateTimePicker> date_time_picker_client_;
 #endif
 
+  // Plugins -------------------------------------------------------------------
+
+  // All the currently active plugin delegates for this RenderView; kept so
+  // that we can enumerate them to send updates about things like window
+  // location or tab focus and visibily. These are non-owning references.
+  std::set<WebPluginDelegateProxy*> plugin_delegates_;
+
+#if defined(OS_WIN)
+  // The ID of the focused NPAPI plug-in.
+  int focused_plugin_id_;
+#endif
+
   // Misc ----------------------------------------------------------------------
 
   // The current and pending file chooser completion objects. If the queue is
@@ -1499,7 +1492,7 @@
   ObserverList<RenderViewObserver> observers_;
 
   // Used to inform didChangeSelection() when it is called in the context
-  // of handling a ViewMsg_SelectRange IPC.
+  // of handling a InputMsg_SelectRange IPC.
   bool handling_select_range_;
 
   // Wraps the |webwidget_| as a MouseLockDispatcher::LockTarget interface.
@@ -1511,52 +1504,14 @@
       PendingSnapshotMap;
   PendingSnapshotMap pending_snapshots_;
 
+  // Allows to selectively disable partial buffer swap for this renderer's
+  // compositor.
   bool allow_partial_swap_;
 
-  // Plugins -------------------------------------------------------------------
-
-  // All the currently active plugin delegates for this RenderView; kept so
-  // that we can enumerate them to send updates about things like window
-  // location or tab focus and visibily. These are non-owning references.
-  std::set<WebPluginDelegateProxy*> plugin_delegates_;
-
-#if defined(OS_WIN)
-  // The ID of the focused NPAPI plug-in.
-  int focused_plugin_id_;
-#endif
-
   // Allows JS to access DOM automation. The JS object is only exposed when the
   // DOM automation bindings are enabled.
   scoped_ptr<DomAutomationController> dom_automation_controller_;
 
-  // Boolean indicating whether we are in the process of creating the frame
-  // tree for this renderer in response to ViewMsg_UpdateFrameTree.  If true,
-  // we won't be sending ViewHostMsg_FrameTreeUpdated messages back to the
-  // browser, as those will be redundant.
-  bool updating_frame_tree_;
-
-  // Boolean indicating that the frame tree has changed, but a message has not
-  // been sent to the browser because a page has been loading. This helps
-  // avoid extra messages being sent to the browser when navigating away from a
-  // page with subframes, which will be destroyed. Instead, a single message
-  // is sent when the load is stopped with the final state of the frame tree.
-  //
-  // TODO(nasko): Relying on the is_loading_ means that frame tree updates will
-  // not be sent until *all* subframes have completed loading. This can cause
-  // JavaScript calls to fail, if they occur prior to the first update message
-  // being sent. This will be fixed by bug http://crbug.com/145014.
-  bool pending_frame_tree_update_;
-
-  // If this render view is a swapped out "mirror" of an active render view in a
-  // different process, we record the process id and route id for the active RV.
-  // For further details, see the comments on ViewHostMsg_FrameTreeUpdated.
-  int target_process_id_;
-  int target_routing_id_;
-
-  // A map of the current process's frame ids to ids in the remote active render
-  // view, if this is a swapped out render view.
-  std::map<int, int> active_frame_id_map_;
-
   // This field stores drag/drop related info for the event that is currently
   // being handled. If the current event results in starting a drag/drop
   // session, this info is sent to the browser along with other drag/drop info.
diff --git a/content/renderer/render_view_impl_android.cc b/content/renderer/render_view_impl_android.cc
index bc061f2..0d5ade1 100644
--- a/content/renderer/render_view_impl_android.cc
+++ b/content/renderer/render_view_impl_android.cc
@@ -11,11 +11,14 @@
 
 namespace content {
 
-void RenderViewImpl::OnEnableHidingTopControls(bool enable) {
-  DCHECK(compositor_);
-  if (compositor_) {
-    compositor_->EnableHidingTopControls(enable);
-  }
+void RenderViewImpl::OnUpdateTopControlsState(bool enable_hiding,
+                                              bool enable_showing,
+                                              bool animate) {
+  // TODO(tedchoc): Investigate why messages are getting here before the
+  //                compositor has been initialized.
+  LOG_IF(WARNING, !compositor_) << "OnUpdateTopControlsState was unhandled.";
+  if (compositor_)
+    compositor_->UpdateTopControlsState(enable_hiding, enable_showing, animate);
 }
 
 }  // namespace content
diff --git a/content/renderer/render_view_impl_params.cc b/content/renderer/render_view_impl_params.cc
index 5035b35..521778b 100644
--- a/content/renderer/render_view_impl_params.cc
+++ b/content/renderer/render_view_impl_params.cc
@@ -9,7 +9,7 @@
 RenderViewImplParams::RenderViewImplParams(
     int32 opener_id,
     const RendererPreferences& renderer_prefs,
-    const webkit_glue::WebPreferences& webkit_prefs,
+    const WebPreferences& webkit_prefs,
     SharedRenderViewCounter* counter,
     int32 routing_id,
     int32 surface_id,
diff --git a/content/renderer/render_view_impl_params.h b/content/renderer/render_view_impl_params.h
index 7288ab1..da29fea 100644
--- a/content/renderer/render_view_impl_params.h
+++ b/content/renderer/render_view_impl_params.h
@@ -11,14 +11,12 @@
 #include "content/common/content_export.h"
 #include "content/common/view_message_enums.h"
 
+struct WebPreferences;
+
 namespace WebKit {
 struct WebScreenInfo;
 }
 
-namespace webkit_glue {
-struct WebPreferences;
-}
-
 namespace content {
 
 struct RendererPreferences;
@@ -28,7 +26,7 @@
 struct CONTENT_EXPORT RenderViewImplParams {
   RenderViewImplParams(int32 opener_id,
                        const RendererPreferences& renderer_prefs,
-                       const webkit_glue::WebPreferences& webkit_prefs,
+                       const WebPreferences& webkit_prefs,
                        SharedRenderViewCounter* counter,
                        int32 routing_id,
                        int32 surface_id,
@@ -44,7 +42,7 @@
 
   int32 opener_id;
   const RendererPreferences& renderer_prefs;
-  const webkit_glue::WebPreferences& webkit_prefs;
+  const WebPreferences& webkit_prefs;
   SharedRenderViewCounter* counter;
   int32 routing_id;
   int32 surface_id;
diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc
index 23511ac..a9069aa 100644
--- a/content/renderer/render_widget.cc
+++ b/content/renderer/render_widget.cc
@@ -20,11 +20,12 @@
 #include "cc/output/output_surface.h"
 #include "cc/trees/layer_tree_host.h"
 #include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h"
+#include "content/common/input_messages.h"
 #include "content/common/swapped_out_messages.h"
 #include "content/common/view_messages.h"
 #include "content/public/common/content_switches.h"
 #include "content/renderer/gpu/compositor_output_surface.h"
-#include "content/renderer/gpu/compositor_software_output_device_gl_adapter.h"
+#include "content/renderer/gpu/compositor_software_output_device.h"
 #include "content/renderer/gpu/input_handler_manager.h"
 #include "content/renderer/gpu/mailbox_output_surface.h"
 #include "content/renderer/gpu/render_widget_compositor.h"
@@ -54,10 +55,13 @@
 #include "ui/surface/transport_dib.h"
 #include "webkit/compositor_bindings/web_rendering_stats_impl.h"
 #include "webkit/glue/webkit_glue.h"
-#include "webkit/gpu/webgraphicscontext3d_in_process_impl.h"
 #include "webkit/plugins/npapi/webplugin.h"
 #include "webkit/plugins/ppapi/ppapi_plugin_instance.h"
 
+#if defined(OS_ANDROID)
+#include "content/renderer/android/synchronous_compositor_output_surface.h"
+#endif
+
 #if defined(OS_POSIX)
 #include "ipc/ipc_channel_posix.h"
 #include "third_party/skia/include/core/SkMallocPixelRef.h"
@@ -171,9 +175,8 @@
       screen_info_(screen_info),
       device_scale_factor_(screen_info_.deviceScaleFactor),
       throttle_input_events_(true),
-      next_smooth_scroll_gesture_id_(0),
       is_threaded_compositing_enabled_(false),
-      ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) {
+      weak_ptr_factory_(this) {
   if (!swapped_out)
     RenderProcess::current()->AddRefProcess();
   DCHECK(RenderThread::Get());
@@ -292,9 +295,24 @@
   return true;
 }
 
+bool RenderWidget::SynchronouslyDisableVSync() const {
+#if defined(OS_ANDROID)
+  if (CommandLine::ForCurrentProcess()->HasSwitch(
+      switches::kEnableSynchronousRendererCompositor)) {
+    return true;
+  }
+#endif
+  return false;
+}
+
 bool RenderWidget::OnMessageReceived(const IPC::Message& message) {
   bool handled = true;
   IPC_BEGIN_MESSAGE_MAP(RenderWidget, message)
+    IPC_MESSAGE_HANDLER(InputMsg_HandleInputEvent, OnHandleInputEvent)
+    IPC_MESSAGE_HANDLER(InputMsg_CursorVisibilityChange,
+                        OnCursorVisibilityChange)
+    IPC_MESSAGE_HANDLER(InputMsg_MouseCaptureLost, OnMouseCaptureLost)
+    IPC_MESSAGE_HANDLER(InputMsg_SetFocus, OnSetFocus)
     IPC_MESSAGE_HANDLER(ViewMsg_Close, OnClose)
     IPC_MESSAGE_HANDLER(ViewMsg_CreatingNew_ACK, OnCreatingNewAck)
     IPC_MESSAGE_HANDLER(ViewMsg_Resize, OnResize)
@@ -305,9 +323,6 @@
     IPC_MESSAGE_HANDLER(ViewMsg_UpdateRect_ACK, OnUpdateRectAck)
     IPC_MESSAGE_HANDLER(ViewMsg_SwapBuffers_ACK,
                         OnViewContextSwapBuffersComplete)
-    IPC_MESSAGE_HANDLER(ViewMsg_HandleInputEvent, OnHandleInputEvent)
-    IPC_MESSAGE_HANDLER(ViewMsg_MouseCaptureLost, OnMouseCaptureLost)
-    IPC_MESSAGE_HANDLER(ViewMsg_SetFocus, OnSetFocus)
     IPC_MESSAGE_HANDLER(ViewMsg_SetInputMethodActive, OnSetInputMethodActive)
     IPC_MESSAGE_HANDLER(ViewMsg_ImeSetComposition, OnImeSetComposition)
     IPC_MESSAGE_HANDLER(ViewMsg_ImeConfirmComposition, OnImeConfirmComposition)
@@ -423,7 +438,7 @@
   // If there is a Send call on the stack, then it could be dangerous to close
   // now.  Post a task that only gets invoked when there are no nested message
   // loops.
-  MessageLoop::current()->PostNonNestableTask(
+  base::MessageLoop::current()->PostNonNestableTask(
       FROM_HERE, base::Bind(&RenderWidget::Close, this));
 
   // Balances the AddRef taken when we called AddRoute.
@@ -556,6 +571,13 @@
 }
 
 scoped_ptr<cc::OutputSurface> RenderWidget::CreateOutputSurface() {
+  const CommandLine& command_line = *CommandLine::ForCurrentProcess();
+  if (command_line.HasSwitch(switches::kEnableSoftwareCompositingGLAdapter)) {
+      return scoped_ptr<cc::OutputSurface>(
+          new CompositorOutputSurface(routing_id(), NULL,
+              new CompositorSoftwareOutputDevice()));
+  }
+
   // Explicitly disable antialiasing for the compositor. As of the time of
   // this writing, the only platform that supported antialiasing for the
   // compositor was Mac OS X, because the on-screen OpenGL context creation
@@ -570,29 +592,30 @@
   attributes.antialias = false;
   attributes.shareResources = true;
   attributes.noAutomaticFlushes = true;
-  WebGraphicsContext3D* context = CreateGraphicsContext3D(attributes);
+  WebGraphicsContext3DCommandBufferImpl* context =
+      CreateGraphicsContext3D(attributes);
   if (!context)
     return scoped_ptr<cc::OutputSurface>();
 
-  const CommandLine& command_line = *CommandLine::ForCurrentProcess();
-  if (command_line.HasSwitch(switches::kEnableSoftwareCompositingGLAdapter)) {
-      // In the absence of a software-based delegating renderer, use this
-      // stopgap adapter class to present the software renderer output using a
-      // 3d context.
-      return scoped_ptr<cc::OutputSurface>(
-          new CompositorOutputSurface(routing_id(), NULL,
-              new CompositorSoftwareOutputDeviceGLAdapter(context)));
-  } else {
-      bool composite_to_mailbox =
-          command_line.HasSwitch(cc::switches::kCompositeToMailbox);
-      DCHECK(!composite_to_mailbox || command_line.HasSwitch(
-          cc::switches::kEnableCompositorFrameMessage));
-      // No swap throttling yet when compositing on the main thread.
-      DCHECK(!composite_to_mailbox || is_threaded_compositing_enabled_);
-      return scoped_ptr<cc::OutputSurface>(composite_to_mailbox ?
-          new MailboxOutputSurface(routing_id(), context, NULL) :
-              new CompositorOutputSurface(routing_id(), context, NULL));
+#if defined(OS_ANDROID)
+  if (command_line.HasSwitch(switches::kEnableSynchronousRendererCompositor)) {
+    // TODO(joth): Move above the |context| creation step above when the
+    // SynchronousCompositor no longer depends on externally created context.
+    return scoped_ptr<cc::OutputSurface>(
+        new SynchronousCompositorOutputSurface(routing_id(),
+                                               context));
   }
+#endif
+
+  bool composite_to_mailbox =
+      command_line.HasSwitch(cc::switches::kCompositeToMailbox);
+  DCHECK(!composite_to_mailbox || command_line.HasSwitch(
+      cc::switches::kEnableCompositorFrameMessage));
+  // No swap throttling yet when compositing on the main thread.
+  DCHECK(!composite_to_mailbox || is_threaded_compositing_enabled_);
+  return scoped_ptr<cc::OutputSurface>(composite_to_mailbox ?
+      new MailboxOutputSurface(routing_id(), context, NULL) :
+          new CompositorOutputSurface(routing_id(), context, NULL));
 }
 
 void RenderWidget::OnViewContextSwapBuffersAborted() {
@@ -619,7 +642,7 @@
     // pending_update_params_ can be NULL if the swap doesn't correspond to an
     // DoDeferredUpdate compositing pass, hence doesn't require an UpdateRect
     // message.
-    if (pending_update_params_.get()) {
+    if (pending_update_params_) {
       msg = new ViewHostMsg_UpdateRect(routing_id_, *pending_update_params_);
       pending_update_params_.reset();
     }
@@ -750,8 +773,8 @@
   }
 
   IPC::Message* response =
-      new ViewHostMsg_HandleInputEvent_ACK(routing_id_, input_event->type,
-                                           ack_result);
+      new InputHostMsg_HandleInputEvent_ACK(routing_id_, input_event->type,
+                                                ack_result);
   bool event_type_gets_rate_limited =
       input_event->type == WebInputEvent::MouseMove ||
       input_event->type == WebInputEvent::MouseWheel ||
@@ -770,7 +793,7 @@
   if (event_type_gets_rate_limited && is_input_throttled && !is_hidden_) {
     // We want to rate limit the input events in this case, so we'll wait for
     // painting to finish before ACKing this message.
-    if (pending_input_event_ack_.get()) {
+    if (pending_input_event_ack_) {
       // As two different kinds of events could cause us to postpone an ack
       // we send it now, if we have one pending. The Browser should never
       // send us the same kind of event we are delaying the ack for.
@@ -800,6 +823,11 @@
   }
 }
 
+void RenderWidget::OnCursorVisibilityChange(bool is_visible) {
+  if (webwidget_)
+    webwidget_->setCursorVisibilityState(is_visible);
+}
+
 void RenderWidget::OnMouseCaptureLost() {
   if (webwidget_)
     webwidget_->mouseCaptureLost();
@@ -924,7 +952,6 @@
   if (kEnableGpuBenchmarking) {
     int64 num_pixels_processed = rect.width() * rect.height();
     software_stats_.total_pixels_painted += num_pixels_processed;
-    software_stats_.total_pixels_rasterized += num_pixels_processed;
   }
 }
 
@@ -1039,7 +1066,7 @@
 void RenderWidget::DoDeferredUpdateAndSendInputAck() {
   DoDeferredUpdate();
 
-  if (pending_input_event_ack_.get())
+  if (pending_input_event_ack_)
     Send(pending_input_event_ack_.release());
 }
 
@@ -1198,7 +1225,7 @@
     scoped_ptr<skia::PlatformCanvas> canvas(
         RenderProcess::current()->GetDrawingCanvas(&current_paint_buf_,
                                                    pixel_bounds));
-    if (!canvas.get()) {
+    if (!canvas) {
       NOTREACHED();
       return;
     }
@@ -1235,7 +1262,8 @@
     // Software FPS tick for performance tests. The accelerated path traces the
     // frame events in didCommitAndDrawCompositorFrame. See throughput_tests.cc.
     // NOTE: Tests may break if this event is renamed or moved.
-    UNSHIPPED_TRACE_EVENT_INSTANT0("test_fps", "TestFrameTickSW");
+    UNSHIPPED_TRACE_EVENT_INSTANT0("test_fps", "TestFrameTickSW",
+                                   TRACE_EVENT_SCOPE_THREAD);
   } else {  // Accelerated compositing path
     // Begin painting.
     // If painting is done via the gpu process then we don't set any damage
@@ -1253,14 +1281,14 @@
   // UpdateReply message so we can receive another input event before the
   // UpdateRect_ACK on platforms where the UpdateRect_ACK is sent from within
   // the UpdateRect IPC message handler.
-  if (pending_input_event_ack_.get())
+  if (pending_input_event_ack_)
     Send(pending_input_event_ack_.release());
 
   // If Composite() called SwapBuffers, pending_update_params_ will be reset (in
   // OnSwapBuffersPosted), meaning a message has been added to the
   // updates_pending_swap_ queue, that will be sent later. Otherwise, we send
   // the message now.
-  if (pending_update_params_.get()) {
+  if (pending_update_params_) {
     // sending an ack to browser process that the paint is complete...
     update_reply_pending_ = pending_update_params_->needs_ack;
     Send(new ViewHostMsg_UpdateRect(routing_id_, *pending_update_params_));
@@ -1314,7 +1342,7 @@
   // 2) Allows us to collect more damage rects before painting to help coalesce
   //    the work that we will need to do.
   invalidation_task_posted_ = true;
-  MessageLoop::current()->PostTask(
+  base::MessageLoop::current()->PostTask(
       FROM_HERE, base::Bind(&RenderWidget::InvalidationCallback, this));
 }
 
@@ -1355,7 +1383,7 @@
   // 2) Allows us to collect more damage rects before painting to help coalesce
   //    the work that we will need to do.
   invalidation_task_posted_ = true;
-  MessageLoop::current()->PostTask(
+  base::MessageLoop::current()->PostTask(
       FROM_HERE, base::Bind(&RenderWidget::InvalidationCallback, this));
 }
 
@@ -1465,7 +1493,7 @@
 
 void RenderWidget::didBecomeReadyForAdditionalInput() {
   TRACE_EVENT0("renderer", "RenderWidget::didBecomeReadyForAdditionalInput");
-  if (pending_input_event_ack_.get())
+  if (pending_input_event_ack_)
     Send(pending_input_event_ack_.release());
 }
 
@@ -1476,7 +1504,8 @@
   TRACE_EVENT0("gpu", "RenderWidget::didCommitAndDrawCompositorFrame");
   // Accelerated FPS tick for performance tests. See throughput_tests.cc.
   // NOTE: Tests may break if this event is renamed or moved.
-  UNSHIPPED_TRACE_EVENT_INSTANT0("test_fps", "TestFrameTickGPU");
+  UNSHIPPED_TRACE_EVENT_INSTANT0("test_fps", "TestFrameTickGPU",
+                                 TRACE_EVENT_SCOPE_THREAD);
   // Notify subclasses that we initiated the paint operation.
   DidInitiatePaint();
 }
@@ -1598,7 +1627,7 @@
   // could be closed before the JS finishes executing.  So instead, post a
   // message back to the message loop, which won't run until the JS is
   // complete, and then the Close message can be sent.
-  MessageLoop::current()->PostTask(
+  base::MessageLoop::current()->PostTask(
       FROM_HERE, base::Bind(&RenderWidget::DoDeferredClose, this));
 }
 
@@ -1796,7 +1825,7 @@
   scoped_ptr<skia::PlatformCanvas> canvas(
       paint_at_size_buffer->GetPlatformCanvas(canvas_size.width(),
                                               canvas_size.height()));
-  if (!canvas.get()) {
+  if (!canvas) {
     NOTREACHED();
     return;
   }
@@ -1854,7 +1883,7 @@
                                  true,
                                  NULL,
                                  skia::RETURN_NULL_ON_FAILURE));
-  if (!canvas.get())
+  if (!canvas)
     return false;
 
   canvas->save();
@@ -1872,28 +1901,28 @@
   return true;
 }
 
-void RenderWidget::OnRepaint(const gfx::Size& size_to_paint) {
+void RenderWidget::OnRepaint(gfx::Size size_to_paint) {
   // During shutdown we can just ignore this message.
   if (!webwidget_)
     return;
 
+  // Even if the browser provides an empty damage rect, it's still expecting to
+  // receive a repaint ack so just damage the entire widget bounds.
+  if (size_to_paint.IsEmpty()) {
+    size_to_paint = size_;
+  }
+
   set_next_paint_is_repaint_ack();
-  if (is_accelerated_compositing_active_) {
-    if (compositor_)
-      compositor_->setNeedsRedraw();
-    scheduleComposite();
+  if (is_accelerated_compositing_active_ && compositor_) {
+    compositor_->SetNeedsRedrawRect(gfx::Rect(size_to_paint));
   } else {
     gfx::Rect repaint_rect(size_to_paint.width(), size_to_paint.height());
     didInvalidateRect(repaint_rect);
   }
 }
 
-void RenderWidget::OnSmoothScrollCompleted(int gesture_id) {
-  PendingSmoothScrollGestureMap::iterator it =
-      pending_smooth_scroll_gestures_.find(gesture_id);
-  DCHECK(it != pending_smooth_scroll_gestures_.end());
-  it->second.Run();
-  pending_smooth_scroll_gestures_.erase(it);
+void RenderWidget::OnSmoothScrollCompleted() {
+  pending_smooth_scroll_gesture_.Run();
 }
 
 void RenderWidget::OnSetTextDirection(WebTextDirection direction) {
@@ -2249,10 +2278,6 @@
       software_stats_.total_paint_time;
   stats.rendering_stats.total_pixels_painted +=
       software_stats_.total_pixels_painted;
-  stats.rendering_stats.total_rasterize_time +=
-      software_stats_.total_rasterize_time;
-  stats.rendering_stats.total_pixels_rasterized +=
-      software_stats_.total_pixels_rasterized;
 }
 
 bool RenderWidget::GetGpuRenderingStats(GpuRenderingStats* stats) const {
@@ -2263,6 +2288,10 @@
   return gpu_channel->CollectRenderingStatsForSurface(surface_id(), stats);
 }
 
+RenderWidgetCompositor* RenderWidget::compositor() const {
+  return compositor_.get();
+}
+
 void RenderWidget::BeginSmoothScroll(
     bool down,
     const SmoothScrollCompletionCallback& callback,
@@ -2270,7 +2299,6 @@
     int mouse_event_x,
     int mouse_event_y) {
   DCHECK(!callback.is_null());
-  int id = next_smooth_scroll_gesture_id_++;
 
   ViewHostMsg_BeginSmoothScroll_Params params;
   params.scroll_down = down;
@@ -2278,8 +2306,8 @@
   params.mouse_event_x = mouse_event_x;
   params.mouse_event_y = mouse_event_y;
 
-  Send(new ViewHostMsg_BeginSmoothScroll(routing_id_, id, params));
-  pending_smooth_scroll_gestures_.insert(std::make_pair(id, callback));
+  Send(new ViewHostMsg_BeginSmoothScroll(routing_id_, params));
+  pending_smooth_scroll_gesture_ = callback;
 }
 
 bool RenderWidget::WillHandleMouseEvent(const WebKit::WebMouseEvent& event) {
@@ -2291,12 +2319,16 @@
   return false;
 }
 
+void RenderWidget::hasTouchEventHandlers(bool has_handlers) {
+  Send(new ViewHostMsg_HasTouchEventHandlers(routing_id_, has_handlers));
+}
+
 bool RenderWidget::HasTouchEventHandlersAt(const gfx::Point& point) const {
   return true;
 }
 
-WebGraphicsContext3D* RenderWidget::CreateGraphicsContext3D(
-    const WebGraphicsContext3D::Attributes& attributes) {
+WebGraphicsContext3DCommandBufferImpl* RenderWidget::CreateGraphicsContext3D(
+    const WebKit::WebGraphicsContext3D::Attributes& attributes) {
   if (!webwidget_)
     return NULL;
   scoped_ptr<WebGraphicsContext3DCommandBufferImpl> context(
diff --git a/content/renderer/render_widget.h b/content/renderer/render_widget.h
index cb06e66..cf9f8fa 100644
--- a/content/renderer/render_widget.h
+++ b/content/renderer/render_widget.h
@@ -171,6 +171,8 @@
   // This call is relatively expensive as it blocks on the GPU process
   bool GetGpuRenderingStats(GpuRenderingStats*) const;
 
+  RenderWidgetCompositor* compositor() const;
+
   virtual scoped_ptr<cc::OutputSurface> CreateOutputSurface();
 
   // Callback for use with BeginSmoothScroll.
@@ -207,6 +209,7 @@
   virtual void InstrumentWillComposite() {}
 
   virtual bool AllowPartialSwap() const;
+  bool SynchronouslyDisableVSync() const;
 
  protected:
   // Friend RefCounted so that the dtor can be non-public. Using this class
@@ -277,6 +280,11 @@
               ResizeAck resize_ack);
 
   // RenderWidget IPC message handlers
+  void OnHandleInputEvent(const WebKit::WebInputEvent* event,
+                          bool keyboard_shortcut);
+  void OnCursorVisibilityChange(bool is_visible);
+  void OnMouseCaptureLost();
+  virtual void OnSetFocus(bool enable);
   void OnClose();
   void OnCreatingNewAck();
   virtual void OnResize(const gfx::Size& new_size,
@@ -292,10 +300,6 @@
   void OnCreateVideoAck(int32 video_id);
   void OnUpdateVideoAck(int32 video_id);
   void OnRequestMoveAck();
-  void OnHandleInputEvent(const WebKit::WebInputEvent* event,
-                          bool keyboard_shortcut);
-  void OnMouseCaptureLost();
-  virtual void OnSetFocus(bool enable);
   void OnSetInputMethodActive(bool is_active);
   virtual void OnImeSetComposition(
       const string16& text,
@@ -308,8 +312,8 @@
                      int tag,
                      const gfx::Size& page_size,
                      const gfx::Size& desired_size);
-  void OnRepaint(const gfx::Size& size_to_paint);
-  void OnSmoothScrollCompleted(int gesture_id);
+  void OnRepaint(gfx::Size size_to_paint);
+  void OnSmoothScrollCompleted();
   void OnSetTextDirection(WebKit::WebTextDirection direction);
   void OnGetFPS();
   void OnScreenInfoChanged(const WebKit::WebScreenInfo& screen_info);
@@ -477,8 +481,11 @@
   // at the given point.
   virtual bool HasTouchEventHandlersAt(const gfx::Point& point) const;
 
+  // Check whether the WebWidget has any touch event handlers registered.
+  virtual void hasTouchEventHandlers(bool has_handlers);
+
   // Creates a 3D context associated with this view.
-  WebKit::WebGraphicsContext3D* CreateGraphicsContext3D(
+  WebGraphicsContext3DCommandBufferImpl* CreateGraphicsContext3D(
       const WebKit::WebGraphicsContext3D::Attributes& attributes);
 
   bool OnSnapshotHelper(const gfx::Rect& src_subrect, SkBitmap* bitmap);
@@ -680,10 +687,7 @@
   bool throttle_input_events_;
 
   // State associated with the BeginSmoothScroll synthetic scrolling function.
-  int next_smooth_scroll_gesture_id_;
-  typedef std::map<int, SmoothScrollCompletionCallback>
-      PendingSmoothScrollGestureMap;
-  PendingSmoothScrollGestureMap pending_smooth_scroll_gestures_;
+  SmoothScrollCompletionCallback pending_smooth_scroll_gesture_;
 
   // Specified whether the compositor will run in its own thread.
   bool is_threaded_compositing_enabled_;
diff --git a/content/renderer/render_widget_fullscreen_pepper.cc b/content/renderer/render_widget_fullscreen_pepper.cc
index b1eeecd..12b8b08 100644
--- a/content/renderer/render_widget_fullscreen_pepper.cc
+++ b/content/renderer/render_widget_fullscreen_pepper.cc
@@ -368,7 +368,7 @@
       plugin_(plugin),
       layer_(NULL),
       mouse_lock_dispatcher_(new FullscreenMouseLockDispatcher(
-          ALLOW_THIS_IN_INITIALIZER_LIST(this))) {
+          this)) {
 }
 
 RenderWidgetFullscreenPepper::~RenderWidgetFullscreenPepper() {
diff --git a/content/renderer/renderer_clipboard_client.cc b/content/renderer/renderer_clipboard_client.cc
index 57ddfac..b21db02 100644
--- a/content/renderer/renderer_clipboard_client.cc
+++ b/content/renderer/renderer_clipboard_client.cc
@@ -47,14 +47,14 @@
     const void* pixels,
     const gfx::Size& size) {
   // Do not try to write a bitmap more than once
-  if (shared_buf_.get())
+  if (shared_buf_)
     return;
 
   uint32 buf_size = 4 * size.width() * size.height();
 
   // Allocate a shared memory buffer to hold the bitmap bits.
   shared_buf_.reset(ChildThread::current()->AllocateSharedMemory(buf_size));
-  if (!shared_buf_.get())
+  if (!shared_buf_)
     return;
 
   // Copy the bits into shared memory
@@ -80,7 +80,7 @@
 // Flushes the objects to the clipboard with an IPC.
 void RendererClipboardWriteContext::Flush(
     const ui::Clipboard::ObjectMap& objects) {
-  if (shared_buf_.get()) {
+  if (shared_buf_) {
     RenderThreadImpl::current()->Send(
         new ClipboardHostMsg_WriteObjectsSync(objects, shared_buf_->handle()));
   } else {
diff --git a/content/renderer/renderer_main.cc b/content/renderer/renderer_main.cc
index 7cfd127..cc8e584 100644
--- a/content/renderer/renderer_main.cc
+++ b/content/renderer/renderer_main.cc
@@ -17,9 +17,9 @@
 #include "base/metrics/stats_counters.h"
 #include "base/path_service.h"
 #include "base/pending_task.h"
+#include "base/power_monitor/power_monitor.h"
 #include "base/process_util.h"
 #include "base/string_util.h"
-#include "base/system_monitor/system_monitor.h"
 #include "base/threading/platform_thread.h"
 #include "base/time.h"
 #include "content/common/pepper_plugin_registry.h"
@@ -30,6 +30,7 @@
 #include "content/renderer/render_process_impl.h"
 #include "content/renderer/render_thread_impl.h"
 #include "content/renderer/renderer_main_platform_delegate.h"
+#include "third_party/libjingle/overrides/init_webrtc.h"
 #include "ui/base/ui_base_switches.h"
 #include "webkit/glue/webkit_glue.h"
 #include "webkit/plugins/ppapi/ppapi_interface_factory.h"
@@ -63,7 +64,7 @@
 
 // This is a simplified version of the browser Jankometer, which measures
 // the processing time of tasks on the render thread.
-class RendererMessageLoopObserver : public MessageLoop::TaskObserver {
+class RendererMessageLoopObserver : public base::MessageLoop::TaskObserver {
  public:
   RendererMessageLoopObserver()
       : process_times_(base::Histogram::FactoryGet(
@@ -87,7 +88,7 @@
 };
 
 // For measuring memory usage after each task. Behind a command line flag.
-class MemoryObserver : public MessageLoop::TaskObserver {
+class MemoryObserver : public base::MessageLoop::TaskObserver {
  public:
   MemoryObserver() {}
   virtual ~MemoryObserver() {}
@@ -144,12 +145,13 @@
 #if defined(OS_MACOSX)
   // As long as we use Cocoa in the renderer (for the forseeable future as of
   // now; see http://crbug.com/13890 for info) we need to have a UI loop.
-  MessageLoop main_message_loop(MessageLoop::TYPE_UI);
+  base::MessageLoop main_message_loop(base::MessageLoop::TYPE_UI);
 #else
   // The main message loop of the renderer services doesn't have IO or UI tasks,
   // unless in-process-plugins is used.
-  MessageLoop main_message_loop(RenderProcessImpl::InProcessPlugins() ?
-              MessageLoop::TYPE_UI : MessageLoop::TYPE_DEFAULT);
+  base::MessageLoop main_message_loop(RenderProcessImpl::InProcessPlugins()
+                                          ? base::MessageLoop::TYPE_UI
+                                          : base::MessageLoop::TYPE_DEFAULT);
 #endif
   main_message_loop.AddTaskObserver(&task_observer);
 
@@ -161,7 +163,7 @@
 
   base::PlatformThread::SetName("CrRendererMain");
 
-  base::SystemMonitor system_monitor;
+  base::PowerMonitor power_monitor;
   HighResolutionTimerManager hi_res_timer_manager;
 
   platform.PlatformInitialize();
@@ -188,6 +190,13 @@
   // Load pepper plugins before engaging the sandbox.
   PepperPluginRegistry::GetInstance();
 #endif
+#if defined(ENABLE_WEBRTC)
+  // Initialize WebRTC before engaging the sandbox.
+  // NOTE: On linux, this call could already have been made from
+  // zygote_main_linux.cc.  However, calling multiple times from the same thread
+  // is OK.
+  InitializeWebRtcModule();
+#endif
 
   {
 #if defined(OS_WIN) || defined(OS_MACOSX)
@@ -223,7 +232,7 @@
         pool->Recycle();
 #endif
       TRACE_EVENT_BEGIN_ETW("RendererMain.START_MSG_LOOP", 0, 0);
-      MessageLoop::current()->Run();
+      base::MessageLoop::current()->Run();
       TRACE_EVENT_END_ETW("RendererMain.START_MSG_LOOP", 0, 0);
     }
   }
diff --git a/content/renderer/renderer_main_platform_delegate_linux.cc b/content/renderer/renderer_main_platform_delegate_linux.cc
index a653bfe..dd8281d 100644
--- a/content/renderer/renderer_main_platform_delegate_linux.cc
+++ b/content/renderer/renderer_main_platform_delegate_linux.cc
@@ -40,9 +40,8 @@
   // The setuid sandbox is started in the zygote process: zygote_main_linux.cc
   // http://code.google.com/p/chromium/wiki/LinuxSUIDSandbox
   //
-  // The seccomp sandbox mode 1 (sandbox/linux/seccomp-legacy) and mode 2
-  // (sandbox/linux/seccomp-bpf) are started in InitializeSandbox().
-  InitializeSandbox();
+  // Anything else is started in InitializeSandbox().
+  LinuxSandbox::InitializeSandbox();
   return true;
 }
 
diff --git a/content/renderer/renderer_main_platform_delegate_mac.mm b/content/renderer/renderer_main_platform_delegate_mac.mm
index 42f8abc..c128cf0 100644
--- a/content/renderer/renderer_main_platform_delegate_mac.mm
+++ b/content/renderer/renderer_main_platform_delegate_mac.mm
@@ -13,7 +13,7 @@
 #import "base/mac/foundation_util.h"
 #import "base/mac/mac_util.h"
 #include "base/mac/scoped_cftyperef.h"
-#include "base/sys_string_conversions.h"
+#include "base/strings/sys_string_conversions.h"
 #include "content/common/sandbox_mac.h"
 #include "content/public/common/content_switches.h"
 #import "content/public/common/injection_test_mac.h"
diff --git a/content/renderer/renderer_main_platform_delegate_win.cc b/content/renderer/renderer_main_platform_delegate_win.cc
index 8732ac8..1af746d 100644
--- a/content/renderer/renderer_main_platform_delegate_win.cc
+++ b/content/renderer/renderer_main_platform_delegate_win.cc
@@ -47,6 +47,15 @@
   base::win::SetAbortBehaviorForCrashReporting();
 }
 
+#if !defined(NDEBUG)
+LRESULT CALLBACK WindowsHookCBT(int code, WPARAM w_param, LPARAM l_param) {
+  CHECK_NE(code, HCBT_CREATEWND)
+      << "Should not be creating windows in the renderer!";
+  return CallNextHookEx(NULL, code, w_param, l_param);
+}
+#endif  // !NDEBUG
+
+
 }  // namespace
 
 RendererMainPlatformDelegate::RendererMainPlatformDelegate(
@@ -59,6 +68,15 @@
 }
 
 void RendererMainPlatformDelegate::PlatformInitialize() {
+#if !defined(NDEBUG)
+  // Install a check that we're not creating windows in the renderer. See
+  // http://crbug.com/230122 for background. TODO(scottmg): Ideally this would
+  // check all threads in the renderer, but it currently only checks the main
+  // thread.
+  PCHECK(
+      SetWindowsHookEx(WH_CBT, WindowsHookCBT, NULL, ::GetCurrentThreadId()));
+#endif  // !NDEBUG
+
   InitExitInterceptions();
 
   // Be mindful of what resources you acquire here. They can be used by
diff --git a/content/renderer/renderer_webapplicationcachehost_impl.cc b/content/renderer/renderer_webapplicationcachehost_impl.cc
index 78418ff..6404053 100644
--- a/content/renderer/renderer_webapplicationcachehost_impl.cc
+++ b/content/renderer/renderer_webapplicationcachehost_impl.cc
@@ -58,8 +58,7 @@
 }
 
 RenderViewImpl* RendererWebApplicationCacheHostImpl::GetRenderView() {
-  return static_cast<RenderViewImpl*>
-      (RenderThreadImpl::current()->ResolveRoute(routing_id_));
+  return RenderViewImpl::FromRoutingID(routing_id_);
 }
 
 // static
diff --git a/content/renderer/renderer_webkitplatformsupport_impl.cc b/content/renderer/renderer_webkitplatformsupport_impl.cc
index 33f9707..f21400e 100644
--- a/content/renderer/renderer_webkitplatformsupport_impl.cc
+++ b/content/renderer/renderer_webkitplatformsupport_impl.cc
@@ -54,7 +54,6 @@
 #include "webkit/glue/webclipboard_impl.h"
 #include "webkit/glue/webfileutilities_impl.h"
 #include "webkit/glue/webkit_glue.h"
-#include "webkit/gpu/webgraphicscontext3d_in_process_impl.h"
 
 #if defined(OS_WIN)
 #include "content/common/child_process_messages.h"
@@ -229,7 +228,7 @@
 
 WebKit::WebFileUtilities*
 RendererWebKitPlatformSupportImpl::fileUtilities() {
-  if (!file_utilities_.get()) {
+  if (!file_utilities_) {
     file_utilities_.reset(new FileUtilities(thread_safe_sender_));
     file_utilities_->set_sandbox_enabled(sandboxEnabled());
   }
@@ -358,7 +357,7 @@
 //------------------------------------------------------------------------------
 
 WebIDBFactory* RendererWebKitPlatformSupportImpl::idbFactory() {
-  if (!web_idb_factory_.get()) {
+  if (!web_idb_factory_) {
     if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess))
       web_idb_factory_.reset(WebIDBFactory::create());
     else
@@ -370,7 +369,7 @@
 //------------------------------------------------------------------------------
 
 WebFileSystem* RendererWebKitPlatformSupportImpl::fileSystem() {
-  if (!web_file_system_.get())
+  if (!web_file_system_)
     web_file_system_.reset(new WebFileSystemImpl());
   return web_file_system_.get();
 }
@@ -471,9 +470,9 @@
 
   // Create a hyphenator object and attach it to the render thread so it can
   // receive a dictionary file opened by a browser.
-  if (!hyphenator_.get()) {
+  if (!hyphenator_) {
     hyphenator_.reset(new content::Hyphenator(base::kInvalidPlatformFileValue));
-    if (!hyphenator_.get())
+    if (!hyphenator_)
       return false;
     return hyphenator_->Attach(RenderThreadImpl::current(), locale);
   }
@@ -633,23 +632,7 @@
 
 double RendererWebKitPlatformSupportImpl::audioHardwareSampleRate() {
   RenderThreadImpl* thread = RenderThreadImpl::current();
-  int sample_rate = thread->GetAudioHardwareConfig()->GetOutputSampleRate();
-
-  // In some rare cases it has been found that Windows returns
-  // a sample-rate of 0.
-  // Let's make sure to return a sane fallback sample-rate.
-  // http://crbug.com/222718
-  static const int kMinSampleRate = 22050;
-  static const int kMaxSampleRate = 192000;
-#if defined(OS_MACOSX)
-  static const int kFallbackSampleRate = 44100;
-#else
-  static const int kFallbackSampleRate = 48000;
-#endif
-  if (sample_rate < kMinSampleRate || sample_rate > kMaxSampleRate)
-    sample_rate = kFallbackSampleRate;
-
-  return sample_rate;
+  return thread->GetAudioHardwareConfig()->GetOutputSampleRate();
 }
 
 size_t RendererWebKitPlatformSupportImpl::audioHardwareBufferSize() {
@@ -776,7 +759,7 @@
 
 WebBlobRegistry* RendererWebKitPlatformSupportImpl::blobRegistry() {
   // thread_safe_sender_ can be NULL when running some tests.
-  if (!blob_registry_.get() && thread_safe_sender_.get())
+  if (!blob_registry_.get() && thread_safe_sender_)
     blob_registry_.reset(new WebBlobRegistryImpl(thread_safe_sender_));
   return blob_registry_.get();
 }
@@ -785,7 +768,7 @@
 
 void RendererWebKitPlatformSupportImpl::sampleGamepads(WebGamepads& gamepads) {
   if (g_test_gamepads == 0) {
-    if (!gamepad_shared_memory_reader_.get())
+    if (!gamepad_shared_memory_reader_)
       gamepad_shared_memory_reader_.reset(new GamepadSharedMemoryReader);
     gamepad_shared_memory_reader_->SampleGamepads(gamepads);
   } else {
@@ -872,6 +855,14 @@
 
 //------------------------------------------------------------------------------
 
+WebKit::WebSpeechSynthesizer*
+RendererWebKitPlatformSupportImpl::createSpeechSynthesizer(
+    WebKit::WebSpeechSynthesizerClient* client) {
+  return GetContentClient()->renderer()->OverrideSpeechSynthesizer(client);
+}
+
+//------------------------------------------------------------------------------
+
 bool RendererWebKitPlatformSupportImpl::processMemorySizesInBytes(
     size_t* private_bytes, size_t* shared_bytes) {
   content::RenderThread::Get()->Send(
diff --git a/content/renderer/renderer_webkitplatformsupport_impl.h b/content/renderer/renderer_webkitplatformsupport_impl.h
index de19386..3a89860 100644
--- a/content/renderer/renderer_webkitplatformsupport_impl.h
+++ b/content/renderer/renderer_webkitplatformsupport_impl.h
@@ -11,7 +11,7 @@
 #include "content/common/content_export.h"
 #include "content/common/webkitplatformsupport_impl.h"
 #include "third_party/WebKit/Source/Platform/chromium/public/WebGraphicsContext3D.h"
-#include "third_party/WebKit/Source/WebKit/chromium/public/WebIDBFactory.h"
+#include "third_party/WebKit/Source/Platform/chromium/public/WebIDBFactory.h"
 #include "third_party/WebKit/Source/WebKit/chromium/public/WebSharedWorkerRepository.h"
 
 namespace cc {
@@ -46,6 +46,8 @@
   virtual WebKit::WebCookieJar* cookieJar();
   virtual WebKit::WebHyphenator* hyphenator();
   virtual WebKit::WebThemeEngine* themeEngine();
+  virtual WebKit::WebSpeechSynthesizer* createSpeechSynthesizer(
+      WebKit::WebSpeechSynthesizerClient* client);
   virtual bool sandboxEnabled();
   virtual unsigned long long visitedLinkHash(
       const char* canonicalURL, size_t length);
diff --git a/content/renderer/resource_fetcher_browsertest.cc b/content/renderer/resource_fetcher_browsertest.cc
new file mode 100644
index 0000000..e7e0c36
--- /dev/null
+++ b/content/renderer/resource_fetcher_browsertest.cc
@@ -0,0 +1,284 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "webkit/glue/resource_fetcher.h"
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/command_line.h"
+#include "base/message_loop.h"
+#include "base/timer.h"
+#include "content/public/common/content_switches.h"
+#include "content/public/renderer/render_view.h"
+#include "content/public/test/test_utils.h"
+#include "content/shell/shell.h"
+#include "content/test/content_browser_test.h"
+#include "content/test/content_browser_test_utils.h"
+#include "third_party/WebKit/Source/Platform/chromium/public/WebURLResponse.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::WebURLRequest;
+using WebKit::WebURLResponse;
+using webkit_glue::ResourceFetcher;
+using webkit_glue::ResourceFetcherWithTimeout;
+
+namespace content {
+
+static const int kMaxWaitTimeMs = 5000;
+
+class FetcherDelegate {
+ public:
+  FetcherDelegate()
+      : 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;
+    StartTimer();
+  }
+
+  virtual ~FetcherDelegate() {}
+
+  ResourceFetcher::Callback NewCallback() {
+    return base::Bind(&FetcherDelegate::OnURLFetchComplete,
+                      base::Unretained(this));
+  }
+
+  virtual void OnURLFetchComplete(const WebURLResponse& response,
+                                  const std::string& data) {
+    response_ = response;
+    data_ = data;
+    completed_ = true;
+    timer_.Stop();
+    if (!timed_out_)
+      quit_task_.Run();
+  }
+
+  bool completed() const { return completed_; }
+  bool timed_out() const { return timed_out_; }
+
+  std::string data() const { return data_; }
+  const WebURLResponse& response() const { return response_; }
+
+  // Wait for the request to complete or timeout.
+  void WaitForResponse() {
+    scoped_refptr<MessageLoopRunner> runner = new MessageLoopRunner;
+    quit_task_ = runner->QuitClosure();
+    runner->Run();
+  }
+
+  void StartTimer() {
+    timer_.Start(FROM_HERE,
+                 base::TimeDelta::FromMilliseconds(kMaxWaitTimeMs),
+                 this,
+                 &FetcherDelegate::TimerFired);
+  }
+
+  void TimerFired() {
+    ASSERT_FALSE(completed_);
+
+    timed_out_ = true;
+    if (!completed_)
+      quit_task_.Run();
+    FAIL() << "fetch timed out";
+  }
+
+  static FetcherDelegate* instance_;
+
+ private:
+  base::OneShotTimer<FetcherDelegate> timer_;
+  bool completed_;
+  bool timed_out_;
+  WebURLResponse response_;
+  std::string data_;
+  base::Closure quit_task_;
+};
+
+FetcherDelegate* FetcherDelegate::instance_ = NULL;
+
+class EvilFetcherDelegate : public FetcherDelegate {
+ public:
+  virtual ~EvilFetcherDelegate() {}
+
+  void SetFetcher(ResourceFetcher* fetcher) {
+    fetcher_.reset(fetcher);
+  }
+
+  virtual void OnURLFetchComplete(const WebURLResponse& response,
+                                  const std::string& data) OVERRIDE {
+    // 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_;
+};
+
+class ResourceFetcherTests : public ContentBrowserTest {
+ public:
+  virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
+    command_line->AppendSwitch(switches::kSingleProcess);
+#if defined(OS_WIN) && defined(USE_AURA)
+    // Don't want to try to create a GPU process.
+    command_line->AppendSwitch(switches::kDisableAcceleratedCompositing);
+#endif
+  }
+
+  RenderView* GetRenderView() {
+    // We could have the test on the UI thread get the WebContent's routing ID,
+    // but we know this will be the first RV so skip that and just hardcode it.
+    return RenderView::FromRoutingID(1);
+  }
+
+  void ResourceFetcherDownloadOnRenderer(const GURL& url) {
+    WebFrame* frame = GetRenderView()->GetWebView()->mainFrame();
+
+    scoped_ptr<FetcherDelegate> delegate(new FetcherDelegate);
+    scoped_ptr<ResourceFetcher> fetcher(new ResourceFetcher(
+        url, frame, WebURLRequest::TargetIsMainFrame, delegate->NewCallback()));
+
+    delegate->WaitForResponse();
+
+    ASSERT_TRUE(delegate->completed());
+    EXPECT_EQ(delegate->response().httpStatusCode(), 200);
+    std::string text = delegate->data();
+    EXPECT_TRUE(text.find("Basic html test.") != std::string::npos);
+  }
+
+  void ResourceFetcher404OnRenderer(const GURL& url) {
+    WebFrame* frame = GetRenderView()->GetWebView()->mainFrame();
+
+    scoped_ptr<FetcherDelegate> delegate(new FetcherDelegate);
+    scoped_ptr<ResourceFetcher> fetcher(new ResourceFetcher(
+        url, frame, WebURLRequest::TargetIsMainFrame, delegate->NewCallback()));
+
+    delegate->WaitForResponse();
+
+    ASSERT_TRUE(delegate->completed());
+    EXPECT_EQ(delegate->response().httpStatusCode(), 404);
+    EXPECT_TRUE(delegate->data().find("Not Found.") != std::string::npos);
+  }
+
+  void ResourceFetcherDidFailOnRenderer() {
+    WebFrame* frame = GetRenderView()->GetWebView()->mainFrame();
+
+    // Try to fetch a page on a site that doesn't exist.
+    GURL url("http://localhost:1339/doesnotexist");
+    scoped_ptr<FetcherDelegate> delegate(new FetcherDelegate);
+    scoped_ptr<ResourceFetcher> fetcher(new ResourceFetcher(
+        url, frame, WebURLRequest::TargetIsMainFrame, delegate->NewCallback()));
+
+    delegate->WaitForResponse();
+
+    // When we fail, we still call the Delegate callback but we pass in empty
+    // values.
+    EXPECT_TRUE(delegate->completed());
+    EXPECT_TRUE(delegate->response().isNull());
+    EXPECT_EQ(delegate->data(), std::string());
+    EXPECT_FALSE(delegate->timed_out());
+  }
+
+  void ResourceFetcherTimeoutOnRenderer(const GURL& url) {
+    WebFrame* frame = GetRenderView()->GetWebView()->mainFrame();
+
+    scoped_ptr<FetcherDelegate> delegate(new FetcherDelegate);
+    scoped_ptr<ResourceFetcher> fetcher(new ResourceFetcherWithTimeout(
+        url, frame, WebURLRequest::TargetIsMainFrame,
+        0, delegate->NewCallback()));
+
+    delegate->WaitForResponse();
+
+    // When we timeout, we still call the Delegate callback but we pass in empty
+    // values.
+    EXPECT_TRUE(delegate->completed());
+    EXPECT_TRUE(delegate->response().isNull());
+    EXPECT_EQ(delegate->data(), std::string());
+    EXPECT_FALSE(delegate->timed_out());
+  }
+
+  void ResourceFetcherDeletedInCallbackOnRenderer(const GURL& url) {
+    WebFrame* frame = GetRenderView()->GetWebView()->mainFrame();
+
+    scoped_ptr<EvilFetcherDelegate> delegate(new EvilFetcherDelegate);
+    scoped_ptr<ResourceFetcher> fetcher(new ResourceFetcherWithTimeout(
+        url, frame, WebURLRequest::TargetIsMainFrame,
+        0, delegate->NewCallback()));
+    delegate->SetFetcher(fetcher.release());
+
+    delegate->WaitForResponse();
+    EXPECT_FALSE(delegate->timed_out());
+  }
+};
+
+// Test a fetch from the test server.
+// If this flakes, use http://crbug.com/51622.
+IN_PROC_BROWSER_TEST_F(ResourceFetcherTests, ResourceFetcherDownload) {
+  // Need to spin up the renderer.
+  NavigateToURL(shell(), GURL("about:blank"));
+
+  ASSERT_TRUE(test_server()->Start());
+  GURL url(test_server()->GetURL("files/simple_page.html"));
+
+  PostTaskToInProcessRendererAndWait(
+        base::Bind(&ResourceFetcherTests::ResourceFetcherDownloadOnRenderer,
+                   base::Unretained(this), url));
+}
+
+IN_PROC_BROWSER_TEST_F(ResourceFetcherTests, ResourceFetcher404) {
+  // Need to spin up the renderer.
+  NavigateToURL(shell(), GURL("about:blank"));
+
+  // Test 404 response.
+  ASSERT_TRUE(test_server()->Start());
+  GURL url = test_server()->GetURL("files/thisfiledoesntexist.html");
+
+  PostTaskToInProcessRendererAndWait(
+        base::Bind(&ResourceFetcherTests::ResourceFetcher404OnRenderer,
+                   base::Unretained(this), url));
+}
+
+// If this flakes, use http://crbug.com/51622.
+IN_PROC_BROWSER_TEST_F(ResourceFetcherTests, ResourceFetcherDidFail) {
+  // Need to spin up the renderer.
+  NavigateToURL(shell(), GURL("about:blank"));
+
+  PostTaskToInProcessRendererAndWait(
+        base::Bind(&ResourceFetcherTests::ResourceFetcherDidFailOnRenderer,
+                   base::Unretained(this)));
+}
+
+IN_PROC_BROWSER_TEST_F(ResourceFetcherTests, ResourceFetcherTimeout) {
+  // Need to spin up the renderer.
+  NavigateToURL(shell(), GURL("about:blank"));
+
+  // Grab a page that takes at least 1 sec to respond, but set the fetcher to
+  // timeout in 0 sec.
+  ASSERT_TRUE(test_server()->Start());
+  GURL url(test_server()->GetURL("slow?1"));
+
+  PostTaskToInProcessRendererAndWait(
+        base::Bind(&ResourceFetcherTests::ResourceFetcherTimeoutOnRenderer,
+                   base::Unretained(this), url));
+}
+
+IN_PROC_BROWSER_TEST_F(ResourceFetcherTests, ResourceFetcherDeletedInCallback) {
+  // Need to spin up the renderer.
+  NavigateToURL(shell(), GURL("about:blank"));
+
+  // Grab a page that takes at least 1 sec to respond, but set the fetcher to
+  // timeout in 0 sec.
+  ASSERT_TRUE(test_server()->Start());
+  GURL url(test_server()->GetURL("slow?1"));
+
+  PostTaskToInProcessRendererAndWait(
+        base::Bind(
+            &ResourceFetcherTests::ResourceFetcherDeletedInCallbackOnRenderer,
+            base::Unretained(this), url));
+}
+
+}  // namespace content
diff --git a/content/renderer/v8_value_converter_impl.cc b/content/renderer/v8_value_converter_impl.cc
index b1a063c..e8b2563 100644
--- a/content/renderer/v8_value_converter_impl.cc
+++ b/content/renderer/v8_value_converter_impl.cc
@@ -263,12 +263,12 @@
   scoped_ptr<WebKit::WebArrayBuffer> array_buffer(
       WebKit::WebArrayBuffer::createFromV8Value(val));
   scoped_ptr<WebKit::WebArrayBufferView> view;
-  if (array_buffer.get()) {
+  if (array_buffer) {
     data = reinterpret_cast<char*>(array_buffer->data());
     length = array_buffer->byteLength();
   } else {
     view.reset(WebKit::WebArrayBufferView::createFromV8Value(val));
-    if (view.get()) {
+    if (view) {
       data = reinterpret_cast<char*>(view->baseAddress()) + view->byteOffset();
       length = view->byteLength();
     }
@@ -322,7 +322,7 @@
     }
 
     scoped_ptr<base::Value> child(FromV8ValueImpl(child_v8, unique_map));
-    if (!child.get())
+    if (!child)
       // JSON.stringify skips properties whose values don't serialize, for
       // example undefined and functions. Emulate that behavior.
       continue;
diff --git a/content/renderer/v8_value_converter_impl_unittest.cc b/content/renderer/v8_value_converter_impl_unittest.cc
index df68e80..8a6a757 100644
--- a/content/renderer/v8_value_converter_impl_unittest.cc
+++ b/content/renderer/v8_value_converter_impl_unittest.cc
@@ -70,7 +70,7 @@
     std::string temp;
     if (!value->GetString(key, &temp)) {
       ADD_FAILURE();
-      return "";
+      return std::string();
     }
     return temp;
   }
@@ -80,7 +80,7 @@
         value->Get(v8::String::New(key.c_str())).As<v8::String>();
     if (temp.IsEmpty()) {
       ADD_FAILURE();
-      return "";
+      return std::string();
     }
     v8::String::Utf8Value utf8(temp);
     return std::string(*utf8, utf8.length());
@@ -90,7 +90,7 @@
     std::string temp;
     if (!value->GetString(static_cast<size_t>(index), &temp)) {
       ADD_FAILURE();
-      return "";
+      return std::string();
     }
     return temp;
   }
@@ -99,7 +99,7 @@
     v8::Handle<v8::String> temp = value->Get(index).As<v8::String>();
     if (temp.IsEmpty()) {
       ADD_FAILURE();
-      return "";
+      return std::string();
     }
     v8::String::Utf8Value utf8(temp);
     return std::string(*utf8, utf8.length());
@@ -147,7 +147,7 @@
                      scoped_ptr<base::Value> expected_value) {
     scoped_ptr<base::Value> raw(converter.FromV8Value(val, context_));
 
-    if (expected_value.get()) {
+    if (expected_value) {
       ASSERT_TRUE(raw.get());
       EXPECT_TRUE(expected_value->Equals(raw.get()));
       EXPECT_EQ(expected_type, raw->GetType());
@@ -162,7 +162,7 @@
             converter.FromV8Value(object, context_)));
     ASSERT_TRUE(dictionary.get());
 
-    if (expected_value.get()) {
+    if (expected_value) {
       base::Value* temp = NULL;
       ASSERT_TRUE(dictionary->Get("test", &temp));
       EXPECT_EQ(expected_type, temp->GetType());
@@ -176,7 +176,7 @@
     scoped_ptr<base::ListValue> list(
         static_cast<base::ListValue*>(converter.FromV8Value(array, context_)));
     ASSERT_TRUE(list.get());
-    if (expected_value.get()) {
+    if (expected_value) {
       base::Value* temp = NULL;
       ASSERT_TRUE(list->Get(0, &temp));
       EXPECT_EQ(expected_type, temp->GetType());
diff --git a/content/renderer/webplugin_delegate_proxy.cc b/content/renderer/webplugin_delegate_proxy.cc
index 1421d63..c3459ed 100644
--- a/content/renderer/webplugin_delegate_proxy.cc
+++ b/content/renderer/webplugin_delegate_proxy.cc
@@ -168,14 +168,14 @@
     DCHECK(channel_ != NULL);
     channel_->Send(new PluginMsg_DidFinishLoading(instance_id_, resource_id_));
     channel_ = NULL;
-    MessageLoop::current()->DeleteSoon(FROM_HERE, this);
+    base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
   }
 
   virtual void DidFail() OVERRIDE {
     DCHECK(channel_ != NULL);
     channel_->Send(new PluginMsg_DidFail(instance_id_, resource_id_));
     channel_ = NULL;
-    MessageLoop::current()->DeleteSoon(FROM_HERE, this);
+    base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
   }
 
   virtual bool IsMultiByteResponseExpected() OVERRIDE {
@@ -279,7 +279,7 @@
 
   plugin_ = NULL;
 
-  MessageLoop::current()->DeleteSoon(FROM_HERE, this);
+  base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
 }
 
 bool WebPluginDelegateProxy::Initialize(
@@ -333,7 +333,7 @@
     channel_host =
         PluginChannelHost::GetPluginChannelHost(
             channel_handle, ChildProcess::current()->io_message_loop_proxy());
-    if (!channel_host.get()) {
+    if (!channel_host) {
       LOG(ERROR) << "Couldn't get PluginChannelHost";
       continue;
     }
@@ -537,12 +537,12 @@
   if (bitmaps_changed)
 #endif
   {
-    if (transport_stores_[0].dib.get())
+    if (transport_stores_[0].dib)
       CopyTransportDIBHandleForMessage(transport_stores_[0].dib->handle(),
                                        &param.windowless_buffer0,
                                        channel_host_->peer_pid());
 
-    if (transport_stores_[1].dib.get())
+    if (transport_stores_[1].dib)
       CopyTransportDIBHandleForMessage(transport_stores_[1].dib->handle(),
                                        &param.windowless_buffer1,
                                        channel_host_->peer_pid());
diff --git a/content/result_codes_java.target.darwin-arm.mk b/content/result_codes_java.target.darwin-arm.mk
new file mode 100644
index 0000000..8c20ed9
--- /dev/null
+++ b/content/result_codes_java.target.darwin-arm.mk
@@ -0,0 +1,142 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := content_result_codes_java_gyp
+LOCAL_MODULE_STEM := result_codes_java
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+
+### Generated for rule "content_content_gyp_result_codes_java_target_generate_java_constants":
+# "{'inputs': ['../build/android/gyp/util/build_utils.py', '../build/android/gyp/gcc_preprocess.py', 'public/common/result_codes_list.h'], 'extension': 'template', 'outputs': ['$(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/%(INPUT_ROOT)s.java'], 'variables': {'output_path': '$(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/%(INPUT_ROOT)s.java'}, 'rule_name': 'generate_java_constants', 'rule_sources': ['public/android/java/src/org/chromium/content/common/ResultCodes.template'], 'action': ['python', '../build/android/gyp/gcc_preprocess.py', '--include-path=..', '--output=$(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/%(INPUT_ROOT)s.java', '--template=$(RULE_SOURCES)'], 'message': 'Generating Java from cpp template $(RULE_SOURCES)'}":
+$(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/ResultCodes.java: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/ResultCodes.java: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
+$(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/ResultCodes.java: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
+$(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/ResultCodes.java: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/ResultCodes.java: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/common/ResultCodes.template $(LOCAL_PATH)/build/android/gyp/util/build_utils.py $(LOCAL_PATH)/build/android/gyp/gcc_preprocess.py $(LOCAL_PATH)/content/public/common/result_codes_list.h $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/templates/org/chromium/content/common; cd $(gyp_local_path)/content; python ../build/android/gyp/gcc_preprocess.py "--include-path=.." "--output=$(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/ResultCodes.java" "--template=public/android/java/src/org/chromium/content/common/ResultCodes.template"
+
+.PHONY: content_result_codes_java_gyp_rule_trigger
+content_result_codes_java_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/ResultCodes.java
+
+### Finished generating for all rules
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/ResultCodes.java
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES := \
+	content_result_codes_java_gyp_rule_trigger
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-fno-tree-sra \
+	-fuse-ld=gold \
+	-Wno-psabi \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections
+
+MY_CFLAGS_C :=
+
+MY_DEFS := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DUSE_LINUX_BREAKPAD' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_GPU=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DENABLE_LANGUAGE_DETECTION=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+LOCAL_CFLAGS := $(MY_CFLAGS_C) $(MY_CFLAGS) $(MY_DEFS)
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES := \
+	$(GYP_ABS_ANDROID_TOP_DIR)/frameworks/wilhelm/include \
+	$(GYP_ABS_ANDROID_TOP_DIR)/bionic \
+	$(GYP_ABS_ANDROID_TOP_DIR)/external/stlport/stlport
+
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES)
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-abi \
+	-Wno-error=c++0x-compat \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_result_codes_java_gyp
+
+# Alias gyp target name.
+.PHONY: result_codes_java
+result_codes_java: content_result_codes_java_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/content/result_codes_java.target.darwin-x86.mk b/content/result_codes_java.target.darwin-x86.mk
new file mode 100644
index 0000000..305c6c3
--- /dev/null
+++ b/content/result_codes_java.target.darwin-x86.mk
@@ -0,0 +1,143 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := content_result_codes_java_gyp
+LOCAL_MODULE_STEM := result_codes_java
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+
+### Generated for rule "content_content_gyp_result_codes_java_target_generate_java_constants":
+# "{'inputs': ['../build/android/gyp/util/build_utils.py', '../build/android/gyp/gcc_preprocess.py', 'public/common/result_codes_list.h'], 'extension': 'template', 'outputs': ['$(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/%(INPUT_ROOT)s.java'], 'variables': {'output_path': '$(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/%(INPUT_ROOT)s.java'}, 'rule_name': 'generate_java_constants', 'rule_sources': ['public/android/java/src/org/chromium/content/common/ResultCodes.template'], 'action': ['python', '../build/android/gyp/gcc_preprocess.py', '--include-path=..', '--output=$(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/%(INPUT_ROOT)s.java', '--template=$(RULE_SOURCES)'], 'message': 'Generating Java from cpp template $(RULE_SOURCES)'}":
+$(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/ResultCodes.java: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/ResultCodes.java: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
+$(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/ResultCodes.java: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
+$(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/ResultCodes.java: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/ResultCodes.java: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/common/ResultCodes.template $(LOCAL_PATH)/build/android/gyp/util/build_utils.py $(LOCAL_PATH)/build/android/gyp/gcc_preprocess.py $(LOCAL_PATH)/content/public/common/result_codes_list.h $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/templates/org/chromium/content/common; cd $(gyp_local_path)/content; python ../build/android/gyp/gcc_preprocess.py "--include-path=.." "--output=$(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/ResultCodes.java" "--template=public/android/java/src/org/chromium/content/common/ResultCodes.template"
+
+.PHONY: content_result_codes_java_gyp_rule_trigger
+content_result_codes_java_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/ResultCodes.java
+
+### Finished generating for all rules
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/ResultCodes.java
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES := \
+	content_result_codes_java_gyp_rule_trigger
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS := \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-m32 \
+	-mmmx \
+	-march=pentium4 \
+	-msse2 \
+	-mfpmath=sse \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-fno-stack-protector \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections
+
+MY_CFLAGS_C :=
+
+MY_DEFS := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DUSE_LINUX_BREAKPAD' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_GPU=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DENABLE_LANGUAGE_DETECTION=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+LOCAL_CFLAGS := $(MY_CFLAGS_C) $(MY_CFLAGS) $(MY_DEFS)
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES := \
+	$(GYP_ABS_ANDROID_TOP_DIR)/frameworks/wilhelm/include \
+	$(GYP_ABS_ANDROID_TOP_DIR)/bionic \
+	$(GYP_ABS_ANDROID_TOP_DIR)/external/stlport/stlport
+
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES)
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-error=c++0x-compat \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_result_codes_java_gyp
+
+# Alias gyp target name.
+.PHONY: result_codes_java
+result_codes_java: content_result_codes_java_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/content/result_codes_java.target.linux-arm.mk b/content/result_codes_java.target.linux-arm.mk
index 04cf2e7..8c20ed9 100644
--- a/content/result_codes_java.target.linux-arm.mk
+++ b/content/result_codes_java.target.linux-arm.mk
@@ -15,13 +15,13 @@
 
 
 ### Generated for rule "content_content_gyp_result_codes_java_target_generate_java_constants":
-# "{'inputs': ['public/common/result_codes_list.h'], 'extension': 'template', 'outputs': ['$(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/%(INPUT_ROOT)s.java'], 'rule_name': 'generate_java_constants', 'rule_sources': ['public/android/java/src/org/chromium/content/common/ResultCodes.template'], 'action': ['gcc', '-E', '-D', 'ANDROID', '-x', 'c-header', '-P', '-I', '..', '-o', '$(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/%(INPUT_ROOT)s.java', '$(RULE_SOURCES)'], 'message': 'Generating Java from cpp template $(RULE_SOURCES)'}":
+# "{'inputs': ['../build/android/gyp/util/build_utils.py', '../build/android/gyp/gcc_preprocess.py', 'public/common/result_codes_list.h'], 'extension': 'template', 'outputs': ['$(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/%(INPUT_ROOT)s.java'], 'variables': {'output_path': '$(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/%(INPUT_ROOT)s.java'}, 'rule_name': 'generate_java_constants', 'rule_sources': ['public/android/java/src/org/chromium/content/common/ResultCodes.template'], 'action': ['python', '../build/android/gyp/gcc_preprocess.py', '--include-path=..', '--output=$(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/%(INPUT_ROOT)s.java', '--template=$(RULE_SOURCES)'], 'message': 'Generating Java from cpp template $(RULE_SOURCES)'}":
 $(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/ResultCodes.java: gyp_local_path := $(LOCAL_PATH)
 $(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/ResultCodes.java: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
 $(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/ResultCodes.java: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
 $(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/ResultCodes.java: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
-$(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/ResultCodes.java: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/common/ResultCodes.template $(LOCAL_PATH)/content/public/common/result_codes_list.h $(GYP_TARGET_DEPENDENCIES)
-	mkdir -p $(gyp_shared_intermediate_dir)/templates/org/chromium/content/common; cd $(gyp_local_path)/content; gcc -E -D ANDROID -x c-header -P -I .. -o "$(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/ResultCodes.java" public/android/java/src/org/chromium/content/common/ResultCodes.template
+$(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/ResultCodes.java: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/common/ResultCodes.template $(LOCAL_PATH)/build/android/gyp/util/build_utils.py $(LOCAL_PATH)/build/android/gyp/gcc_preprocess.py $(LOCAL_PATH)/content/public/common/result_codes_list.h $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/templates/org/chromium/content/common; cd $(gyp_local_path)/content; python ../build/android/gyp/gcc_preprocess.py "--include-path=.." "--output=$(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/ResultCodes.java" "--template=public/android/java/src/org/chromium/content/common/ResultCodes.template"
 
 .PHONY: content_result_codes_java_gyp_rule_trigger
 content_result_codes_java_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/ResultCodes.java
@@ -79,7 +79,6 @@
 
 MY_DEFS := \
 	'-DCONTENT_IMPLEMENTATION' \
-	'-DUSE_SKIA' \
 	'-D_FILE_OFFSET_BITS=64' \
 	'-DUSE_LINUX_BREAKPAD' \
 	'-DNO_TCMALLOC' \
@@ -87,7 +86,6 @@
 	'-DCHROMIUM_BUILD' \
 	'-DUSE_LIBJPEG_TURBO=1' \
 	'-DUSE_PROPRIETARY_CODECS' \
-	'-DENABLE_PEPPER_THREADING' \
 	'-DENABLE_GPU=1' \
 	'-DUSE_OPENSSL=1' \
 	'-DENABLE_EGLIMAGE=1' \
diff --git a/content/result_codes_java.target.linux-x86.mk b/content/result_codes_java.target.linux-x86.mk
index 293b1a7..305c6c3 100644
--- a/content/result_codes_java.target.linux-x86.mk
+++ b/content/result_codes_java.target.linux-x86.mk
@@ -15,13 +15,13 @@
 
 
 ### Generated for rule "content_content_gyp_result_codes_java_target_generate_java_constants":
-# "{'inputs': ['public/common/result_codes_list.h'], 'extension': 'template', 'outputs': ['$(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/%(INPUT_ROOT)s.java'], 'rule_name': 'generate_java_constants', 'rule_sources': ['public/android/java/src/org/chromium/content/common/ResultCodes.template'], 'action': ['gcc', '-E', '-D', 'ANDROID', '-x', 'c-header', '-P', '-I', '..', '-o', '$(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/%(INPUT_ROOT)s.java', '$(RULE_SOURCES)'], 'message': 'Generating Java from cpp template $(RULE_SOURCES)'}":
+# "{'inputs': ['../build/android/gyp/util/build_utils.py', '../build/android/gyp/gcc_preprocess.py', 'public/common/result_codes_list.h'], 'extension': 'template', 'outputs': ['$(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/%(INPUT_ROOT)s.java'], 'variables': {'output_path': '$(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/%(INPUT_ROOT)s.java'}, 'rule_name': 'generate_java_constants', 'rule_sources': ['public/android/java/src/org/chromium/content/common/ResultCodes.template'], 'action': ['python', '../build/android/gyp/gcc_preprocess.py', '--include-path=..', '--output=$(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/%(INPUT_ROOT)s.java', '--template=$(RULE_SOURCES)'], 'message': 'Generating Java from cpp template $(RULE_SOURCES)'}":
 $(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/ResultCodes.java: gyp_local_path := $(LOCAL_PATH)
 $(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/ResultCodes.java: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
 $(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/ResultCodes.java: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
 $(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/ResultCodes.java: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
-$(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/ResultCodes.java: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/common/ResultCodes.template $(LOCAL_PATH)/content/public/common/result_codes_list.h $(GYP_TARGET_DEPENDENCIES)
-	mkdir -p $(gyp_shared_intermediate_dir)/templates/org/chromium/content/common; cd $(gyp_local_path)/content; gcc -E -D ANDROID -x c-header -P -I .. -o "$(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/ResultCodes.java" public/android/java/src/org/chromium/content/common/ResultCodes.template
+$(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/ResultCodes.java: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/common/ResultCodes.template $(LOCAL_PATH)/build/android/gyp/util/build_utils.py $(LOCAL_PATH)/build/android/gyp/gcc_preprocess.py $(LOCAL_PATH)/content/public/common/result_codes_list.h $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/templates/org/chromium/content/common; cd $(gyp_local_path)/content; python ../build/android/gyp/gcc_preprocess.py "--include-path=.." "--output=$(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/ResultCodes.java" "--template=public/android/java/src/org/chromium/content/common/ResultCodes.template"
 
 .PHONY: content_result_codes_java_gyp_rule_trigger
 content_result_codes_java_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/ResultCodes.java
@@ -59,6 +59,7 @@
 	-march=pentium4 \
 	-msse2 \
 	-mfpmath=sse \
+	-fuse-ld=gold \
 	-ffunction-sections \
 	-funwind-tables \
 	-g \
@@ -80,7 +81,6 @@
 
 MY_DEFS := \
 	'-DCONTENT_IMPLEMENTATION' \
-	'-DUSE_SKIA' \
 	'-D_FILE_OFFSET_BITS=64' \
 	'-DUSE_LINUX_BREAKPAD' \
 	'-DNO_TCMALLOC' \
@@ -88,7 +88,6 @@
 	'-DCHROMIUM_BUILD' \
 	'-DUSE_LIBJPEG_TURBO=1' \
 	'-DUSE_PROPRIETARY_CODECS' \
-	'-DENABLE_PEPPER_THREADING' \
 	'-DENABLE_GPU=1' \
 	'-DUSE_OPENSSL=1' \
 	'-DENABLE_EGLIMAGE=1' \
diff --git a/content/shell/android/browsertests_apk/content_browser_tests_android.cc b/content/shell/android/browsertests_apk/content_browser_tests_android.cc
index cb4c120..3425480 100644
--- a/content/shell/android/browsertests_apk/content_browser_tests_android.cc
+++ b/content/shell/android/browsertests_apk/content_browser_tests_android.cc
@@ -77,6 +77,10 @@
   // Append required switches.
   command_line->AppendSwitch(content::kSingleProcessTestsFlag);
   command_line->AppendSwitch(switches::kUseFakeDeviceForMediaStream);
+  // Specify a socket name to not conflict with the default one used
+  // in content_shell.
+  command_line->AppendSwitchASCII(switches::kRemoteDebuggingSocketName,
+                                  "content_browsertests_devtools_remote");
 
   // Create fifo and redirect stdout and stderr to it.
   base::FilePath files_dir(
diff --git a/content/shell/android/browsertests_apk/src/org/chromium/content_browsertests_apk/ContentBrowserTestsActivity.java b/content/shell/android/browsertests_apk/src/org/chromium/content_browsertests_apk/ContentBrowserTestsActivity.java
index 249baf6..3f25e68 100644
--- a/content/shell/android/browsertests_apk/src/org/chromium/content_browsertests_apk/ContentBrowserTestsActivity.java
+++ b/content/shell/android/browsertests_apk/src/org/chromium/content_browsertests_apk/ContentBrowserTestsActivity.java
@@ -15,15 +15,15 @@
 import org.chromium.content.app.LibraryLoader;
 import org.chromium.content.browser.AndroidBrowserProcess;
 import org.chromium.content.common.ProcessInitException;
-import org.chromium.ui.gfx.ActivityNativeWindow;
 import org.chromium.content_shell.ShellManager;
+import org.chromium.ui.WindowAndroid;
 
 @JNINamespace("content")
 public class ContentBrowserTestsActivity extends Activity {
     private static final String TAG = "ChromeBrowserTestsActivity";
 
     private ShellManager mShellManager;
-    private ActivityNativeWindow mActivityNativeWindow;
+    private WindowAndroid mWindowAndroid;
 
     @Override
     public void onCreate(Bundle savedInstanceState) {
@@ -40,8 +40,8 @@
                 (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
         View view = inflater.inflate(R.layout.test_activity, null);
         mShellManager = (ShellManager) view.findViewById(R.id.shell_container);
-        mActivityNativeWindow = new ActivityNativeWindow(this);
-        mShellManager.setWindow(mActivityNativeWindow);
+        mWindowAndroid = new WindowAndroid(this);
+        mShellManager.setWindow(mWindowAndroid);
 
         Log.i(TAG, "Running tests");
         runTests();
diff --git a/content/shell/android/browsertests_apk/src/org/chromium/content_browsertests_apk/ContentBrowserTestsApplication.java b/content/shell/android/browsertests_apk/src/org/chromium/content_browsertests_apk/ContentBrowserTestsApplication.java
index 315a17e..c850636 100644
--- a/content/shell/android/browsertests_apk/src/org/chromium/content_browsertests_apk/ContentBrowserTestsApplication.java
+++ b/content/shell/android/browsertests_apk/src/org/chromium/content_browsertests_apk/ContentBrowserTestsApplication.java
@@ -12,7 +12,6 @@
 
 public class ContentBrowserTestsApplication extends Application {
 
-    private static final String NATIVE_LIBRARY = "content_browsertests";
     private static final String[] MANDATORY_PAK_FILES = new String[] {"content_shell.pak"};
     private static final String PRIVATE_DATA_DIRECTORY_SUFFIX = "content_shell";
 
@@ -24,7 +23,6 @@
 
     public static void initializeApplicationParameters() {
         ResourceExtractor.setMandatoryPaksToExtract(MANDATORY_PAK_FILES);
-        LibraryLoader.setLibraryToLoad(NATIVE_LIBRARY);
         PathUtils.setPrivateDataDirectorySuffix(PRIVATE_DATA_DIRECTORY_SUFFIX);
     }
 
diff --git a/content/shell/android/java/src/org/chromium/content_shell/Shell.java b/content/shell/android/java/src/org/chromium/content_shell/Shell.java
index 7a11022..064e312 100644
--- a/content/shell/android/java/src/org/chromium/content_shell/Shell.java
+++ b/content/shell/android/java/src/org/chromium/content_shell/Shell.java
@@ -24,7 +24,7 @@
 import org.chromium.content.browser.ContentView;
 import org.chromium.content.browser.ContentViewRenderView;
 import org.chromium.content.browser.LoadUrlParams;
-import org.chromium.ui.gfx.NativeWindow;
+import org.chromium.ui.WindowAndroid;
 
 /**
  * Container for the various UI components that make up a shell window.
@@ -50,7 +50,7 @@
     private ClipDrawable mProgressDrawable;
 
     private ContentViewRenderView mContentViewRenderView;
-    private NativeWindow mWindow;
+    private WindowAndroid mWindow;
 
     private boolean mLoading = false;
 
@@ -82,7 +82,7 @@
     /**
      * @param window The owning window for this shell.
      */
-    public void setWindow(NativeWindow window) {
+    public void setWindow(WindowAndroid window) {
         mWindow = window;
     }
 
diff --git a/content/shell/android/java/src/org/chromium/content_shell/ShellManager.java b/content/shell/android/java/src/org/chromium/content_shell/ShellManager.java
index 7cf962d..b3fd950 100644
--- a/content/shell/android/java/src/org/chromium/content_shell/ShellManager.java
+++ b/content/shell/android/java/src/org/chromium/content_shell/ShellManager.java
@@ -13,7 +13,7 @@
 import org.chromium.base.JNINamespace;
 import org.chromium.content.browser.ContentView;
 import org.chromium.content.browser.ContentViewRenderView;
-import org.chromium.ui.gfx.NativeWindow;
+import org.chromium.ui.WindowAndroid;
 
 /**
  * Container and generator of ShellViews.
@@ -23,7 +23,7 @@
 
     public static final String DEFAULT_SHELL_URL = "http://www.google.com";
     private static boolean sStartup = true;
-    private NativeWindow mWindow;
+    private WindowAndroid mWindow;
     private Shell mActiveShell;
 
     private String mStartupUrl = DEFAULT_SHELL_URL;
@@ -51,14 +51,14 @@
     /**
      * @param window The window used to generate all shells.
      */
-    public void setWindow(NativeWindow window) {
+    public void setWindow(WindowAndroid window) {
         mWindow = window;
     }
 
     /**
      * @return The window used to generate all shells.
      */
-    public NativeWindow getWindow() {
+    public WindowAndroid getWindow() {
         return mWindow;
     }
 
diff --git a/content/shell/android/shell_apk/src/org/chromium/content_shell_apk/ContentShellActivity.java b/content/shell/android/shell_apk/src/org/chromium/content_shell_apk/ContentShellActivity.java
index f72d1fb..9dc2bce 100644
--- a/content/shell/android/shell_apk/src/org/chromium/content_shell_apk/ContentShellActivity.java
+++ b/content/shell/android/shell_apk/src/org/chromium/content_shell_apk/ContentShellActivity.java
@@ -4,7 +4,6 @@
 
 package org.chromium.content_shell_apk;
 
-import android.app.Activity;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -26,7 +25,7 @@
 import org.chromium.content.common.ProcessInitException;
 import org.chromium.content_shell.Shell;
 import org.chromium.content_shell.ShellManager;
-import org.chromium.ui.gfx.ActivityNativeWindow;
+import org.chromium.ui.WindowAndroid;
 
 /**
  * Activity for managing the Content Shell.
@@ -44,7 +43,7 @@
     public static final String COMMAND_LINE_ARGS_KEY = "commandLineArgs";
 
     private ShellManager mShellManager;
-    private ActivityNativeWindow mActivityNativeWindow;
+    private WindowAndroid mWindowAndroid;
     private BroadcastReceiver mReceiver;
 
     @Override
@@ -67,9 +66,9 @@
 
             setContentView(R.layout.content_shell_activity);
             mShellManager = (ShellManager) findViewById(R.id.shell_container);
-            mActivityNativeWindow = new ActivityNativeWindow(this);
-            mActivityNativeWindow.restoreInstanceState(savedInstanceState);
-            mShellManager.setWindow(mActivityNativeWindow);
+            mWindowAndroid = new WindowAndroid(this);
+            mWindowAndroid.restoreInstanceState(savedInstanceState);
+            mShellManager.setWindow(mWindowAndroid);
             ContentVideoView.registerContentVideoViewContextDelegate(
                     new ActivityContentVideoViewDelegate(this));
 
@@ -99,7 +98,7 @@
             outState.putString(ACTIVE_SHELL_URL_KEY, activeShell.getContentView().getUrl());
         }
 
-        mActivityNativeWindow.saveInstanceState(outState);
+        mWindowAndroid.saveInstanceState(outState);
     }
 
     private void waitForDebuggerIfNeeded() {
@@ -179,7 +178,7 @@
     @Override
     public void onActivityResult(int requestCode, int resultCode, Intent data) {
         super.onActivityResult(requestCode, resultCode, data);
-        mActivityNativeWindow.onActivityResult(requestCode, resultCode, data);
+        mWindowAndroid.onActivityResult(requestCode, resultCode, data);
     }
 
     private static String getUrlFromIntent(Intent intent) {
diff --git a/content/shell/android/shell_apk/src/org/chromium/content_shell_apk/ContentShellApplication.java b/content/shell/android/shell_apk/src/org/chromium/content_shell_apk/ContentShellApplication.java
index 6d79070..ddbe76f 100644
--- a/content/shell/android/shell_apk/src/org/chromium/content_shell_apk/ContentShellApplication.java
+++ b/content/shell/android/shell_apk/src/org/chromium/content_shell_apk/ContentShellApplication.java
@@ -16,7 +16,6 @@
  */
 public class ContentShellApplication extends Application {
 
-    private static final String NATIVE_LIBRARY = "content_shell_content_view";
     private static final String[] MANDATORY_PAK_FILES = new String[] {"content_shell.pak"};
     private static final String PRIVATE_DATA_DIRECTORY_SUFFIX = "content_shell";
 
@@ -28,7 +27,6 @@
 
     public static void initializeApplicationParameters() {
         ResourceExtractor.setMandatoryPaksToExtract(MANDATORY_PAK_FILES);
-        LibraryLoader.setLibraryToLoad(NATIVE_LIBRARY);
         PathUtils.setPrivateDataDirectorySuffix(PRIVATE_DATA_DIRECTORY_SUFFIX);
     }
 
diff --git a/content/shell/android/shell_manager.cc b/content/shell/android/shell_manager.cc
index 39fd872..0b12e1d 100644
--- a/content/shell/android/shell_manager.cc
+++ b/content/shell/android/shell_manager.cc
@@ -50,8 +50,7 @@
 
 void LaunchShell(JNIEnv* env, jclass clazz, jstring jurl) {
   ShellBrowserContext* browserContext =
-      static_cast<ShellContentBrowserClient*>(
-          GetContentClient()->browser())->browser_context();
+      ShellContentBrowserClient::Get()->browser_context();
   GURL url(base::android::ConvertJavaStringToUTF8(env, jurl));
   Shell::CreateNewWindow(browserContext,
                          url,
diff --git a/content/shell/geolocation/shell_access_token_store.cc b/content/shell/geolocation/shell_access_token_store.cc
index 587057c..2c011cd 100644
--- a/content/shell/geolocation/shell_access_token_store.cc
+++ b/content/shell/geolocation/shell_access_token_store.cc
@@ -7,10 +7,15 @@
 #include "base/bind.h"
 #include "base/message_loop.h"
 #include "base/utf_string_conversions.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/shell/shell_browser_context.h"
+
+namespace content {
 
 ShellAccessTokenStore::ShellAccessTokenStore(
-    net::URLRequestContextGetter* request_context)
-    : request_context_(request_context) {
+    content::ShellBrowserContext* shell_browser_context)
+    : shell_browser_context_(shell_browser_context),
+      system_request_context_(NULL) {
 }
 
 ShellAccessTokenStore::~ShellAccessTokenStore() {
@@ -18,22 +23,33 @@
 
 void ShellAccessTokenStore::LoadAccessTokens(
     const LoadAccessTokensCallbackType& callback) {
-  MessageLoop::current()->PostTask(
+  BrowserThread::PostTaskAndReply(
+      BrowserThread::UI,
       FROM_HERE,
-      base::Bind(&ShellAccessTokenStore::DidLoadAccessTokens,
-                 request_context_, callback));
+      base::Bind(&ShellAccessTokenStore::GetRequestContextOnUIThread,
+                 this,
+                 shell_browser_context_),
+      base::Bind(&ShellAccessTokenStore::RespondOnOriginatingThread,
+                 this,
+                 callback));
 }
 
-void ShellAccessTokenStore::DidLoadAccessTokens(
-    net::URLRequestContextGetter* request_context,
+void ShellAccessTokenStore::GetRequestContextOnUIThread(
+    content::ShellBrowserContext* shell_browser_context) {
+  system_request_context_ = shell_browser_context->GetRequestContext();
+}
+
+void ShellAccessTokenStore::RespondOnOriginatingThread(
     const LoadAccessTokensCallbackType& callback) {
   // Since content_shell is a test executable, rather than an end user program,
   // we provide a dummy access_token set to avoid hitting the server.
   AccessTokenSet access_token_set;
   access_token_set[GURL()] = ASCIIToUTF16("chromium_content_shell");
-  callback.Run(access_token_set, request_context);
+  callback.Run(access_token_set, system_request_context_);
 }
 
 void ShellAccessTokenStore::SaveAccessToken(
     const GURL& server_url, const string16& access_token) {
 }
+
+}  // namespace content
diff --git a/content/shell/geolocation/shell_access_token_store.h b/content/shell/geolocation/shell_access_token_store.h
index 1384ac5..82ee0f8 100644
--- a/content/shell/geolocation/shell_access_token_store.h
+++ b/content/shell/geolocation/shell_access_token_store.h
@@ -7,14 +7,22 @@
 
 #include "content/public/browser/access_token_store.h"
 
+namespace content {
+class ShellBrowserContext;
+
 // Dummy access token store used to initialise the network location provider.
 class ShellAccessTokenStore : public content::AccessTokenStore {
  public:
-  explicit ShellAccessTokenStore(net::URLRequestContextGetter* request_context);
+  explicit ShellAccessTokenStore(
+      content::ShellBrowserContext* shell_browser_context);
 
  private:
   virtual ~ShellAccessTokenStore();
 
+  void GetRequestContextOnUIThread(
+      content::ShellBrowserContext* shell_browser_context);
+  void RespondOnOriginatingThread(const LoadAccessTokensCallbackType& callback);
+
   // AccessTokenStore
   virtual void LoadAccessTokens(
       const LoadAccessTokensCallbackType& callback) OVERRIDE;
@@ -22,13 +30,12 @@
   virtual void SaveAccessToken(
       const GURL& server_url, const string16& access_token) OVERRIDE;
 
-  static void DidLoadAccessTokens(
-      net::URLRequestContextGetter* request_context,
-      const LoadAccessTokensCallbackType& callback);
-
-  net::URLRequestContextGetter* request_context_;
+  content::ShellBrowserContext* shell_browser_context_;
+  net::URLRequestContextGetter* system_request_context_;
 
   DISALLOW_COPY_AND_ASSIGN(ShellAccessTokenStore);
 };
 
+}  // namespace content
+
 #endif  // CONTENT_SHELL_GEOLOCATION_SHELL_ACCESS_TOKEN_STORE_H_
diff --git a/content/shell/notify_done_forwarder.cc b/content/shell/notify_done_forwarder.cc
new file mode 100644
index 0000000..7de67ed
--- /dev/null
+++ b/content/shell/notify_done_forwarder.cc
@@ -0,0 +1,33 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/shell/notify_done_forwarder.h"
+
+#include "content/shell/shell_messages.h"
+#include "content/shell/webkit_test_controller.h"
+
+namespace content {
+
+DEFINE_WEB_CONTENTS_USER_DATA_KEY(NotifyDoneForwarder);
+
+NotifyDoneForwarder::NotifyDoneForwarder(WebContents* web_contents)
+    : WebContentsObserver(web_contents) {}
+
+NotifyDoneForwarder::~NotifyDoneForwarder() {}
+
+bool NotifyDoneForwarder::OnMessageReceived(const IPC::Message& message) {
+  bool handled = true;
+  IPC_BEGIN_MESSAGE_MAP(NotifyDoneForwarder, message)
+    IPC_MESSAGE_HANDLER(ShellViewHostMsg_TestFinishedInSecondaryWindow,
+                        OnTestFinishedInSecondaryWindow)
+    IPC_MESSAGE_UNHANDLED(handled = false)
+  IPC_END_MESSAGE_MAP()
+  return handled;
+}
+
+void NotifyDoneForwarder::OnTestFinishedInSecondaryWindow() {
+  WebKitTestController::Get()->TestFinishedInSecondaryWindow();
+}
+
+}  // namespace content
diff --git a/content/shell/notify_done_forwarder.h b/content/shell/notify_done_forwarder.h
new file mode 100644
index 0000000..008371a
--- /dev/null
+++ b/content/shell/notify_done_forwarder.h
@@ -0,0 +1,34 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_SHELL_NOTIFY_DONE_FORWARDER_H_
+#define CONTENT_SHELL_NOTIFY_DONE_FORWARDER_H_
+
+#include "base/basictypes.h"
+#include "content/public/browser/web_contents_observer.h"
+#include "content/public/browser/web_contents_user_data.h"
+
+namespace content {
+
+class NotifyDoneForwarder : public WebContentsObserver,
+                            public WebContentsUserData<NotifyDoneForwarder> {
+ public:
+  virtual ~NotifyDoneForwarder();
+
+  // WebContentsObserver implementation.
+  virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+
+ private:
+  friend class WebContentsUserData<NotifyDoneForwarder>;
+
+  explicit NotifyDoneForwarder(WebContents* web_contents);
+
+  void OnTestFinishedInSecondaryWindow();
+
+  DISALLOW_COPY_AND_ASSIGN(NotifyDoneForwarder);
+};
+
+}  // namespace content
+
+#endif  // CONTENT_SHELL_NOTIFY_DONE_FORWARDER_H_
diff --git a/content/shell/shell_content_renderer_client.cc b/content/shell/renderer/shell_content_renderer_client.cc
similarity index 93%
rename from content/shell/shell_content_renderer_client.cc
rename to content/shell/renderer/shell_content_renderer_client.cc
index e794f0d..293bc0b 100644
--- a/content/shell/shell_content_renderer_client.cc
+++ b/content/shell/renderer/shell_content_renderer_client.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 "content/shell/shell_content_renderer_client.h"
+#include "content/shell/renderer/shell_content_renderer_client.h"
 
 #include "base/callback.h"
 #include "base/command_line.h"
@@ -11,9 +11,9 @@
 #include "content/public/common/content_switches.h"
 #include "content/public/renderer/render_view.h"
 #include "content/public/test/layouttest_support.h"
-#include "content/shell/shell_render_process_observer.h"
+#include "content/shell/renderer/shell_render_process_observer.h"
+#include "content/shell/renderer/webkit_test_runner.h"
 #include "content/shell/shell_switches.h"
-#include "content/shell/webkit_test_runner.h"
 #include "third_party/WebKit/Source/Platform/chromium/public/WebMediaStreamCenter.h"
 #include "third_party/WebKit/Source/WebKit/chromium/public/WebPluginParams.h"
 #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
@@ -42,7 +42,17 @@
 
 namespace content {
 
+namespace {
+ShellContentRendererClient* g_renderer_client;
+}
+
+ShellContentRendererClient* ShellContentRendererClient::Get() {
+  return g_renderer_client;
+}
+
 ShellContentRendererClient::ShellContentRendererClient() {
+  DCHECK(!g_renderer_client);
+  g_renderer_client = this;
   if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpRenderTree)) {
     EnableWebTestProxyCreation(
         base::Bind(&ShellContentRendererClient::WebTestProxyCreated,
@@ -51,6 +61,7 @@
 }
 
 ShellContentRendererClient::~ShellContentRendererClient() {
+  g_renderer_client = NULL;
 }
 
 void ShellContentRendererClient::LoadHyphenDictionary(
diff --git a/content/shell/shell_content_renderer_client.h b/content/shell/renderer/shell_content_renderer_client.h
similarity index 97%
rename from content/shell/shell_content_renderer_client.h
rename to content/shell/renderer/shell_content_renderer_client.h
index 14bc54d..857b5c9 100644
--- a/content/shell/shell_content_renderer_client.h
+++ b/content/shell/renderer/shell_content_renderer_client.h
@@ -33,6 +33,8 @@
 
 class ShellContentRendererClient : public ContentRendererClient {
  public:
+  static ShellContentRendererClient* Get();
+
   ShellContentRendererClient();
   virtual ~ShellContentRendererClient();
 
diff --git a/content/shell/shell_render_process_observer.cc b/content/shell/renderer/shell_render_process_observer.cc
similarity index 89%
rename from content/shell/shell_render_process_observer.cc
rename to content/shell/renderer/shell_render_process_observer.cc
index da8a5d0..c0fa05c 100644
--- a/content/shell/shell_render_process_observer.cc
+++ b/content/shell/renderer/shell_render_process_observer.cc
@@ -2,17 +2,17 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "content/shell/shell_render_process_observer.h"
+#include "content/shell/renderer/shell_render_process_observer.h"
 
 #include "base/command_line.h"
 #include "content/public/common/content_client.h"
-#include "content/public/renderer/render_view.h"
 #include "content/public/renderer/render_thread.h"
+#include "content/public/renderer/render_view.h"
 #include "content/public/test/layouttest_support.h"
-#include "content/shell/shell_content_renderer_client.h"
+#include "content/shell/renderer/shell_content_renderer_client.h"
+#include "content/shell/renderer/webkit_test_runner.h"
 #include "content/shell/shell_messages.h"
 #include "content/shell/shell_switches.h"
-#include "content/shell/webkit_test_runner.h"
 #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
 #include "third_party/WebKit/Tools/DumpRenderTree/chromium/TestRunner/public/WebTestInterfaces.h"
 #include "webkit/glue/webkit_glue.h"
@@ -96,10 +96,7 @@
 
 void ShellRenderProcessObserver::OnLoadHyphenDictionary(
     const IPC::PlatformFileForTransit& dict_file) {
-  ShellContentRendererClient* renderer_client =
-      static_cast<content::ShellContentRendererClient*>(
-          content::GetContentClient()->renderer());
-  renderer_client->LoadHyphenDictionary(
+  ShellContentRendererClient::Get()->LoadHyphenDictionary(
       IPC::PlatformFileForTransitToPlatformFile(dict_file));
 }
 
diff --git a/content/shell/shell_render_process_observer.h b/content/shell/renderer/shell_render_process_observer.h
similarity index 100%
rename from content/shell/shell_render_process_observer.h
rename to content/shell/renderer/shell_render_process_observer.h
diff --git a/content/shell/webkit_test_runner.cc b/content/shell/renderer/webkit_test_runner.cc
similarity index 90%
rename from content/shell/webkit_test_runner.cc
rename to content/shell/renderer/webkit_test_runner.cc
index eb2c10d..a4c2d6b 100644
--- a/content/shell/webkit_test_runner.cc
+++ b/content/shell/renderer/webkit_test_runner.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 "content/shell/webkit_test_runner.h"
+#include "content/shell/renderer/webkit_test_runner.h"
 
 #include <algorithm>
 #include <clocale>
@@ -15,14 +15,14 @@
 #include "base/message_loop.h"
 #include "base/string_util.h"
 #include "base/stringprintf.h"
-#include "base/sys_string_conversions.h"
+#include "base/strings/sys_string_conversions.h"
 #include "base/time.h"
 #include "base/utf_string_conversions.h"
 #include "content/public/renderer/render_view.h"
 #include "content/public/renderer/render_view_visitor.h"
 #include "content/public/test/layouttest_support.h"
+#include "content/shell/renderer/shell_render_process_observer.h"
 #include "content/shell/shell_messages.h"
-#include "content/shell/shell_render_process_observer.h"
 #include "content/shell/webkit_test_helpers.h"
 #include "net/base/net_errors.h"
 #include "net/base/net_util.h"
@@ -47,6 +47,7 @@
 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
 #include "third_party/WebKit/Source/WebKit/chromium/public/WebHistoryItem.h"
 #include "third_party/WebKit/Source/WebKit/chromium/public/WebKit.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebScriptSource.h"
 #include "third_party/WebKit/Source/WebKit/chromium/public/WebTestingSupport.h"
 #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
 #include "third_party/WebKit/Tools/DumpRenderTree/chromium/TestRunner/public/WebTask.h"
@@ -58,6 +59,7 @@
 #include "webkit/glue/glue_serialize.h"
 #include "webkit/glue/webkit_glue.h"
 #include "webkit/glue/webpreferences.h"
+#include "webkit/mocks/test_media_stream_client.h"
 
 using WebKit::Platform;
 using WebKit::WebArrayBufferView;
@@ -68,8 +70,11 @@
 using WebKit::WebFrame;
 using WebKit::WebGamepads;
 using WebKit::WebHistoryItem;
+using WebKit::WebMediaPlayer;
+using WebKit::WebMediaPlayerClient;
 using WebKit::WebPoint;
 using WebKit::WebRect;
+using WebKit::WebScriptSource;
 using WebKit::WebSize;
 using WebKit::WebString;
 using WebKit::WebURL;
@@ -78,7 +83,6 @@
 using WebKit::WebTestingSupport;
 using WebKit::WebVector;
 using WebKit::WebView;
-using WebTestRunner::WebPreferences;
 using WebTestRunner::WebTask;
 using WebTestRunner::WebTestInterfaces;
 using WebTestRunner::WebTestProxyBase;
@@ -159,6 +163,26 @@
   DISALLOW_COPY_AND_ASSIGN(ProxyToRenderViewVisitor);
 };
 
+class NavigateAwayVisitor : public RenderViewVisitor {
+ public:
+  NavigateAwayVisitor(RenderView* main_render_view)
+      : main_render_view_(main_render_view) {}
+  virtual ~NavigateAwayVisitor() {}
+
+  virtual bool Visit(RenderView* render_view) OVERRIDE {
+    if (render_view == main_render_view_)
+      return true;
+    render_view->GetWebView()->mainFrame()
+        ->loadRequest(WebURLRequest(GURL("about:blank")));
+    return true;
+  }
+
+ private:
+  RenderView* main_render_view_;
+
+  DISALLOW_COPY_AND_ASSIGN(NavigateAwayVisitor);
+};
+
 }  // namespace
 
 WebKitTestRunner::WebKitTestRunner(RenderView* render_view)
@@ -197,7 +221,7 @@
 }
 
 void WebKitTestRunner::postDelayedTask(WebTask* task, long long ms) {
-  MessageLoop::current()->PostDelayedTask(
+  base::MessageLoop::current()->PostDelayedTask(
       FROM_HERE,
       base::Bind(&WebTask::run, base::Owned(task)),
       base::TimeDelta::FromMilliseconds(ms));
@@ -274,12 +298,12 @@
   return WebURL(GURL(new_url));
 }
 
-WebPreferences* WebKitTestRunner::preferences() {
+WebTestRunner::WebPreferences* WebKitTestRunner::preferences() {
   return &prefs_;
 }
 
 void WebKitTestRunner::applyPreferences() {
-  webkit_glue::WebPreferences prefs = render_view()->GetWebkitPreferences();
+  WebPreferences prefs = render_view()->GetWebkitPreferences();
   ExportLayoutTestSpecificPreferences(prefs_, &prefs);
   render_view()->SetWebkitPreferences(prefs);
   Send(new ShellViewHostMsg_OverridePreferences(routing_id(), prefs));
@@ -402,8 +426,10 @@
 }
 
 void WebKitTestRunner::testFinished() {
-  if (!is_main_window_)
+  if (!is_main_window_) {
+    Send(new ShellViewHostMsg_TestFinishedInSecondaryWindow(routing_id()));
     return;
+  }
   WebTestInterfaces* interfaces =
       ShellRenderProcessObserver::GetInstance()->test_interfaces();
   interfaces->setTestIsRunning(false);
@@ -434,6 +460,8 @@
 }
 
 void WebKitTestRunner::closeRemainingWindows() {
+  NavigateAwayVisitor visitor(render_view());
+  RenderView::ForEach(&visitor);
   Send(new ShellViewHostMsg_CloseRemainingWindows(routing_id()));
 }
 
@@ -489,6 +517,17 @@
   history->swap(result);
 }
 
+WebMediaPlayer* WebKitTestRunner::createWebMediaPlayer(
+    WebFrame* frame, const WebURL& url, WebMediaPlayerClient* client)
+{
+  if (!test_media_stream_client_) {
+    test_media_stream_client_.reset(
+        new webkit_glue::TestMediaStreamClient());
+  }
+  return webkit_glue::CreateMediaPlayer(
+      frame, url, client, test_media_stream_client_.get());
+}
+
 // RenderViewObserver  --------------------------------------------------------
 
 void WebKitTestRunner::DidClearWindowObject(WebFrame* frame) {
@@ -503,6 +542,7 @@
                         OnSetTestConfiguration)
     IPC_MESSAGE_HANDLER(ShellViewMsg_SessionHistory, OnSessionHistory)
     IPC_MESSAGE_HANDLER(ShellViewMsg_Reset, OnReset)
+    IPC_MESSAGE_HANDLER(ShellViewMsg_NotifyDone, OnNotifyDone)
     IPC_MESSAGE_UNHANDLED(handled = false)
   IPC_END_MESSAGE_MAP()
 
@@ -511,6 +551,13 @@
 
 void WebKitTestRunner::Navigate(const GURL& url) {
   focus_on_next_commit_ = true;
+  if (!is_main_window_ &&
+      ShellRenderProcessObserver::GetInstance()->main_test_runner() == this) {
+    WebTestInterfaces* interfaces =
+        ShellRenderProcessObserver::GetInstance()->test_interfaces();
+    interfaces->setTestIsRunning(true);
+    interfaces->configureForTestWithURL(GURL(), false);
+  }
 }
 
 void WebKitTestRunner::DidCommitProvisionalLoad(WebFrame* frame,
@@ -582,7 +629,7 @@
       const uint8_t* raw_pixels =
           reinterpret_cast<const uint8_t*>(snapshot.getPixels());
       size_t snapshot_size = snapshot.getSize();
-      scoped_array<uint8_t> reordered_pixels(new uint8_t[snapshot_size]);
+      scoped_ptr<uint8_t[]> reordered_pixels(new uint8_t[snapshot_size]);
       for (size_t i = 0; i < snapshot_size; i += 4) {
         reordered_pixels[i] = raw_pixels[i + 2];
         reordered_pixels[i + 1] = raw_pixels[i + 1];
@@ -606,7 +653,7 @@
     }
   }
 
-  MessageLoop::current()->PostTask(
+  base::MessageLoop::current()->PostTask(
       FROM_HERE,
       base::Bind(base::IgnoreResult(&WebKitTestRunner::Send),
                  base::Unretained(this),
@@ -647,4 +694,9 @@
   Send(new ShellViewHostMsg_ResetDone(routing_id()));
 }
 
+void WebKitTestRunner::OnNotifyDone() {
+  render_view()->GetWebView()->mainFrame()->executeScript(
+      WebScriptSource(WebString::fromUTF8("testRunner.notifyDone();")));
+}
+
 }  // namespace content
diff --git a/content/shell/webkit_test_runner.h b/content/shell/renderer/webkit_test_runner.h
similarity index 92%
rename from content/shell/webkit_test_runner.h
rename to content/shell/renderer/webkit_test_runner.h
index 860378d..0023ec4 100644
--- a/content/shell/webkit_test_runner.h
+++ b/content/shell/renderer/webkit_test_runner.h
@@ -19,6 +19,8 @@
 class SkCanvas;
 
 namespace WebKit {
+class WebMediaPlayer;
+class WebMediaPlayerClient;
 struct WebRect;
 }
 
@@ -26,6 +28,10 @@
 class WebTestProxyBase;
 }
 
+namespace webkit_glue {
+class TestMediaStreamClient;
+}
+
 namespace content {
 
 // This is the renderer side of the webkit test runner.
@@ -90,6 +96,10 @@
       WebTestRunner::WebTestProxyBase* proxy,
       WebKit::WebVector<WebKit::WebHistoryItem>* history,
       size_t* currentEntryIndex);
+  virtual WebKit::WebMediaPlayer* createWebMediaPlayer(
+      WebKit::WebFrame* frame,
+      const WebKit::WebURL& url,
+      WebKit::WebMediaPlayerClient* client);
 
   void Reset();
 
@@ -104,6 +114,7 @@
       const std::vector<std::vector<std::string> >& session_histories,
       const std::vector<unsigned>& current_entry_indexes);
   void OnReset();
+  void OnNotifyDone();
 
   // After finishing the test, retrieves the audio, text, and pixel dumps from
   // the TestRunner library and sends them to the browser process.
@@ -125,6 +136,8 @@
 
   bool focus_on_next_commit_;
 
+  scoped_ptr<webkit_glue::TestMediaStreamClient> test_media_stream_client_;
+
   DISALLOW_COPY_AND_ASSIGN(WebKitTestRunner);
 };
 
diff --git a/content/shell/shell.cc b/content/shell/shell.cc
index 0d32f0f..5eac7af 100644
--- a/content/shell/shell.cc
+++ b/content/shell/shell.cc
@@ -22,6 +22,7 @@
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_contents_view.h"
 #include "content/public/common/renderer_preferences.h"
+#include "content/shell/notify_done_forwarder.h"
 #include "content/shell/shell_browser_main_parts.h"
 #include "content/shell/shell_content_browser_client.h"
 #include "content/shell/shell_devtools_frontend.h"
@@ -76,7 +77,8 @@
   }
 
   if (windows_.empty() && quit_message_loop_)
-    MessageLoop::current()->PostTask(FROM_HERE, MessageLoop::QuitClosure());
+    base::MessageLoop::current()->PostTask(FROM_HERE,
+                                           base::MessageLoop::QuitClosure());
 }
 
 Shell* Shell::CreateShell(WebContents* web_contents) {
@@ -104,7 +106,7 @@
   std::vector<Shell*> open_windows(windows_);
   for (size_t i = 0; i < open_windows.size(); ++i)
     open_windows[i]->Close();
-  MessageLoop::current()->RunUntilIdle();
+  base::MessageLoop::current()->RunUntilIdle();
 }
 
 void Shell::SetShellCreatedCallback(
@@ -189,17 +191,25 @@
     return;
   }
   devtools_frontend_ = ShellDevToolsFrontend::Show(web_contents());
+  registrar_.Add(this,
+                 NOTIFICATION_WEB_CONTENTS_DESTROYED,
+                 Source<WebContents>(
+                     devtools_frontend_->frontend_shell()->web_contents()));
 }
 
 void Shell::CloseDevTools() {
   if (!devtools_frontend_)
     return;
+  registrar_.Remove(this,
+                    NOTIFICATION_WEB_CONTENTS_DESTROYED,
+                    Source<WebContents>(
+                        devtools_frontend_->frontend_shell()->web_contents()));
   devtools_frontend_->Close();
   devtools_frontend_ = NULL;
 }
 
 gfx::NativeView Shell::GetContentView() {
-  if (!web_contents_.get())
+  if (!web_contents_)
     return NULL;
   return web_contents_->GetView()->GetNativeView();
 }
@@ -263,6 +273,8 @@
                                const GURL& target_url,
                                WebContents* new_contents) {
   CreateShell(new_contents);
+  if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpRenderTree))
+    NotifyDoneForwarder::CreateForWebContents(new_contents);
 }
 
 void Shell::DidNavigateMainFramePostCommit(WebContents* web_contents) {
@@ -270,7 +282,7 @@
 }
 
 JavaScriptDialogManager* Shell::GetJavaScriptDialogManager() {
-  if (!dialog_manager_.get())
+  if (!dialog_manager_)
     dialog_manager_.reset(new ShellJavaScriptDialogManager());
   return dialog_manager_.get();
 }
@@ -308,6 +320,11 @@
       string16 text = title->first->GetTitle();
       PlatformSetTitle(text);
     }
+  } else if (type == NOTIFICATION_WEB_CONTENTS_DESTROYED) {
+    devtools_frontend_ = NULL;
+    registrar_.Remove(this, NOTIFICATION_WEB_CONTENTS_DESTROYED, source);
+  } else {
+    NOTREACHED();
   }
 }
 
diff --git a/content/shell/shell.h b/content/shell/shell.h
index fb1c5c6..736bd3f 100644
--- a/content/shell/shell.h
+++ b/content/shell/shell.h
@@ -10,9 +10,9 @@
 #include "base/basictypes.h"
 #include "base/callback_forward.h"
 #include "base/memory/scoped_ptr.h"
-#include "base/string_piece.h"
-#include "content/public/browser/notification_registrar.h"
+#include "base/strings/string_piece.h"
 #include "content/public/browser/notification_observer.h"
+#include "content/public/browser/notification_registrar.h"
 #include "content/public/browser/web_contents_delegate.h"
 #include "ipc/ipc_channel.h"
 #include "ui/gfx/native_widget_types.h"
diff --git a/content/shell/shell_android.cc b/content/shell/shell_android.cc
index 32d7fc0..d8a6fcb 100644
--- a/content/shell/shell_android.cc
+++ b/content/shell/shell_android.cc
@@ -6,11 +6,11 @@
 
 #include <jni.h>
 
-#include "base/android/scoped_java_ref.h"
 #include "base/android/jni_string.h"
+#include "base/android/scoped_java_ref.h"
 #include "base/command_line.h"
 #include "base/logging.h"
-#include "base/string_piece.h"
+#include "base/strings/string_piece.h"
 #include "content/public/common/content_switches.h"
 #include "content/shell/android/shell_manager.h"
 #include "jni/Shell_jni.h"
diff --git a/content/shell/shell_application_mac.mm b/content/shell/shell_application_mac.mm
index 7918c1d..a810804 100644
--- a/content/shell/shell_application_mac.mm
+++ b/content/shell/shell_application_mac.mm
@@ -27,8 +27,7 @@
 
 - (IBAction)newDocument:(id)sender {
   content::ShellBrowserContext* browserContext =
-      static_cast<content::ShellContentBrowserClient*>(
-        content::GetContentClient()->browser())->browser_context();
+      content::ShellContentBrowserClient::Get()->browser_context();
   content::Shell::CreateNewWindow(browserContext,
                                   GURL("about:blank"),
                                   NULL,
diff --git a/content/shell/shell_browser_context.cc b/content/shell/shell_browser_context.cc
index 81af960..5eb0f6d 100644
--- a/content/shell/shell_browser_context.cc
+++ b/content/shell/shell_browser_context.cc
@@ -62,7 +62,7 @@
 }
 
 ShellBrowserContext::~ShellBrowserContext() {
-  if (resource_context_.get()) {
+  if (resource_context_) {
     BrowserThread::DeleteSoon(
       BrowserThread::IO, FROM_HERE, resource_context_.release());
   }
@@ -113,7 +113,7 @@
 DownloadManagerDelegate* ShellBrowserContext::GetDownloadManagerDelegate()  {
   DownloadManager* manager = BrowserContext::GetDownloadManager(this);
 
-  if (!download_manager_delegate_.get()) {
+  if (!download_manager_delegate_) {
     download_manager_delegate_ = new ShellDownloadManagerDelegate();
     download_manager_delegate_->SetDownloadManager(manager);
     CommandLine* cmd_line = CommandLine::ForCurrentProcess();
diff --git a/content/shell/shell_browser_main.cc b/content/shell/shell_browser_main.cc
index 28a9431..e6e45c3 100644
--- a/content/shell/shell_browser_main.cc
+++ b/content/shell/shell_browser_main.cc
@@ -13,13 +13,14 @@
 #include "base/logging.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/message_loop.h"
-#include "base/sys_string_conversions.h"
+#include "base/strings/sys_string_conversions.h"
 #include "base/threading/thread_restrictions.h"
 #include "base/utf_string_conversions.h"
 #include "content/public/browser/browser_main_runner.h"
 #include "content/shell/shell.h"
 #include "content/shell/shell_switches.h"
 #include "content/shell/webkit_test_controller.h"
+#include "content/shell/webkit_test_helpers.h"
 #include "net/base/net_util.h"
 #include "webkit/support/webkit_support.h"
 
@@ -60,8 +61,11 @@
 #else
     base::FilePath local_file(path_or_url);
 #endif
-    file_util::AbsolutePath(&local_file);
-    test_url = net::FilePathToFileURL(local_file);
+    if (!file_util::PathExists(local_file)) {
+      local_file = content::GetWebKitRootDirFilePath()
+          .Append(FILE_PATH_LITERAL("LayoutTests")).Append(local_file);
+    }
+    test_url = net::FilePathToFileURL(base::MakeAbsoluteFilePath(local_file));
   }
   base::FilePath local_path;
   if (current_working_directory) {
@@ -116,7 +120,8 @@
 
   if (CommandLine::ForCurrentProcess()->HasSwitch(
         switches::kCheckLayoutTestSysDeps)) {
-    MessageLoop::current()->PostTask(FROM_HERE, MessageLoop::QuitClosure());
+    base::MessageLoop::current()->PostTask(FROM_HERE,
+                                           base::MessageLoop::QuitClosure());
     main_runner_->Run();
     content::Shell::CloseAllWindows();
     main_runner_->Shutdown();
@@ -166,7 +171,8 @@
         break;
     }
     if (!ran_at_least_once) {
-      MessageLoop::current()->PostTask(FROM_HERE, MessageLoop::QuitClosure());
+      base::MessageLoop::current()->PostTask(FROM_HERE,
+                                             base::MessageLoop::QuitClosure());
       main_runner_->Run();
     }
     exit_code = 0;
diff --git a/content/shell/shell_browser_main_parts.cc b/content/shell/shell_browser_main_parts.cc
index c0d9cb4..99ff7ce 100644
--- a/content/shell/shell_browser_main_parts.cc
+++ b/content/shell/shell_browser_main_parts.cc
@@ -8,7 +8,6 @@
 #include "base/command_line.h"
 #include "base/files/file_path.h"
 #include "base/message_loop.h"
-#include "base/string_number_conversions.h"
 #include "base/threading/thread.h"
 #include "base/threading/thread_restrictions.h"
 #include "cc/base/switches.h"
@@ -31,7 +30,7 @@
 #endif
 
 #if defined(USE_AURA) && defined(USE_X11)
-#include "ui/base/touch/touch_factory.h"
+#include "ui/base/touch/touch_factory_x11.h"
 #endif
 
 namespace content {
@@ -92,7 +91,7 @@
 
 void ShellBrowserMainParts::PostMainMessageLoopStart() {
 #if defined(OS_ANDROID)
-  MessageLoopForUI::current()->Start();
+  base::MessageLoopForUI::current()->Start();
 #endif
 }
 
@@ -113,25 +112,7 @@
   Shell::Initialize();
   net::NetModule::SetResourceProvider(PlatformResourceProvider);
 
-  int port = 0;
-// On android the port number isn't used.
-#if !defined(OS_ANDROID)
-  // See if the user specified a port on the command line (useful for
-  // automation). If not, use an ephemeral port by specifying 0.
-  const CommandLine& command_line = *CommandLine::ForCurrentProcess();
-  if (command_line.HasSwitch(switches::kRemoteDebuggingPort)) {
-    int temp_port;
-    std::string port_str =
-        command_line.GetSwitchValueASCII(switches::kRemoteDebuggingPort);
-    if (base::StringToInt(port_str, &temp_port) &&
-        temp_port > 0 && temp_port < 65535) {
-      port = temp_port;
-    } else {
-      DLOG(WARNING) << "Invalid http debugger port number " << temp_port;
-    }
-  }
-#endif
-  devtools_delegate_ = new ShellDevToolsDelegate(browser_context_.get(), port);
+  devtools_delegate_ = new ShellDevToolsDelegate(browser_context_.get());
 
   if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpRenderTree)) {
     Shell::CreateNewWindow(browser_context_.get(),
diff --git a/content/shell/shell_content_browser_client.cc b/content/shell/shell_content_browser_client.cc
index 163027f..fc2a1e0 100644
--- a/content/shell/shell_content_browser_client.cc
+++ b/content/shell/shell_content_browser_client.cc
@@ -7,6 +7,8 @@
 #include "base/command_line.h"
 #include "base/file_util.h"
 #include "base/path_service.h"
+#include "content/public/browser/notification_service.h"
+#include "content/public/browser/notification_types.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/resource_dispatcher_host.h"
 #include "content/public/browser/storage_partition.h"
@@ -23,6 +25,7 @@
 #include "content/shell/shell_switches.h"
 #include "content/shell/shell_web_contents_view_delegate_creator.h"
 #include "content/shell/webkit_test_controller.h"
+#include "content/shell/webkit_test_helpers.h"
 #include "googleurl/src/gurl.h"
 #include "webkit/glue/webpreferences.h"
 
@@ -37,50 +40,25 @@
 
 namespace {
 
-base::FilePath GetWebKitRootDirFilePath() {
-  base::FilePath base_path;
-  PathService::Get(base::DIR_SOURCE_ROOT, &base_path);
-  if (file_util::PathExists(
-          base_path.Append(FILE_PATH_LITERAL("third_party/WebKit")))) {
-    // We're in a WebKit-in-chrome checkout.
-    return base_path.Append(FILE_PATH_LITERAL("third_party/WebKit"));
-  } else if (file_util::PathExists(
-          base_path.Append(FILE_PATH_LITERAL("chromium")))) {
-    // We're in a WebKit-only checkout on Windows.
-    return base_path.Append(FILE_PATH_LITERAL("../.."));
-  } else if (file_util::PathExists(
-          base_path.Append(FILE_PATH_LITERAL("webkit/support")))) {
-    // We're in a WebKit-only/xcodebuild checkout on Mac
-    return base_path.Append(FILE_PATH_LITERAL("../../.."));
-  }
-  // We're in a WebKit-only, make-build, so the DIR_SOURCE_ROOT is already the
-  // WebKit root. That, or we have no idea where we are.
-  return base_path;
-}
-
-base::FilePath GetChromiumRootDirFilePath() {
-  base::FilePath webkit_path = GetWebKitRootDirFilePath();
-  if (file_util::PathExists(webkit_path.Append(
-          FILE_PATH_LITERAL("Source/WebKit/chromium/webkit/support")))) {
-    // We're in a WebKit-only checkout.
-    return webkit_path.Append(FILE_PATH_LITERAL("Source/WebKit/chromium"));
-  } else {
-    // We're in a Chromium checkout, and WebKit is in third_party/WebKit.
-    return webkit_path.Append(FILE_PATH_LITERAL("../.."));
-  }
-}
+ShellContentBrowserClient* g_browser_client;
 
 }  // namespace
 
+ShellContentBrowserClient* ShellContentBrowserClient::Get() {
+  return g_browser_client;
+}
+
 ShellContentBrowserClient::ShellContentBrowserClient()
     : hyphen_dictionary_file_(base::kInvalidPlatformFileValue),
       shell_browser_main_parts_(NULL) {
+  DCHECK(!g_browser_client);
+  g_browser_client = this;
   if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpRenderTree))
     return;
   webkit_source_dir_ = GetWebKitRootDirFilePath();
-  base::FilePath dictionary_file_path = GetChromiumRootDirFilePath().Append(
-      FILE_PATH_LITERAL("third_party/hyphen/hyph_en_US.dic"));
-  file_util::AbsolutePath(&dictionary_file_path);
+  base::FilePath dictionary_file_path = base::MakeAbsoluteFilePath(
+      GetChromiumRootDirFilePath().Append(
+          FILE_PATH_LITERAL("third_party/hyphen/hyph_en_US.dic")));
   hyphen_dictionary_file_ = base::CreatePlatformFile(dictionary_file_path,
                                                      base::PLATFORM_FILE_READ |
                                                      base::PLATFORM_FILE_OPEN,
@@ -89,6 +67,7 @@
 }
 
 ShellContentBrowserClient::~ShellContentBrowserClient() {
+  g_browser_client = NULL;
 }
 
 BrowserMainParts* ShellContentBrowserClient::CreateBrowserMainParts(
@@ -108,12 +87,9 @@
       BrowserContext::GetDefaultStoragePartition(browser_context())
           ->GetQuotaManager()));
   host->Send(new ShellViewMsg_SetWebKitSourceDir(webkit_source_dir_));
-
-  if (hyphen_dictionary_file_ != base::kInvalidPlatformFileValue) {
-    IPC::PlatformFileForTransit file = IPC::GetFileHandleForProcess(
-        hyphen_dictionary_file_, host->GetHandle(), false);
-    host->Send(new ShellViewMsg_LoadHyphenDictionary(file));
-  }
+  registrar_.Add(this,
+                 NOTIFICATION_RENDERER_PROCESS_CREATED,
+                 Source<RenderProcessHost>(host));
 }
 
 net::URLRequestContextGetter* ShellContentBrowserClient::CreateRequestContext(
@@ -145,7 +121,7 @@
 void ShellContentBrowserClient::OverrideWebkitPrefs(
     RenderViewHost* render_view_host,
     const GURL& url,
-    webkit_glue::WebPreferences* prefs) {
+    WebPreferences* prefs) {
   if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpRenderTree))
     return;
   WebKitTestController::Get()->OverrideWebkitPrefs(prefs);
@@ -206,6 +182,28 @@
 }
 #endif
 
+void ShellContentBrowserClient::Observe(int type,
+                                        const NotificationSource& source,
+                                        const NotificationDetails& details) {
+  switch (type) {
+    case NOTIFICATION_RENDERER_PROCESS_CREATED: {
+      registrar_.Remove(this,
+                        NOTIFICATION_RENDERER_PROCESS_CREATED,
+                        source);
+      if (hyphen_dictionary_file_ != base::kInvalidPlatformFileValue) {
+        RenderProcessHost* host = Source<RenderProcessHost>(source).ptr();
+        IPC::PlatformFileForTransit file = IPC::GetFileHandleForProcess(
+            hyphen_dictionary_file_, host->GetHandle(), false);
+        host->Send(new ShellViewMsg_LoadHyphenDictionary(file));
+      }
+      break;
+    }
+
+    default:
+      NOTREACHED();
+  }
+}
+
 ShellBrowserContext* ShellContentBrowserClient::browser_context() {
   return shell_browser_main_parts_->browser_context();
 }
@@ -216,7 +214,7 @@
 }
 
 AccessTokenStore* ShellContentBrowserClient::CreateAccessTokenStore() {
-  return new ShellAccessTokenStore(browser_context()->GetRequestContext());
+  return new ShellAccessTokenStore(browser_context());
 }
 
 ShellBrowserContext*
diff --git a/content/shell/shell_content_browser_client.h b/content/shell/shell_content_browser_client.h
index 6fce1f8..0adba6f 100644
--- a/content/shell/shell_content_browser_client.h
+++ b/content/shell/shell_content_browser_client.h
@@ -12,6 +12,8 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/platform_file.h"
 #include "content/public/browser/content_browser_client.h"
+#include "content/public/browser/notification_observer.h"
+#include "content/public/browser/notification_registrar.h"
 
 namespace content {
 
@@ -19,8 +21,12 @@
 class ShellBrowserMainParts;
 class ShellResourceDispatcherHostDelegate;
 
-class ShellContentBrowserClient : public ContentBrowserClient {
+class ShellContentBrowserClient : public ContentBrowserClient,
+                                  public NotificationObserver {
  public:
+  // Gets the current instance.
+  static ShellContentBrowserClient* Get();
+
   ShellContentBrowserClient();
   virtual ~ShellContentBrowserClient();
 
@@ -40,7 +46,7 @@
                                               int child_process_id) OVERRIDE;
   virtual void OverrideWebkitPrefs(RenderViewHost* render_view_host,
                                    const GURL& url,
-                                   webkit_glue::WebPreferences* prefs) OVERRIDE;
+                                   WebPreferences* prefs) OVERRIDE;
   virtual void ResourceDispatcherHostCreated() OVERRIDE;
   virtual AccessTokenStore* CreateAccessTokenStore() OVERRIDE;
   virtual std::string GetDefaultDownloadName() OVERRIDE;
@@ -57,6 +63,11 @@
       std::vector<content::FileDescriptorInfo>* mappings) OVERRIDE;
 #endif
 
+  // NotificationObserver implementation.
+  virtual void Observe(int type,
+                       const NotificationSource& source,
+                       const NotificationDetails& details) OVERRIDE;
+
   ShellBrowserContext* browser_context();
   ShellBrowserContext* off_the_record_browser_context();
   ShellResourceDispatcherHostDelegate* resource_dispatcher_host_delegate() {
@@ -78,6 +89,8 @@
   base::PlatformFile hyphen_dictionary_file_;
 
   ShellBrowserMainParts* shell_browser_main_parts_;
+
+  NotificationRegistrar registrar_;
 };
 
 }  // namespace content
diff --git a/content/shell/shell_content_client.cc b/content/shell/shell_content_client.cc
index f96b6a3..a8f697a 100644
--- a/content/shell/shell_content_client.cc
+++ b/content/shell/shell_content_client.cc
@@ -5,7 +5,7 @@
 #include "content/shell/shell_content_client.h"
 
 #include "base/command_line.h"
-#include "base/string_piece.h"
+#include "base/strings/string_piece.h"
 #include "base/utf_string_conversions.h"
 #include "content/public/common/content_switches.h"
 #include "content/shell/shell_switches.h"
diff --git a/content/shell/shell_devtools_delegate.cc b/content/shell/shell_devtools_delegate.cc
index 8eb4722..ae46298 100644
--- a/content/shell/shell_devtools_delegate.cc
+++ b/content/shell/shell_devtools_delegate.cc
@@ -4,39 +4,63 @@
 
 #include "content/shell/shell_devtools_delegate.h"
 
+#include <vector>
+
 #include "base/bind.h"
+#include "base/command_line.h"
+#include "base/strings/string_number_conversions.h"
 #include "content/public/browser/devtools_http_handler.h"
 #include "content/public/browser/web_contents.h"
+#include "content/public/common/content_switches.h"
 #include "content/public/common/url_constants.h"
 #include "content/shell/shell.h"
 #include "grit/shell_resources.h"
-#include "net/base/tcp_listen_socket.h"
+#include "net/socket/tcp_listen_socket.h"
 #include "ui/base/resource/resource_bundle.h"
 
 #if defined(OS_ANDROID)
 #include "content/public/browser/android/devtools_auth.h"
-#include "net/base/unix_domain_socket_posix.h"
+#include "net/socket/unix_domain_socket_posix.h"
+#endif
 
 namespace {
-const char kSocketName[] = "content_shell_devtools_remote";
-}
+
+net::StreamListenSocketFactory* CreateSocketFactory() {
+  const CommandLine& command_line = *CommandLine::ForCurrentProcess();
+#if defined(OS_ANDROID)
+  std::string socket_name = "content_shell_devtools_remote";
+  if (command_line.HasSwitch(switches::kRemoteDebuggingSocketName)) {
+    socket_name = command_line.GetSwitchValueASCII(
+        switches::kRemoteDebuggingSocketName);
+  }
+  return new net::UnixDomainSocketWithAbstractNamespaceFactory(
+      socket_name, base::Bind(&content::CanUserConnectToDevTools));
+#else
+  // See if the user specified a port on the command line (useful for
+  // automation). If not, use an ephemeral port by specifying 0.
+  int port = 0;
+  if (command_line.HasSwitch(switches::kRemoteDebuggingPort)) {
+    int temp_port;
+    std::string port_str =
+        command_line.GetSwitchValueASCII(switches::kRemoteDebuggingPort);
+    if (base::StringToInt(port_str, &temp_port) &&
+        temp_port > 0 && temp_port < 65535) {
+      port = temp_port;
+    } else {
+      DLOG(WARNING) << "Invalid http debugger port number " << temp_port;
+    }
+  }
+  return new net::TCPListenSocketFactory("127.0.0.1", port);
 #endif
+}
+}  // namespace
 
 namespace content {
 
-ShellDevToolsDelegate::ShellDevToolsDelegate(BrowserContext* browser_context,
-                                             int port)
+ShellDevToolsDelegate::ShellDevToolsDelegate(BrowserContext* browser_context)
     : browser_context_(browser_context) {
-  devtools_http_handler_ = DevToolsHttpHandler::Start(
-#if defined(OS_ANDROID)
-      new net::UnixDomainSocketWithAbstractNamespaceFactory(
-          kSocketName,
-          base::Bind(&CanUserConnectToDevTools)),
-#else
-      new net::TCPListenSocketFactory("127.0.0.1", port),
-#endif
-      "",
-      this);
+  devtools_http_handler_ =
+      DevToolsHttpHandler::Start(CreateSocketFactory(), std::string(), this);
 }
 
 ShellDevToolsDelegate::~ShellDevToolsDelegate() {
@@ -61,7 +85,7 @@
 }
 
 std::string ShellDevToolsDelegate::GetPageThumbnailData(const GURL& url) {
-  return "";
+  return std::string();
 }
 
 RenderViewHost* ShellDevToolsDelegate::CreateNewTarget() {
@@ -80,7 +104,14 @@
 
 std::string ShellDevToolsDelegate::GetViewDescription(
     content::RenderViewHost*) {
-  return "";
+  return std::string();
+}
+
+scoped_refptr<net::StreamListenSocket>
+ShellDevToolsDelegate::CreateSocketForTethering(
+    net::StreamListenSocket::Delegate* delegate,
+    std::string* name) {
+  return NULL;
 }
 
 }  // namespace content
diff --git a/content/shell/shell_devtools_delegate.h b/content/shell/shell_devtools_delegate.h
index 8fda52a..dd4e762 100644
--- a/content/shell/shell_devtools_delegate.h
+++ b/content/shell/shell_devtools_delegate.h
@@ -5,8 +5,6 @@
 #ifndef CONTENT_SHELL_SHELL_DEVTOOLS_DELEGATE_H_
 #define CONTENT_SHELL_SHELL_DEVTOOLS_DELEGATE_H_
 
-#include <vector>
-
 #include "base/basictypes.h"
 #include "base/compiler_specific.h"
 #include "content/public/browser/devtools_http_handler_delegate.h"
@@ -18,7 +16,7 @@
 
 class ShellDevToolsDelegate : public DevToolsHttpHandlerDelegate {
  public:
-  ShellDevToolsDelegate(BrowserContext* browser_context, int port);
+  explicit ShellDevToolsDelegate(BrowserContext* browser_context);
   virtual ~ShellDevToolsDelegate();
 
   // Stops http server.
@@ -32,6 +30,9 @@
   virtual RenderViewHost* CreateNewTarget() OVERRIDE;
   virtual TargetType GetTargetType(RenderViewHost*) OVERRIDE;
   virtual std::string GetViewDescription(content::RenderViewHost*) OVERRIDE;
+  virtual scoped_refptr<net::StreamListenSocket> CreateSocketForTethering(
+      net::StreamListenSocket::Delegate* delegate,
+      std::string* name) OVERRIDE;
 
   DevToolsHttpHandler* devtools_http_handler() {
     return devtools_http_handler_;
diff --git a/content/shell/shell_devtools_frontend.cc b/content/shell/shell_devtools_frontend.cc
index ee78b81..fcb810c 100644
--- a/content/shell/shell_devtools_frontend.cc
+++ b/content/shell/shell_devtools_frontend.cc
@@ -56,11 +56,8 @@
       DevToolsAgentHost::GetOrCreateFor(
           inspected_contents->GetRenderViewHost()));
 
-  ShellContentBrowserClient* browser_client =
-      static_cast<ShellContentBrowserClient*>(
-          GetContentClient()->browser());
-  ShellDevToolsDelegate* delegate =
-      browser_client->shell_browser_main_parts()->devtools_delegate();
+  ShellDevToolsDelegate* delegate = ShellContentBrowserClient::Get()->
+      shell_browser_main_parts()->devtools_delegate();
   if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpRenderTree))
     shell->LoadURL(GetDevToolsPathAsURL());
   else
diff --git a/content/shell/shell_devtools_frontend.h b/content/shell/shell_devtools_frontend.h
index 2308aa3..bee0bd0 100644
--- a/content/shell/shell_devtools_frontend.h
+++ b/content/shell/shell_devtools_frontend.h
@@ -27,6 +27,8 @@
   void Focus();
   void Close();
 
+  Shell* frontend_shell() const { return frontend_shell_; }
+
  private:
   ShellDevToolsFrontend(Shell* frontend_shell, DevToolsAgentHost* agent_host);
   virtual ~ShellDevToolsFrontend();
diff --git a/content/shell/shell_gtk.cc b/content/shell/shell_gtk.cc
index 8d024ce..22d6b33 100644
--- a/content/shell/shell_gtk.cc
+++ b/content/shell/shell_gtk.cc
@@ -8,7 +8,7 @@
 #include <gtk/gtk.h>
 
 #include "base/logging.h"
-#include "base/string_piece.h"
+#include "base/strings/string_piece.h"
 #include "base/utf_string_conversions.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/native_web_keyboard_event.h"
@@ -209,7 +209,7 @@
 void Shell::SizeTo(int width, int height) {
   content_width_ = width;
   content_height_ = height;
-  if (web_contents_.get()) {
+  if (web_contents_) {
     gtk_widget_set_size_request(web_contents_->GetView()->GetNativeView(),
                                 width, height);
   }
@@ -271,8 +271,7 @@
                                       guint keyval,
                                       GdkModifierType modifier) {
   ShellBrowserContext* browser_context =
-      static_cast<ShellContentBrowserClient*>(
-        GetContentClient()->browser())->browser_context();
+      ShellContentBrowserClient::Get()->browser_context();
   Shell::CreateNewWindow(browser_context,
                          GURL(),
                          NULL,
diff --git a/content/shell/shell_javascript_dialog_mac.mm b/content/shell/shell_javascript_dialog_mac.mm
index 920bb66..6bdd9ab 100644
--- a/content/shell/shell_javascript_dialog_mac.mm
+++ b/content/shell/shell_javascript_dialog_mac.mm
@@ -7,7 +7,7 @@
 #import <Cocoa/Cocoa.h>
 
 #import "base/memory/scoped_nsobject.h"
-#include "base/sys_string_conversions.h"
+#include "base/strings/sys_string_conversions.h"
 #include "content/shell/shell_javascript_dialog_manager.h"
 
 // Helper object that receives the notification that the dialog/sheet is
diff --git a/content/shell/shell_javascript_dialog_manager.cc b/content/shell/shell_javascript_dialog_manager.cc
index 17f5b6b..4ef5e2b 100644
--- a/content/shell/shell_javascript_dialog_manager.cc
+++ b/content/shell/shell_javascript_dialog_manager.cc
@@ -46,7 +46,7 @@
 #if defined(OS_MACOSX) || defined(OS_WIN) || defined(TOOLKIT_GTK)
   *did_suppress_message = false;
 
-  if (dialog_.get()) {
+  if (dialog_) {
     // One dialog at a time, please.
     *did_suppress_message = true;
     return;
@@ -89,7 +89,7 @@
   }
 
 #if defined(OS_MACOSX) || defined(OS_WIN) || defined(TOOLKIT_GTK)
-  if (dialog_.get()) {
+  if (dialog_) {
     // Seriously!?
     callback.Run(true, string16());
     return;
@@ -118,7 +118,7 @@
 void ShellJavaScriptDialogManager::ResetJavaScriptState(
     WebContents* web_contents) {
 #if defined(OS_MACOSX) || defined(OS_WIN) || defined(TOOLKIT_GTK)
-  if (dialog_.get()) {
+  if (dialog_) {
     dialog_->Cancel();
     dialog_.reset();
   }
diff --git a/content/shell/shell_login_dialog_mac.mm b/content/shell/shell_login_dialog_mac.mm
index c315644..5a5d4df 100644
--- a/content/shell/shell_login_dialog_mac.mm
+++ b/content/shell/shell_login_dialog_mac.mm
@@ -9,7 +9,7 @@
 #include "base/logging.h"
 #include "base/mac/bundle_locations.h"
 #import "base/memory/scoped_nsobject.h"
-#include "base/sys_string_conversions.h"
+#include "base/strings/sys_string_conversions.h"
 #include "content/public/browser/browser_thread.h"
 #import "ui/base/cocoa/nib_loading.h"
 
diff --git a/content/shell/shell_mac.mm b/content/shell/shell_mac.mm
index e0e7ee7..0e1c582 100644
--- a/content/shell/shell_mac.mm
+++ b/content/shell/shell_mac.mm
@@ -8,8 +8,8 @@
 
 #include "base/logging.h"
 #import "base/memory/scoped_nsobject.h"
-#include "base/string_piece.h"
-#include "base/sys_string_conversions.h"
+#include "base/strings/string_piece.h"
+#include "base/strings/sys_string_conversions.h"
 #include "content/public/browser/native_web_keyboard_event.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_contents_view.h"
diff --git a/content/shell/shell_main_delegate.cc b/content/shell/shell_main_delegate.cc
index e0c5e7f..6981321 100644
--- a/content/shell/shell_main_delegate.cc
+++ b/content/shell/shell_main_delegate.cc
@@ -11,9 +11,9 @@
 #include "content/public/browser/browser_main_runner.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/common/url_constants.h"
+#include "content/shell/renderer/shell_content_renderer_client.h"
 #include "content/shell/shell_browser_main.h"
 #include "content/shell/shell_content_browser_client.h"
-#include "content/shell/shell_content_renderer_client.h"
 #include "content/shell/shell_switches.h"
 #include "content/shell/webkit_test_platform_support.h"
 #include "content/public/test/layouttest_support.h"
@@ -104,10 +104,12 @@
   InitLogging();
   CommandLine& command_line = *CommandLine::ForCurrentProcess();
   if (command_line.HasSwitch(switches::kDumpRenderTree)) {
+    command_line.AppendSwitch(switches::kProcessPerTab);
     command_line.AppendSwitch(switches::kAllowFileAccessFromFiles);
     command_line.AppendSwitchASCII(
         switches::kUseGL, gfx::kGLImplementationOSMesaName);
     SetAllowOSMesaImageTransportForTesting();
+    DisableSystemDragDrop();
     command_line.AppendSwitch(switches::kSkipGpuDataLoading);
     command_line.AppendSwitch(switches::kEnableExperimentalWebKitFeatures);
     command_line.AppendSwitch(switches::kEnableCssShaders);
diff --git a/content/shell/shell_message_filter.cc b/content/shell/shell_message_filter.cc
index 0aff194..cb16871 100644
--- a/content/shell/shell_message_filter.cc
+++ b/content/shell/shell_message_filter.cc
@@ -5,6 +5,7 @@
 #include "content/shell/shell_message_filter.h"
 
 #include "base/file_util.h"
+#include "base/threading/thread_restrictions.h"
 #include "content/public/browser/child_process_security_policy.h"
 #include "content/shell/shell_messages.h"
 #include "content/shell/shell_network_delegate.h"
@@ -51,6 +52,7 @@
 
 void ShellMessageFilter::OnReadFileToString(const base::FilePath& local_file,
                                             std::string* contents) {
+  base::ThreadRestrictions::ScopedAllowIO allow_io;
   file_util::ReadFileToString(local_file, contents);
 }
 
diff --git a/content/shell/shell_messages.h b/content/shell/shell_messages.h
index 5389d96..dde2dda 100644
--- a/content/shell/shell_messages.h
+++ b/content/shell/shell_messages.h
@@ -39,6 +39,10 @@
 IPC_MESSAGE_ROUTED1(ShellViewMsg_SetTestConfiguration,
                     content::ShellTestConfiguration)
 
+// Tells the main window that a secondary window in a different process invoked
+// notifyDone().
+IPC_MESSAGE_ROUTED0(ShellViewMsg_NotifyDone)
+
 // Pushes a snapshot of the current session history from the browser process.
 // This includes only information about those RenderViews that are in the
 // same process as the main window of the layout test and that are the current
@@ -67,9 +71,11 @@
 
 IPC_MESSAGE_ROUTED0(ShellViewHostMsg_ResetDone)
 
+IPC_MESSAGE_ROUTED0(ShellViewHostMsg_TestFinishedInSecondaryWindow)
+
 // WebTestDelegate related.
 IPC_MESSAGE_ROUTED1(ShellViewHostMsg_OverridePreferences,
-                    webkit_glue::WebPreferences /* preferences */)
+                    WebPreferences /* preferences */)
 IPC_SYNC_MESSAGE_ROUTED1_1(ShellViewHostMsg_RegisterIsolatedFileSystem,
                            std::vector<base::FilePath> /* absolute_filenames */,
                            std::string /* filesystem_id */)
diff --git a/content/shell/shell_url_request_context_getter.cc b/content/shell/shell_url_request_context_getter.cc
index e861369..2fa6c39 100644
--- a/content/shell/shell_url_request_context_getter.cc
+++ b/content/shell/shell_url_request_context_getter.cc
@@ -15,7 +15,7 @@
 #include "content/public/common/url_constants.h"
 #include "content/shell/shell_network_delegate.h"
 #include "content/shell/shell_switches.h"
-#include "net/base/cert_verifier.h"
+#include "net/cert/cert_verifier.h"
 #include "net/cookies/cookie_monster.h"
 #include "net/dns/host_resolver.h"
 #include "net/dns/mapped_host_resolver.h"
@@ -56,8 +56,8 @@
 ShellURLRequestContextGetter::ShellURLRequestContextGetter(
     bool ignore_certificate_errors,
     const base::FilePath& base_path,
-    MessageLoop* io_loop,
-    MessageLoop* file_loop,
+    base::MessageLoop* io_loop,
+    base::MessageLoop* file_loop,
     ProtocolHandlerMap* protocol_handlers)
     : ignore_certificate_errors_(ignore_certificate_errors),
       base_path_(base_path),
@@ -84,7 +84,7 @@
 net::URLRequestContext* ShellURLRequestContextGetter::GetURLRequestContext() {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
 
-  if (!url_request_context_.get()) {
+  if (!url_request_context_) {
     const CommandLine& command_line = *CommandLine::ForCurrentProcess();
 
     url_request_context_.reset(new net::URLRequestContext());
diff --git a/content/shell/shell_url_request_context_getter.h b/content/shell/shell_url_request_context_getter.h
index 846c5d3..d7a96b2 100644
--- a/content/shell/shell_url_request_context_getter.h
+++ b/content/shell/shell_url_request_context_getter.h
@@ -13,7 +13,9 @@
 #include "net/url_request/url_request_context_getter.h"
 #include "net/url_request/url_request_job_factory.h"
 
+namespace base {
 class MessageLoop;
+}
 
 namespace net {
 class HostResolver;
@@ -30,8 +32,8 @@
   ShellURLRequestContextGetter(
       bool ignore_certificate_errors,
       const base::FilePath& base_path,
-      MessageLoop* io_loop,
-      MessageLoop* file_loop,
+      base::MessageLoop* io_loop,
+      base::MessageLoop* file_loop,
       ProtocolHandlerMap* protocol_handlers);
 
   // net::URLRequestContextGetter implementation.
@@ -47,8 +49,8 @@
  private:
   bool ignore_certificate_errors_;
   base::FilePath base_path_;
-  MessageLoop* io_loop_;
-  MessageLoop* file_loop_;
+  base::MessageLoop* io_loop_;
+  base::MessageLoop* file_loop_;
 
   scoped_ptr<net::ProxyConfigService> proxy_config_service_;
   scoped_ptr<net::NetworkDelegate> network_delegate_;
diff --git a/content/shell/shell_web_contents_view_delegate_android.cc b/content/shell/shell_web_contents_view_delegate_android.cc
index d222b88..6277a1c 100644
--- a/content/shell/shell_web_contents_view_delegate_android.cc
+++ b/content/shell/shell_web_contents_view_delegate_android.cc
@@ -32,7 +32,7 @@
     ContextMenuSourceType type) {
   if (params.is_editable && params.selection_text.empty()) {
     content::ContentViewCore* content_view_core =
-        web_contents_->GetView()->GetContentNativeView();
+        ContentViewCore::FromWebContents(web_contents_);
     if (content_view_core) {
       content_view_core->ShowPastePopup(params.selection_start.x(),
                                         params.selection_start.y());
diff --git a/content/shell/shell_web_contents_view_delegate_gtk.cc b/content/shell/shell_web_contents_view_delegate_gtk.cc
index cd72e03..ca0a2af 100644
--- a/content/shell/shell_web_contents_view_delegate_gtk.cc
+++ b/content/shell/shell_web_contents_view_delegate_gtk.cc
@@ -211,8 +211,7 @@
 
 void ShellWebContentsViewDelegate::OnOpenURLMenuActivated(GtkWidget* widget) {
   ShellBrowserContext* browser_context =
-      static_cast<ShellContentBrowserClient*>(
-        GetContentClient()->browser())->browser_context();
+      ShellContentBrowserClient::Get()->browser_context();
   Shell::CreateNewWindow(browser_context,
                          params_.link_url,
                          NULL,
diff --git a/content/shell/shell_web_contents_view_delegate_mac.mm b/content/shell/shell_web_contents_view_delegate_mac.mm
index 2460595..32a9aad 100644
--- a/content/shell/shell_web_contents_view_delegate_mac.mm
+++ b/content/shell/shell_web_contents_view_delegate_mac.mm
@@ -237,8 +237,7 @@
       break;
     case ShellContextMenuItemOpenLinkTag: {
       ShellBrowserContext* browser_context =
-          static_cast<ShellContentBrowserClient*>(
-            GetContentClient()->browser())->browser_context();
+          ShellContentBrowserClient::Get()->browser_context();
       Shell::CreateNewWindow(browser_context,
                              params_.link_url,
                              NULL,
diff --git a/content/shell/shell_web_contents_view_delegate_win.cc b/content/shell/shell_web_contents_view_delegate_win.cc
index df400f7..52bc21f 100644
--- a/content/shell/shell_web_contents_view_delegate_win.cc
+++ b/content/shell/shell_web_contents_view_delegate_win.cc
@@ -205,8 +205,7 @@
       break;
     case ShellContextMenuItemOpenLinkId: {
       ShellBrowserContext* browser_context =
-          static_cast<ShellContentBrowserClient*>(
-            GetContentClient()->browser())->browser_context();
+          ShellContentBrowserClient::Get()->browser_context();
       Shell::CreateNewWindow(browser_context,
                              params_.link_url,
                              NULL,
diff --git a/content/shell/webkit_test_controller.cc b/content/shell/webkit_test_controller.cc
index 1f712a8..ab12295 100644
--- a/content/shell/webkit_test_controller.cc
+++ b/content/shell/webkit_test_controller.cc
@@ -22,6 +22,7 @@
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/render_widget_host_view.h"
 #include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_contents_view.h"
 #include "content/shell/shell.h"
 #include "content/shell/shell_browser_context.h"
 #include "content/shell/shell_content_browser_client.h"
@@ -205,9 +206,8 @@
   expected_pixel_hash_ = expected_pixel_hash;
   test_url_ = test_url;
   printer_->reset();
-  content::ShellBrowserContext* browser_context =
-      static_cast<content::ShellContentBrowserClient*>(
-          content::GetContentClient()->browser())->browser_context();
+  ShellBrowserContext* browser_context =
+      ShellContentBrowserClient::Get()->browser_context();
   if (test_url.spec().find("compositing/") != std::string::npos)
     is_compositing_test_ = true;
   gfx::Size initial_size(kTestWindowWidthDip, kTestWindowHeightDip);
@@ -224,6 +224,7 @@
     WebContentsObserver::Observe(main_window_->web_contents());
     send_configuration_to_next_host_ = true;
     current_pid_ = base::kNullProcessId;
+    main_window_->LoadURL(test_url);
   } else {
 #if (defined(OS_WIN) && !defined(USE_AURA)) || defined(TOOLKIT_GTK)
     // Shell::SizeTo is not implemented on all platforms.
@@ -234,23 +235,24 @@
     main_window_->web_contents()->GetRenderViewHost()->WasResized();
     RenderViewHost* render_view_host =
         main_window_->web_contents()->GetRenderViewHost();
-    webkit_glue::WebPreferences prefs =
-        render_view_host->GetWebkitPreferences();
+    WebPreferences prefs = render_view_host->GetWebkitPreferences();
     OverrideWebkitPrefs(&prefs);
     render_view_host->UpdateWebkitPreferences(prefs);
     SendTestConfiguration();
-    registrar_.Add(this,
-                   NOTIFICATION_NAV_ENTRY_PENDING,
-                   Source<NavigationController>(
-                       &main_window_->web_contents()->GetController()));
+
+    NavigationController::LoadURLParams params(test_url);
+    params.transition_type = PageTransitionFromInt(
+        PAGE_TRANSITION_TYPED | PAGE_TRANSITION_FROM_ADDRESS_BAR);
+    params.should_clear_history_list = true;
+    main_window_->web_contents()->GetController().LoadURLWithParams(params);
+    main_window_->web_contents()->GetView()->Focus();
   }
-  main_window_->LoadURL(test_url);
   main_window_->web_contents()->GetRenderViewHost()->SetActive(true);
   main_window_->web_contents()->GetRenderViewHost()->Focus();
   if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kNoTimeout)) {
     watchdog_.Reset(base::Bind(&WebKitTestController::TimeoutHandler,
                                base::Unretained(this)));
-    MessageLoop::current()->PostDelayedTask(
+    base::MessageLoop::current()->PostDelayedTask(
         FROM_HERE,
         watchdog_.callback(),
         base::TimeDelta::FromMilliseconds(kTestTimeoutMilliseconds + 1000));
@@ -268,7 +270,7 @@
   enable_pixel_dumping_ = false;
   expected_pixel_hash_.clear();
   test_url_ = GURL();
-  prefs_ = webkit_glue::WebPreferences();
+  prefs_ = WebPreferences();
   should_override_prefs_ = false;
   watchdog_.Cancel();
   return true;
@@ -280,21 +282,17 @@
 
 void WebKitTestController::RendererUnresponsive() {
   DCHECK(CalledOnValidThread());
-  if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kNoTimeout))
-    return;
-  printer_->AddErrorMessage("#PROCESS UNRESPONSIVE - renderer");
-  DiscardMainWindow();
+  LOG(WARNING) << "renderer unresponsive";
 }
 
-void WebKitTestController::OverrideWebkitPrefs(
-    webkit_glue::WebPreferences* prefs) {
+void WebKitTestController::OverrideWebkitPrefs(WebPreferences* prefs) {
   if (should_override_prefs_) {
     *prefs = prefs_;
   } else {
     ApplyLayoutTestDefaultPreferences(prefs);
     if (is_compositing_test_) {
       CommandLine& command_line = *CommandLine::ForCurrentProcess();
-      if (command_line.HasSwitch(switches::kEnableSoftwareCompositing))
+      if (!command_line.HasSwitch(switches::kEnableSoftwareCompositing))
         prefs->accelerated_2d_canvas_enabled = true;
       prefs->accelerated_compositing_for_video_enabled = true;
       prefs->mock_scrollbars_enabled = true;
@@ -310,6 +308,13 @@
                          gfx::Size());
 }
 
+void WebKitTestController::TestFinishedInSecondaryWindow() {
+  RenderViewHost* render_view_host =
+      main_window_->web_contents()->GetRenderViewHost();
+  render_view_host->Send(
+      new ShellViewMsg_NotifyDone(render_view_host->GetRoutingID()));
+}
+
 bool WebKitTestController::OnMessageReceived(const IPC::Message& message) {
   DCHECK(CalledOnValidThread());
   bool handled = true;
@@ -393,11 +398,6 @@
       current_pid_ = base::GetProcId(render_process_host->GetHandle());
       break;
     }
-    case NOTIFICATION_NAV_ENTRY_PENDING: {
-      registrar_.Remove(this, NOTIFICATION_NAV_ENTRY_PENDING, source);
-      main_window_->web_contents()->GetController().PruneAllButActive();
-      break;
-    }
     default:
       NOTREACHED();
   }
@@ -424,7 +424,8 @@
   WebContentsObserver::Observe(NULL);
   if (is_running_test_) {
     Shell::CloseAllWindows();
-    MessageLoop::current()->PostTask(FROM_HERE, MessageLoop::QuitClosure());
+    base::MessageLoop::current()->PostTask(FROM_HERE,
+                                           base::MessageLoop::QuitClosure());
   } else if (main_window_) {
     main_window_->Close();
   }
@@ -463,7 +464,7 @@
     printer_->PrintImageFooter();
   RenderViewHost* render_view_host =
       main_window_->web_contents()->GetRenderViewHost();
-  MessageLoop::current()->PostTask(
+  base::MessageLoop::current()->PostTask(
       FROM_HERE,
       base::Bind(base::IgnoreResult(&WebKitTestController::Send),
                  base::Unretained(this),
@@ -531,8 +532,7 @@
   printer_->AddMessageRaw(message);
 }
 
-void WebKitTestController::OnOverridePreferences(
-    const webkit_glue::WebPreferences& prefs) {
+void WebKitTestController::OnOverridePreferences(const WebPreferences& prefs) {
   should_override_prefs_ = true;
   prefs_ = prefs;
 }
@@ -609,11 +609,12 @@
     if (open_windows[i] != main_window_)
       open_windows[i]->Close();
   }
-  MessageLoop::current()->RunUntilIdle();
+  base::MessageLoop::current()->RunUntilIdle();
 }
 
 void WebKitTestController::OnResetDone() {
-  MessageLoop::current()->PostTask(FROM_HERE, MessageLoop::QuitClosure());
+  base::MessageLoop::current()->PostTask(FROM_HERE,
+                                         base::MessageLoop::QuitClosure());
 }
 
 }  // namespace content
diff --git a/content/shell/webkit_test_controller.h b/content/shell/webkit_test_controller.h
index 8964f7f..f2e626e 100644
--- a/content/shell/webkit_test_controller.h
+++ b/content/shell/webkit_test_controller.h
@@ -92,8 +92,9 @@
 
   void SetTempPath(const base::FilePath& temp_path);
   void RendererUnresponsive();
-  void OverrideWebkitPrefs(webkit_glue::WebPreferences* prefs);
+  void OverrideWebkitPrefs(WebPreferences* prefs);
   void OpenURL(const GURL& url);
+  void TestFinishedInSecondaryWindow();
 
   WebKitTestResultPrinter* printer() { return printer_.get(); }
   void set_printer(WebKitTestResultPrinter* printer) {
@@ -128,7 +129,7 @@
   void OnImageDump(const std::string& actual_pixel_hash, const SkBitmap& image);
   void OnTextDump(const std::string& dump);
   void OnPrintMessage(const std::string& message);
-  void OnOverridePreferences(const webkit_glue::WebPreferences& prefs);
+  void OnOverridePreferences(const WebPreferences& prefs);
   void OnTestFinished(bool did_timeout);
   void OnShowDevTools();
   void OnCloseDevTools();
@@ -168,7 +169,7 @@
   // True if the WebPreferences of newly created RenderViewHost should be
   // overridden with prefs_.
   bool should_override_prefs_;
-  webkit_glue::WebPreferences prefs_;
+  WebPreferences prefs_;
 
   base::CancelableClosure watchdog_;
 
diff --git a/content/shell/webkit_test_helpers.cc b/content/shell/webkit_test_helpers.cc
index 0a40a22..1bddfcd 100644
--- a/content/shell/webkit_test_helpers.cc
+++ b/content/shell/webkit_test_helpers.cc
@@ -5,25 +5,25 @@
 #include "content/shell/webkit_test_helpers.h"
 
 #include "base/command_line.h"
+#include "base/file_util.h"
+#include "base/path_service.h"
 #include "base/utf_string_conversions.h"
 #include "content/shell/shell_switches.h"
 #include "third_party/WebKit/Tools/DumpRenderTree/chromium/TestRunner/public/WebPreferences.h"
 #include "webkit/glue/webpreferences.h"
 
-using WebTestRunner::WebPreferences;
-
 namespace content {
 
-void ExportLayoutTestSpecificPreferences(const WebPreferences& from,
-                                         webkit_glue::WebPreferences* to) {
+void ExportLayoutTestSpecificPreferences(
+    const WebTestRunner::WebPreferences& from,
+    WebPreferences* to) {
   to->allow_universal_access_from_file_urls =
       from.allowUniversalAccessFromFileURLs;
   to->dom_paste_enabled = from.DOMPasteAllowed;
   to->javascript_can_access_clipboard = from.javaScriptCanAccessClipboard;
   to->xss_auditor_enabled = from.XSSAuditorEnabled;
-  to->editing_behavior =
-      static_cast<webkit_glue::WebPreferences::EditingBehavior>(
-          from.editingBehavior);
+  to->editing_behavior = static_cast<webkit_glue::EditingBehavior>(
+      from.editingBehavior);
   to->default_font_size = from.defaultFontSize;
   to->minimum_font_size = from.minimumFontSize;
   to->default_encoding = from.defaultTextEncodingName.utf8().data();
@@ -32,8 +32,6 @@
   to->loads_images_automatically = from.loadsImagesAutomatically;
   to->plugins_enabled = from.pluginsEnabled;
   to->java_enabled = from.javaEnabled;
-  to->uses_page_cache = from.usesPageCache;
-  to->page_cache_supports_plugins = from.pageCacheSupportsPlugins;
   to->application_cache_enabled = from.offlineWebApplicationCacheEnabled;
   to->tabs_to_links = from.tabsToLinks;
   to->experimental_webgl_enabled = from.experimentalWebGLEnabled;
@@ -58,16 +56,16 @@
 // Applies settings that differ between layout tests and regular mode. Some
 // of the defaults are controlled via command line flags which are
 // automatically set for layout tests.
-void ApplyLayoutTestDefaultPreferences(webkit_glue::WebPreferences* prefs) {
+void ApplyLayoutTestDefaultPreferences(WebPreferences* prefs) {
   CommandLine& command_line = *CommandLine::ForCurrentProcess();
   prefs->allow_universal_access_from_file_urls = true;
   prefs->dom_paste_enabled = true;
   prefs->javascript_can_access_clipboard = true;
   prefs->xss_auditor_enabled = false;
 #if defined(OS_MACOSX)
-  prefs->editing_behavior = webkit_glue::WebPreferences::EDITING_BEHAVIOR_MAC;
+  prefs->editing_behavior = webkit_glue::EDITING_BEHAVIOR_MAC;
 #else
-  prefs->editing_behavior = webkit_glue::WebPreferences::EDITING_BEHAVIOR_WIN;
+  prefs->editing_behavior = webkit_glue::EDITING_BEHAVIOR_WIN;
 #endif
   prefs->java_enabled = false;
   prefs->application_cache_enabled = true;
@@ -78,26 +76,26 @@
   prefs->webgl_errors_to_console_enabled = false;
   string16 serif;
 #if defined(OS_MACOSX)
-  prefs->cursive_font_family_map[webkit_glue::WebPreferences::kCommonScript] =
+  prefs->cursive_font_family_map[webkit_glue::kCommonScript] =
       ASCIIToUTF16("Apple Chancery");
-  prefs->fantasy_font_family_map[webkit_glue::WebPreferences::kCommonScript] =
+  prefs->fantasy_font_family_map[webkit_glue::kCommonScript] =
       ASCIIToUTF16("Papyrus");
   serif = ASCIIToUTF16("Times");
 #else
-  prefs->cursive_font_family_map[webkit_glue::WebPreferences::kCommonScript] =
+  prefs->cursive_font_family_map[webkit_glue::kCommonScript] =
       ASCIIToUTF16("Comic Sans MS");
-  prefs->fantasy_font_family_map[webkit_glue::WebPreferences::kCommonScript] =
+  prefs->fantasy_font_family_map[webkit_glue::kCommonScript] =
       ASCIIToUTF16("Impact");
   serif = ASCIIToUTF16("times new roman");
 #endif
-  prefs->serif_font_family_map[webkit_glue::WebPreferences::kCommonScript] =
+  prefs->serif_font_family_map[webkit_glue::kCommonScript] =
       serif;
-  prefs->standard_font_family_map[webkit_glue::WebPreferences::kCommonScript] =
+  prefs->standard_font_family_map[webkit_glue::kCommonScript] =
       serif;
-  prefs->fixed_font_family_map[webkit_glue::WebPreferences::kCommonScript] =
+  prefs->fixed_font_family_map[webkit_glue::kCommonScript] =
       ASCIIToUTF16("Courier");
   prefs->sans_serif_font_family_map[
-      webkit_glue::WebPreferences::kCommonScript] = ASCIIToUTF16("Helvetica");
+      webkit_glue::kCommonScript] = ASCIIToUTF16("Helvetica");
   prefs->minimum_logical_font_size = 9;
   prefs->asynchronous_spell_checking_enabled = false;
   prefs->user_style_sheet_enabled = true;
@@ -112,4 +110,37 @@
   prefs->minimum_accelerated_2d_canvas_size = 0;
 }
 
+base::FilePath GetWebKitRootDirFilePath() {
+  base::FilePath base_path;
+  PathService::Get(base::DIR_SOURCE_ROOT, &base_path);
+  if (file_util::PathExists(
+          base_path.Append(FILE_PATH_LITERAL("third_party/WebKit")))) {
+    // We're in a WebKit-in-chrome checkout.
+    return base_path.Append(FILE_PATH_LITERAL("third_party/WebKit"));
+  } else if (file_util::PathExists(
+          base_path.Append(FILE_PATH_LITERAL("chromium")))) {
+    // We're in a WebKit-only checkout on Windows.
+    return base_path.Append(FILE_PATH_LITERAL("../.."));
+  } else if (file_util::PathExists(
+          base_path.Append(FILE_PATH_LITERAL("webkit/support")))) {
+    // We're in a WebKit-only/xcodebuild checkout on Mac
+    return base_path.Append(FILE_PATH_LITERAL("../../.."));
+  }
+  // We're in a WebKit-only, make-build, so the DIR_SOURCE_ROOT is already the
+  // WebKit root. That, or we have no idea where we are.
+  return base_path;
+}
+
+base::FilePath GetChromiumRootDirFilePath() {
+  base::FilePath webkit_path = GetWebKitRootDirFilePath();
+  if (file_util::PathExists(webkit_path.Append(
+          FILE_PATH_LITERAL("Source/WebKit/chromium/webkit/support")))) {
+    // We're in a WebKit-only checkout.
+    return webkit_path.Append(FILE_PATH_LITERAL("Source/WebKit/chromium"));
+  } else {
+    // We're in a Chromium checkout, and WebKit is in third_party/WebKit.
+    return webkit_path.Append(FILE_PATH_LITERAL("../.."));
+  }
+}
+
 }  // namespace content
diff --git a/content/shell/webkit_test_helpers.h b/content/shell/webkit_test_helpers.h
index 4cb9626..08ccec8 100644
--- a/content/shell/webkit_test_helpers.h
+++ b/content/shell/webkit_test_helpers.h
@@ -5,25 +5,35 @@
 #ifndef CONTENT_SHELL_WEBKIT_TEST_HELPERS_H_
 #define CONTENT_SHELL_WEBKIT_TEST_HELPERS_H_
 
+struct WebPreferences;
+
 namespace WebTestRunner {
 struct WebPreferences;
 }
 
-namespace webkit_glue {
-struct WebPreferences;
+namespace base {
+class FilePath;
 }
 
+struct WebPreferences;
+
 namespace content {
 
 // The TestRunner library keeps its settings in a WebTestRunner::WebPreferenes
-// object. The content_shell, however, uses webkit_glue::WebPreferences. This
+// object. The content_shell, however, uses WebPreferences. This
 // method exports the settings from the WebTestRunner library which are relevant
 // for layout tests.
 void ExportLayoutTestSpecificPreferences(
-    const WebTestRunner::WebPreferences& from, webkit_glue::WebPreferences* to);
+    const WebTestRunner::WebPreferences& from, WebPreferences* to);
 
 // Applies settings that differ between layout tests and regular mode.
-void ApplyLayoutTestDefaultPreferences(webkit_glue::WebPreferences* prefs);
+void ApplyLayoutTestDefaultPreferences(WebPreferences* prefs);
+
+// Returns the root of the Blink checkout.
+base::FilePath GetWebKitRootDirFilePath();
+
+// Returns the root of the chromium checkout.
+base::FilePath GetChromiumRootDirFilePath();
 
 }  // namespace content
 
diff --git a/content/surface_texture_jni_headers.target.linux-arm.mk b/content/surface_texture_jni_headers.target.linux-arm.mk
deleted file mode 100644
index d650167..0000000
--- a/content/surface_texture_jni_headers.target.linux-arm.mk
+++ /dev/null
@@ -1,140 +0,0 @@
-# This file is generated by gyp; do not edit.
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_CLASS := GYP
-LOCAL_MODULE := content_surface_texture_jni_headers_gyp
-LOCAL_MODULE_STEM := surface_texture_jni_headers
-LOCAL_MODULE_SUFFIX := .stamp
-LOCAL_MODULE_TAGS := optional
-gyp_intermediate_dir := $(call local-intermediates-dir)
-gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
-
-# Make sure our deps are built first.
-GYP_TARGET_DEPENDENCIES :=
-
-### Rules for action "generate_jni_headers_from_jar_file":
-$(gyp_shared_intermediate_dir)/content/jni/SurfaceTexture_jni.h: gyp_local_path := $(LOCAL_PATH)
-$(gyp_shared_intermediate_dir)/content/jni/SurfaceTexture_jni.h: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
-$(gyp_shared_intermediate_dir)/content/jni/SurfaceTexture_jni.h: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
-$(gyp_shared_intermediate_dir)/content/jni/SurfaceTexture_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
-$(gyp_shared_intermediate_dir)/content/jni/SurfaceTexture_jni.h: $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(GYP_ABS_ANDROID_TOP_DIR)/prebuilts/sdk/17/android.jar $(GYP_TARGET_DEPENDENCIES)
-	@echo "Gyp action: Generating JNI bindings from  $(GYP_ABS_ANDROID_TOP_DIR)/prebuilts/sdk/17/android.jar/android/graphics/SurfaceTexture.class ($@)"
-	$(hide)cd $(gyp_local_path)/content; mkdir -p $(gyp_shared_intermediate_dir)/content/jni; ../base/android/jni_generator/jni_generator.py -j "$(GYP_ABS_ANDROID_TOP_DIR)/prebuilts/sdk/17/android.jar" --input_file android/graphics/SurfaceTexture.class --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --optimize_generation 0
-
-
-
-GYP_GENERATED_OUTPUTS := \
-	$(gyp_shared_intermediate_dir)/content/jni/SurfaceTexture_jni.h
-
-# Make sure our deps and generated files are built first.
-LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
-
-LOCAL_GENERATED_SOURCES := \
-	$(gyp_shared_intermediate_dir)/content/jni/SurfaceTexture_jni.h
-
-GYP_COPIED_SOURCE_ORIGIN_DIRS :=
-
-LOCAL_SRC_FILES :=
-
-
-# Flags passed to both C and C++ files.
-MY_CFLAGS := \
-	-fstack-protector \
-	--param=ssp-buffer-size=4 \
-	-Werror \
-	-fno-exceptions \
-	-fno-strict-aliasing \
-	-Wall \
-	-Wno-unused-parameter \
-	-Wno-missing-field-initializers \
-	-fvisibility=hidden \
-	-pipe \
-	-fPIC \
-	-fno-tree-sra \
-	-fuse-ld=gold \
-	-Wno-psabi \
-	-ffunction-sections \
-	-funwind-tables \
-	-g \
-	-fstack-protector \
-	-fno-short-enums \
-	-finline-limit=64 \
-	-Wa,--noexecstack \
-	-U_FORTIFY_SOURCE \
-	-Wno-extra \
-	-Wno-ignored-qualifiers \
-	-Wno-type-limits \
-	-Os \
-	-g \
-	-fomit-frame-pointer \
-	-fdata-sections \
-	-ffunction-sections
-
-MY_CFLAGS_C :=
-
-MY_DEFS := \
-	'-DCONTENT_IMPLEMENTATION' \
-	'-DUSE_SKIA' \
-	'-D_FILE_OFFSET_BITS=64' \
-	'-DUSE_LINUX_BREAKPAD' \
-	'-DNO_TCMALLOC' \
-	'-DDISABLE_NACL' \
-	'-DCHROMIUM_BUILD' \
-	'-DUSE_LIBJPEG_TURBO=1' \
-	'-DUSE_PROPRIETARY_CODECS' \
-	'-DENABLE_PEPPER_THREADING' \
-	'-DENABLE_GPU=1' \
-	'-DUSE_OPENSSL=1' \
-	'-DENABLE_EGLIMAGE=1' \
-	'-DENABLE_LANGUAGE_DETECTION=1' \
-	'-D__STDC_CONSTANT_MACROS' \
-	'-D__STDC_FORMAT_MACROS' \
-	'-DANDROID' \
-	'-D__GNU_SOURCE=1' \
-	'-DUSE_STLPORT=1' \
-	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
-	'-DCHROME_BUILD_ID=""' \
-	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
-	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
-	'-D_DEBUG'
-
-LOCAL_CFLAGS := $(MY_CFLAGS_C) $(MY_CFLAGS) $(MY_DEFS)
-
-# Include paths placed before CFLAGS/CPPFLAGS
-LOCAL_C_INCLUDES := \
-	$(GYP_ABS_ANDROID_TOP_DIR)/frameworks/wilhelm/include \
-	$(GYP_ABS_ANDROID_TOP_DIR)/bionic \
-	$(GYP_ABS_ANDROID_TOP_DIR)/external/stlport/stlport
-
-LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES)
-
-# Flags passed to only C++ (and not C) files.
-LOCAL_CPPFLAGS := \
-	-fno-rtti \
-	-fno-threadsafe-statics \
-	-fvisibility-inlines-hidden \
-	-Wsign-compare \
-	-Wno-abi \
-	-Wno-error=c++0x-compat \
-	-Wno-non-virtual-dtor \
-	-Wno-sign-promo
-
-### Rules for final target.
-# Add target alias to "gyp_all_modules" target.
-.PHONY: gyp_all_modules
-gyp_all_modules: content_surface_texture_jni_headers_gyp
-
-# Alias gyp target name.
-.PHONY: surface_texture_jni_headers
-surface_texture_jni_headers: content_surface_texture_jni_headers_gyp
-
-LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
-LOCAL_UNINSTALLABLE_MODULE := true
-
-include $(BUILD_SYSTEM)/base_rules.mk
-
-$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
-	$(hide) echo "Gyp timestamp: $@"
-	$(hide) mkdir -p $(dir $@)
-	$(hide) touch $@
diff --git a/content/surface_texture_jni_headers.target.linux-x86.mk b/content/surface_texture_jni_headers.target.linux-x86.mk
deleted file mode 100644
index d4b7c87..0000000
--- a/content/surface_texture_jni_headers.target.linux-x86.mk
+++ /dev/null
@@ -1,140 +0,0 @@
-# This file is generated by gyp; do not edit.
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_CLASS := GYP
-LOCAL_MODULE := content_surface_texture_jni_headers_gyp
-LOCAL_MODULE_STEM := surface_texture_jni_headers
-LOCAL_MODULE_SUFFIX := .stamp
-LOCAL_MODULE_TAGS := optional
-gyp_intermediate_dir := $(call local-intermediates-dir)
-gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
-
-# Make sure our deps are built first.
-GYP_TARGET_DEPENDENCIES :=
-
-### Rules for action "generate_jni_headers_from_jar_file":
-$(gyp_shared_intermediate_dir)/content/jni/SurfaceTexture_jni.h: gyp_local_path := $(LOCAL_PATH)
-$(gyp_shared_intermediate_dir)/content/jni/SurfaceTexture_jni.h: gyp_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)
-$(gyp_shared_intermediate_dir)/content/jni/SurfaceTexture_jni.h: gyp_shared_intermediate_dir := $(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)
-$(gyp_shared_intermediate_dir)/content/jni/SurfaceTexture_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
-$(gyp_shared_intermediate_dir)/content/jni/SurfaceTexture_jni.h: $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(GYP_ABS_ANDROID_TOP_DIR)/prebuilts/sdk/17/android.jar $(GYP_TARGET_DEPENDENCIES)
-	@echo "Gyp action: Generating JNI bindings from  $(GYP_ABS_ANDROID_TOP_DIR)/prebuilts/sdk/17/android.jar/android/graphics/SurfaceTexture.class ($@)"
-	$(hide)cd $(gyp_local_path)/content; mkdir -p $(gyp_shared_intermediate_dir)/content/jni; ../base/android/jni_generator/jni_generator.py -j "$(GYP_ABS_ANDROID_TOP_DIR)/prebuilts/sdk/17/android.jar" --input_file android/graphics/SurfaceTexture.class --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --optimize_generation 0
-
-
-
-GYP_GENERATED_OUTPUTS := \
-	$(gyp_shared_intermediate_dir)/content/jni/SurfaceTexture_jni.h
-
-# Make sure our deps and generated files are built first.
-LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
-
-LOCAL_GENERATED_SOURCES := \
-	$(gyp_shared_intermediate_dir)/content/jni/SurfaceTexture_jni.h
-
-GYP_COPIED_SOURCE_ORIGIN_DIRS :=
-
-LOCAL_SRC_FILES :=
-
-
-# Flags passed to both C and C++ files.
-MY_CFLAGS := \
-	--param=ssp-buffer-size=4 \
-	-Werror \
-	-fno-exceptions \
-	-fno-strict-aliasing \
-	-Wall \
-	-Wno-unused-parameter \
-	-Wno-missing-field-initializers \
-	-fvisibility=hidden \
-	-pipe \
-	-fPIC \
-	-m32 \
-	-mmmx \
-	-march=pentium4 \
-	-msse2 \
-	-mfpmath=sse \
-	-ffunction-sections \
-	-funwind-tables \
-	-g \
-	-fno-short-enums \
-	-finline-limit=64 \
-	-Wa,--noexecstack \
-	-U_FORTIFY_SOURCE \
-	-Wno-extra \
-	-Wno-ignored-qualifiers \
-	-Wno-type-limits \
-	-fno-stack-protector \
-	-Os \
-	-g \
-	-fomit-frame-pointer \
-	-fdata-sections \
-	-ffunction-sections
-
-MY_CFLAGS_C :=
-
-MY_DEFS := \
-	'-DCONTENT_IMPLEMENTATION' \
-	'-DUSE_SKIA' \
-	'-D_FILE_OFFSET_BITS=64' \
-	'-DUSE_LINUX_BREAKPAD' \
-	'-DNO_TCMALLOC' \
-	'-DDISABLE_NACL' \
-	'-DCHROMIUM_BUILD' \
-	'-DUSE_LIBJPEG_TURBO=1' \
-	'-DUSE_PROPRIETARY_CODECS' \
-	'-DENABLE_PEPPER_THREADING' \
-	'-DENABLE_GPU=1' \
-	'-DUSE_OPENSSL=1' \
-	'-DENABLE_EGLIMAGE=1' \
-	'-DENABLE_LANGUAGE_DETECTION=1' \
-	'-D__STDC_CONSTANT_MACROS' \
-	'-D__STDC_FORMAT_MACROS' \
-	'-DANDROID' \
-	'-D__GNU_SOURCE=1' \
-	'-DUSE_STLPORT=1' \
-	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
-	'-DCHROME_BUILD_ID=""' \
-	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
-	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
-	'-D_DEBUG'
-
-LOCAL_CFLAGS := $(MY_CFLAGS_C) $(MY_CFLAGS) $(MY_DEFS)
-
-# Include paths placed before CFLAGS/CPPFLAGS
-LOCAL_C_INCLUDES := \
-	$(GYP_ABS_ANDROID_TOP_DIR)/frameworks/wilhelm/include \
-	$(GYP_ABS_ANDROID_TOP_DIR)/bionic \
-	$(GYP_ABS_ANDROID_TOP_DIR)/external/stlport/stlport
-
-LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES)
-
-# Flags passed to only C++ (and not C) files.
-LOCAL_CPPFLAGS := \
-	-fno-rtti \
-	-fno-threadsafe-statics \
-	-fvisibility-inlines-hidden \
-	-Wsign-compare \
-	-Wno-error=c++0x-compat \
-	-Wno-non-virtual-dtor \
-	-Wno-sign-promo
-
-### Rules for final target.
-# Add target alias to "gyp_all_modules" target.
-.PHONY: gyp_all_modules
-gyp_all_modules: content_surface_texture_jni_headers_gyp
-
-# Alias gyp target name.
-.PHONY: surface_texture_jni_headers
-surface_texture_jni_headers: content_surface_texture_jni_headers_gyp
-
-LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
-LOCAL_UNINSTALLABLE_MODULE := true
-
-include $(BUILD_SYSTEM)/base_rules.mk
-
-$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
-	$(hide) echo "Gyp timestamp: $@"
-	$(hide) mkdir -p $(dir $@)
-	$(hide) touch $@
diff --git a/content/test/browser_test_message_pump_android.cc b/content/test/browser_test_message_pump_android.cc
index b20b491..f992110 100644
--- a/content/test/browser_test_message_pump_android.cc
+++ b/content/test/browser_test_message_pump_android.cc
@@ -56,7 +56,6 @@
   RunState state(delegate, state_ ? state_->run_depth + 1 : 1);
   RunState* previous_state = state_;
   state_ = &state;
-  DCHECK(state_->run_depth <= 1) << "Only one level nested loops supported";
 
   JNIEnv* env = base::android::AttachCurrentThread();
   DCHECK(env);
diff --git a/content/test/content_browser_test.cc b/content/test/content_browser_test.cc
index aa91303..bcaa587 100644
--- a/content/test/content_browser_test.cc
+++ b/content/test/content_browser_test.cc
@@ -12,10 +12,10 @@
 #include "content/public/browser/render_process_host.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/common/url_constants.h"
+#include "content/shell/renderer/shell_content_renderer_client.h"
 #include "content/shell/shell.h"
 #include "content/shell/shell_browser_context.h"
 #include "content/shell/shell_content_browser_client.h"
-#include "content/shell/shell_content_renderer_client.h"
 #include "content/shell/shell_main_delegate.h"
 #include "content/shell/shell_switches.h"
 #include "content/test/test_content_client.h"
@@ -60,8 +60,7 @@
   // and set up renderer.
   if (command_line->HasSwitch(switches::kSingleProcess)) {
     single_process_renderer_client_.reset(new ShellContentRendererClient);
-    GetContentClient()->set_renderer_for_testing(
-        single_process_renderer_client_.get());
+    SetRendererClientForTesting(single_process_renderer_client_.get());
   }
 
 #if defined(OS_MACOSX)
@@ -109,7 +108,7 @@
 #endif
 
   // Pump startup related events.
-  MessageLoopForUI::current()->RunUntilIdle();
+  base::MessageLoopForUI::current()->RunUntilIdle();
 
 #if defined(OS_MACOSX)
   pool.Recycle();
@@ -131,10 +130,8 @@
 }
 
 Shell* ContentBrowserTest::CreateBrowser() {
-  ShellContentBrowserClient* browser_client =
-      static_cast<ShellContentBrowserClient*>(GetContentClient()->browser());
   return Shell::CreateNewWindow(
-      browser_client->browser_context(),
+      ShellContentBrowserClient::Get()->browser_context(),
       GURL(chrome::kAboutBlankURL),
       NULL,
       MSG_ROUTING_NONE,
@@ -142,10 +139,8 @@
 }
 
 Shell* ContentBrowserTest::CreateOffTheRecordBrowser() {
-  ShellContentBrowserClient* browser_client =
-      static_cast<ShellContentBrowserClient*>(GetContentClient()->browser());
   return Shell::CreateNewWindow(
-      browser_client->off_the_record_browser_context(),
+      ShellContentBrowserClient::Get()->off_the_record_browser_context(),
       GURL(chrome::kAboutBlankURL),
       NULL,
       MSG_ROUTING_NONE,
diff --git a/content/test/content_test_launcher.cc b/content/test/content_test_launcher.cc
index aa1f362..ae26552 100644
--- a/content/test/content_test_launcher.cc
+++ b/content/test/content_test_launcher.cc
@@ -36,15 +36,13 @@
   }
 
   virtual void OnTestStart(const testing::TestInfo& test_info) OVERRIDE {
-    DCHECK(!GetContentClient());
     content_client_.reset(new ShellContentClient);
     browser_content_client_.reset(new ShellContentBrowserClient());
-    content_client_->set_browser_for_testing(browser_content_client_.get());
     SetContentClient(content_client_.get());
+    SetBrowserClientForTesting(browser_content_client_.get());
   }
 
   virtual void OnTestEnd(const testing::TestInfo& test_info) OVERRIDE {
-    DCHECK_EQ(content_client_.get(), GetContentClient());
     browser_content_client_.reset();
     content_client_.reset();
     SetContentClient(NULL);
@@ -77,7 +75,8 @@
 #if defined(OS_ANDROID)
     // This needs to be done before base::TestSuite::Initialize() is called,
     // as it also tries to set MessagePumpForUIFactory.
-    if (!MessageLoop::InitMessagePumpForUIFactory(&CreateMessagePumpForUI))
+    if (!base::MessageLoop::InitMessagePumpForUIFactory(
+            &CreateMessagePumpForUI))
       LOG(INFO) << "MessagePumpForUIFactory already set, unable to override.";
 #endif
 
diff --git a/content/test/data/accessibility/a-expected-mac.txt b/content/test/data/accessibility/a-expected-mac.txt
index 27da7da..2a7792a 100644
--- a/content/test/data/accessibility/a-expected-mac.txt
+++ b/content/test/data/accessibility/a-expected-mac.txt
@@ -1,4 +1,4 @@
 AXWebArea
     AXGroup
-        AXLink title='normal link'
-            AXStaticText value='normal link'
+        AXLink AXTitle='normal link'
+            AXStaticText AXValue='normal link'
diff --git a/content/test/data/accessibility/a-with-img-expected-mac.txt b/content/test/data/accessibility/a-with-img-expected-mac.txt
index b4261da..37db67f 100644
--- a/content/test/data/accessibility/a-with-img-expected-mac.txt
+++ b/content/test/data/accessibility/a-with-img-expected-mac.txt
@@ -1,16 +1,16 @@
 AXWebArea
     AXGroup
-        AXLink title='Link with image at start.'
-            AXImage description='Link'
-            AXStaticText value=' with image at start.'
-        AXLink title='Link with image in the middle.'
-            AXStaticText value='Link with '
-            AXImage description='image'
-            AXStaticText value=' in the middle.'
-        AXLink title='Link with broken in the middle.'
-            AXStaticText value='Link with '
-            AXImage description='broken'
-            AXStaticText value=' in the middle.'
-        AXLink title='Link with image at the end'
-            AXStaticText value='Link with image at the '
-            AXImage description='end'
+        AXLink AXTitle='Link with image at start.'
+            AXImage AXDescription='Link'
+            AXStaticText AXValue=' with image at start.'
+        AXLink AXTitle='Link with image in the middle.'
+            AXStaticText AXValue='Link with '
+            AXImage AXDescription='image'
+            AXStaticText AXValue=' in the middle.'
+        AXLink AXTitle='Link with broken in the middle.'
+            AXStaticText AXValue='Link with '
+            AXImage AXDescription='broken'
+            AXStaticText AXValue=' in the middle.'
+        AXLink AXTitle='Link with image at the end'
+            AXStaticText AXValue='Link with image at the '
+            AXImage AXDescription='end'
diff --git a/content/test/data/accessibility/a-with-img.html b/content/test/data/accessibility/a-with-img.html
index f090da8..daeede6 100644
--- a/content/test/data/accessibility/a-with-img.html
+++ b/content/test/data/accessibility/a-with-img.html
@@ -1,5 +1,5 @@
 <!--
-@MAC-ALLOW:description*
+@MAC-ALLOW:AXDescription*
 -->
 <html>
 <body>
diff --git a/content/test/data/accessibility/address-expected-mac.txt b/content/test/data/accessibility/address-expected-mac.txt
index 23b45b2..3a129b2 100644
--- a/content/test/data/accessibility/address-expected-mac.txt
+++ b/content/test/data/accessibility/address-expected-mac.txt
@@ -1,4 +1,4 @@
 #<skip -- wrong roleDescription (bug)>
-AXWebArea subrole=(null) roleDescription='HTML content'
-    AXGroup subrole=AXLandmarkContentInfo roleDescription='address'
-        AXStaticText subrole=(null) roleDescription='text' value='Please contact John Citizen for more information.'
+AXWebArea AXRoleDescription='HTML content'
+    AXGroup AXSubrole=AXLandmarkContentInfo AXRoleDescription='group'
+        AXStaticText AXRoleDescription='text' AXValue='Please contact John Citizen for more information.'
diff --git a/content/test/data/accessibility/address.html b/content/test/data/accessibility/address.html
index 2082cd9..a78bf41 100644
--- a/content/test/data/accessibility/address.html
+++ b/content/test/data/accessibility/address.html
@@ -1,6 +1,6 @@
 <!--
-@MAC-ALLOW:subrole=*
-@MAC-ALLOW:roleDescription=*
+@MAC-ALLOW:AXSubrole=*
+@MAC-ALLOW:AXRoleDescription=*
 @WIN-ALLOW:role:*
 @WIN-ALLOW:xml-role*
 -->
diff --git a/content/test/data/accessibility/aria-application-expected-mac.txt b/content/test/data/accessibility/aria-application-expected-mac.txt
index f8e11fb..febaff7 100644
--- a/content/test/data/accessibility/aria-application-expected-mac.txt
+++ b/content/test/data/accessibility/aria-application-expected-mac.txt
@@ -1,2 +1,2 @@
 AXWebArea
-    AXGroup subrole=AXLandmarkApplication roleDescription='application'
+    AXGroup AXSubrole=AXLandmarkApplication AXRoleDescription='application'
diff --git a/content/test/data/accessibility/aria-application.html b/content/test/data/accessibility/aria-application.html
index 6c59998..445ab95 100644
--- a/content/test/data/accessibility/aria-application.html
+++ b/content/test/data/accessibility/aria-application.html
@@ -1,6 +1,6 @@
 <!--
-@MAC-ALLOW:roleDescription='application'
-@MAC-ALLOW:subrole*
+@MAC-ALLOW:AXRoleDescription='application'
+@MAC-ALLOW:AXSubrole*
 -->
 <html>
 <body role="application" id="testAriaApplication">
diff --git a/content/test/data/accessibility/aria-combobox-expected-mac.txt b/content/test/data/accessibility/aria-combobox-expected-mac.txt
index 6f2ef42..6fc5996 100644
--- a/content/test/data/accessibility/aria-combobox-expected-mac.txt
+++ b/content/test/data/accessibility/aria-combobox-expected-mac.txt
@@ -1,7 +1,7 @@
 AXWebArea
     AXGroup
-        AXStaticText value='State'
+        AXStaticText AXValue='State'
         AXComboBox
     AXList
-        AXStaticText title='Alabama'
-        AXStaticText title='Alaska'
+        AXStaticText AXTitle='Alabama'
+        AXStaticText AXTitle='Alaska'
diff --git a/content/test/data/accessibility/aria-invalid-expected-mac.txt b/content/test/data/accessibility/aria-invalid-expected-mac.txt
index 5b3db34..daa90ed 100644
--- a/content/test/data/accessibility/aria-invalid-expected-mac.txt
+++ b/content/test/data/accessibility/aria-invalid-expected-mac.txt
@@ -1,13 +1,13 @@
 AXWebArea
-    AXGroup invalid='true'
-        AXStaticText value='invalid=true'
-    AXGroup invalid='spelling'
-        AXStaticText value='invalid=spelling'
-    AXGroup invalid='grammar'
-        AXStaticText value='invalid=grammar'
-    AXGroup invalid='false'
-        AXStaticText value='invalid=false'
-    AXGroup invalid='false'
-        AXStaticText value='invalid=<empty>'
-    AXGroup invalid='somethingelse'
-        AXStaticText value='invalid=somethingelse'
+    AXGroup AXInvalid='true'
+        AXStaticText AXValue='invalid=true'
+    AXGroup AXInvalid='spelling'
+        AXStaticText AXValue='invalid=spelling'
+    AXGroup AXInvalid='grammar'
+        AXStaticText AXValue='invalid=grammar'
+    AXGroup AXInvalid='false'
+        AXStaticText AXValue='invalid=false'
+    AXGroup AXInvalid='false'
+        AXStaticText AXValue='invalid=<empty>'
+    AXGroup AXInvalid='somethingelse'
+        AXStaticText AXValue='invalid=somethingelse'
diff --git a/content/test/data/accessibility/aria-invalid.html b/content/test/data/accessibility/aria-invalid.html
index 80d86cc..fcacee2 100644
--- a/content/test/data/accessibility/aria-invalid.html
+++ b/content/test/data/accessibility/aria-invalid.html
@@ -1,5 +1,5 @@
 <!--
-@MAC-ALLOW:invalid=*
+@MAC-ALLOW:AXInvalid=*
 @WIN-ALLOW:checkable:*
 @WIN-DENY:name=''
 -->
diff --git a/content/test/data/accessibility/aria-level-expected-mac.txt b/content/test/data/accessibility/aria-level-expected-mac.txt
index 2879b99..43fccc3 100644
--- a/content/test/data/accessibility/aria-level-expected-mac.txt
+++ b/content/test/data/accessibility/aria-level-expected-mac.txt
@@ -1,21 +1,21 @@
 AXWebArea
-    AXHeading title='H3' value='3'
-        AXStaticText value='H3'
-    AXHeading title='ARIA heading level 3' value='3'
-        AXStaticText value='ARIA heading level 3'
+    AXHeading AXTitle='H3' AXValue='3'
+        AXStaticText AXValue='H3'
+    AXHeading AXTitle='ARIA heading level 3' AXValue='3'
+        AXStaticText AXValue='ARIA heading level 3'
     AXOutline
-        AXRow subrole=AXOutlineRow disclosing='1' disclosureLevel='0'
-            AXStaticText value='Tree item at level 1'
-            AXRow subrole=AXOutlineRow disclosing='0' disclosureLevel='1'
-                AXStaticText value='Tree item at level 2'
-        AXRow subrole=AXOutlineRow disclosing='0' disclosureLevel='2'
-            AXStaticText value='Tree item at level 3'
+        AXRow AXSubrole=AXOutlineRow AXDisclosing='1' AXDisclosureLevel='0'
+            AXStaticText AXValue='Tree item at level 1'
+            AXRow AXSubrole=AXOutlineRow AXDisclosing='0' AXDisclosureLevel='1'
+                AXStaticText AXValue='Tree item at level 2'
+        AXRow AXSubrole=AXOutlineRow AXDisclosing='0' AXDisclosureLevel='2'
+            AXStaticText AXValue='Tree item at level 3'
     AXTable
-        AXRow disclosureLevel='0'
+        AXRow AXDisclosureLevel='0'
             AXCell
-                AXStaticText value='Cell at level 1'
-        AXRow disclosureLevel='1'
+                AXStaticText AXValue='Cell at level 1'
+        AXRow AXDisclosureLevel='1'
             AXCell
-                AXStaticText value='Cell at level 2'
+                AXStaticText AXValue='Cell at level 2'
         AXColumn
         AXGroup
diff --git a/content/test/data/accessibility/aria-level.html b/content/test/data/accessibility/aria-level.html
index 56240ff..94df22d 100644
--- a/content/test/data/accessibility/aria-level.html
+++ b/content/test/data/accessibility/aria-level.html
@@ -1,8 +1,8 @@
 <!doctype html>
 <!--
-@MAC-ALLOW:subrole=AXOutlineRow
-@MAC-ALLOW:disclosing*
-@MAC-ALLOW:disclosureLevel*
+@MAC-ALLOW:AXSubrole=AXOutlineRow
+@MAC-ALLOW:AXDisclosing*
+@MAC-ALLOW:AXDisclosureLevel*
 @WIN-ALLOW:level:1
 @WIN-ALLOW:level:2
 @WIN-ALLOW:level:3
diff --git a/content/test/data/accessibility/aria-menu-expected-mac.txt b/content/test/data/accessibility/aria-menu-expected-mac.txt
index 021e959..570809e 100644
--- a/content/test/data/accessibility/aria-menu-expected-mac.txt
+++ b/content/test/data/accessibility/aria-menu-expected-mac.txt
@@ -1,10 +1,10 @@
 AXWebArea
     AXMenuBar
-        AXMenuItem title='File'
-        AXMenuItem title='Edit'
-        AXMenuItem title='View'
-    AXMenu description='File'
-        AXMenuItem title='New'
-        AXMenuItem title='Open'
-        AXMenuItem title='Save'
-        AXMenuItem title='Quit'
+        AXMenuItem AXTitle='File'
+        AXMenuItem AXTitle='Edit'
+        AXMenuItem AXTitle='View'
+    AXMenu AXDescription='File'
+        AXMenuItem AXTitle='New'
+        AXMenuItem AXTitle='Open'
+        AXMenuItem AXTitle='Save'
+        AXMenuItem AXTitle='Quit'
diff --git a/content/test/data/accessibility/aria-menu.html b/content/test/data/accessibility/aria-menu.html
index c729d82..1fd7ebb 100644
--- a/content/test/data/accessibility/aria-menu.html
+++ b/content/test/data/accessibility/aria-menu.html
@@ -1,6 +1,6 @@
 <!--
-@MAC-ALLOW:description='File'
-@MAC-DENY:value*
+@MAC-ALLOW:AXDescription='File'
+@MAC-DENY:AXValue*
 @WIN-DENY:description=''
 -->
 <html>
diff --git a/content/test/data/accessibility/aria-menuitemradio-expected-mac.txt b/content/test/data/accessibility/aria-menuitemradio-expected-mac.txt
index b475e71..1f4295c 100644
--- a/content/test/data/accessibility/aria-menuitemradio-expected-mac.txt
+++ b/content/test/data/accessibility/aria-menuitemradio-expected-mac.txt
@@ -1,9 +1,9 @@
 #<skip - role should be AXMenuItem. http://crbug.com/169578
        - role description should be 'menu item'. http://crbug.com/169580
        - AXMenuItemMarkChar should be \236. http://crbug.com/169582>
-AXWebArea roleDescription='HTML content'
-    AXMenu roleDescription='menu'
-        AXMenuItem roleDescription='menu item' AXMenuItemMarkChar='\236'
-            AXStaticText roleDescription='text' value='Menu item 1'
-        AXMenuItem roleDescription='menu item' AXMenuItemMarkChar='(null)'
-            AXStaticText roleDescription='text' value='Menu item 2'
+AXWebArea AXRoleDescription='HTML content'
+    AXMenu AXRoleDescription='menu'
+        AXGroup AXRoleDescription='aria-menuitemradio'
+            AXStaticText AXRoleDescription='text' AXValue='Menu item 1'
+        AXGroup AXRoleDescription='aria-menuitemradio'
+            AXStaticText AXRoleDescription='text' AXValue='Menu item 2'
diff --git a/content/test/data/accessibility/aria-menuitemradio.html b/content/test/data/accessibility/aria-menuitemradio.html
index d5292ff..4e096c1 100644
--- a/content/test/data/accessibility/aria-menuitemradio.html
+++ b/content/test/data/accessibility/aria-menuitemradio.html
@@ -1,5 +1,5 @@
 <!--
-@MAC-ALLOW:roleDescription=*
+@MAC-ALLOW:AXRoleDescription=*
 @WIN-ALLOW:checkable:*
 @WIN-DENY:name=''
 -->
diff --git a/content/test/data/accessibility/aria-pressed-expected-mac.txt b/content/test/data/accessibility/aria-pressed-expected-mac.txt
index 6ca8346..c5ab71d 100644
--- a/content/test/data/accessibility/aria-pressed-expected-mac.txt
+++ b/content/test/data/accessibility/aria-pressed-expected-mac.txt
@@ -1,5 +1,5 @@
 AXWebArea
-    AXButton title='Regular button'
-    AXButton title='Toggle button unpressed'
-    AXButton title='Toggle button pressed'
-    AXButton title='Toggle button mixed'
+    AXButton AXTitle='Regular button'
+    AXButton AXTitle='Toggle button unpressed'
+    AXButton AXTitle='Toggle button pressed'
+    AXButton AXTitle='Toggle button mixed'
diff --git a/content/test/data/accessibility/aria-progressbar-expected-mac.txt b/content/test/data/accessibility/aria-progressbar-expected-mac.txt
index 7e7da6e..a3329cb 100644
--- a/content/test/data/accessibility/aria-progressbar-expected-mac.txt
+++ b/content/test/data/accessibility/aria-progressbar-expected-mac.txt
@@ -1,3 +1,3 @@
-AXWebArea roleDescription='HTML content'
-    AXProgressIndicator roleDescription='progress indicator' value='3' minValue='1' maxValue='37'
-    AXProgressIndicator roleDescription='progress indicator' value='0' minValue='1' maxValue='96' valueDescription='three'
+AXWebArea AXRoleDescription='HTML content'
+    AXProgressIndicator AXRoleDescription='progress indicator' AXValue='3' AXMinValue='1' AXMaxValue='37'
+    AXProgressIndicator AXRoleDescription='progress indicator' AXValue='0' AXMinValue='1' AXMaxValue='96' AXValueDescription='three'
diff --git a/content/test/data/accessibility/aria-progressbar.html b/content/test/data/accessibility/aria-progressbar.html
index 3f888ee..3c3f350 100644
--- a/content/test/data/accessibility/aria-progressbar.html
+++ b/content/test/data/accessibility/aria-progressbar.html
@@ -1,8 +1,8 @@
 <!--
-@MAC-ALLOW:roleDescription=*
-@MAC-ALLOW:valueDescription=*
-@MAC-ALLOW:minValue=*
-@MAC-ALLOW:maxValue=*
+@MAC-ALLOW:AXRoleDescription=*
+@MAC-ALLOW:AXValueDescription=*
+@MAC-ALLOW:AXMinValue=*
+@MAC-ALLOW:AXMaxValue=*
 @WIN-ALLOW:READONLY
 @WIN-ALLOW:STATE_SYSTEM_READONLY
 @WIN-ALLOW:valuetext:*
diff --git a/content/test/data/accessibility/aria-valuemax-expected-mac.txt b/content/test/data/accessibility/aria-valuemax-expected-mac.txt
index ce04ee5..2914a44 100644
--- a/content/test/data/accessibility/aria-valuemax-expected-mac.txt
+++ b/content/test/data/accessibility/aria-valuemax-expected-mac.txt
@@ -1,5 +1,5 @@
 AXWebArea
-    AXProgressIndicator value='51' maxValue='101'
-    AXScrollBar value='52' maxValue='102'
-    AXSlider value='53' maxValue='103'
-    AXSlider value='54' maxValue='104'
+    AXProgressIndicator AXValue='51' AXMaxValue='101'
+    AXScrollBar AXValue='52' AXMaxValue='102'
+    AXSlider AXValue='53' AXMaxValue='103'
+    AXSlider AXValue='54' AXMaxValue='104'
diff --git a/content/test/data/accessibility/aria-valuemax.html b/content/test/data/accessibility/aria-valuemax.html
index d894018..d4c23d9 100644
--- a/content/test/data/accessibility/aria-valuemax.html
+++ b/content/test/data/accessibility/aria-valuemax.html
@@ -1,7 +1,7 @@
 <!doctype html>
 <!--
-@MAC-ALLOW:maxValue=*
-@MAC-DENY:title*
+@MAC-ALLOW:AXMaxValue=*
+@MAC-DENY:AXTitle*
 @WIN-ALLOW:maximumValue=*
 @WIN-DENY:description=''
 -->
diff --git a/content/test/data/accessibility/aria-valuemin-expected-mac.txt b/content/test/data/accessibility/aria-valuemin-expected-mac.txt
index 74824b1..a348f78 100644
--- a/content/test/data/accessibility/aria-valuemin-expected-mac.txt
+++ b/content/test/data/accessibility/aria-valuemin-expected-mac.txt
@@ -1,5 +1,5 @@
 AXWebArea
-    AXProgressIndicator minValue='1'
-    AXScrollBar minValue='2'
-    AXSlider minValue='3'
-    AXSlider minValue='4'
+    AXProgressIndicator AXMinValue='1'
+    AXScrollBar AXMinValue='2'
+    AXSlider AXMinValue='3'
+    AXSlider AXMinValue='4'
diff --git a/content/test/data/accessibility/aria-valuemin.html b/content/test/data/accessibility/aria-valuemin.html
index d4df6e1..0352c01 100644
--- a/content/test/data/accessibility/aria-valuemin.html
+++ b/content/test/data/accessibility/aria-valuemin.html
@@ -1,8 +1,8 @@
 <!doctype html>
 <!--
-@MAC-ALLOW:minValue=*
-@MAC-DENY:title*
-@MAC-DENY:value*
+@MAC-ALLOW:AXMinValue=*
+@MAC-DENY:AXTitle*
+@MAC-DENY:AXValue*
 @WIN-ALLOW:minimumValue=*
 @WIN-DENY:description=''
 -->
diff --git a/content/test/data/accessibility/article-expected-mac.txt b/content/test/data/accessibility/article-expected-mac.txt
index 2d07907..8f0006d 100644
--- a/content/test/data/accessibility/article-expected-mac.txt
+++ b/content/test/data/accessibility/article-expected-mac.txt
@@ -1,3 +1,3 @@
 AXWebArea
-    AXGroup subrole=AXDocumentArticle
-        AXStaticText value='This is an article.'
+    AXGroup AXSubrole=AXDocumentArticle
+        AXStaticText AXValue='This is an article.'
diff --git a/content/test/data/accessibility/article.html b/content/test/data/accessibility/article.html
index 49f7b08..6abc7b6 100644
--- a/content/test/data/accessibility/article.html
+++ b/content/test/data/accessibility/article.html
@@ -1,6 +1,6 @@
 <!--
-@MAC-ALLOW:subrole=AXDocumentArticle
-@MAC-DENY:title*
+@MAC-ALLOW:AXSubrole=AXDocumentArticle
+@MAC-DENY:AXTitle*
 @WIN-ALLOW:xml-roles:article
 -->
 <!doctype html>
diff --git a/content/test/data/accessibility/bdo-expected-mac.txt b/content/test/data/accessibility/bdo-expected-mac.txt
index d5c29c8..2473176 100644
--- a/content/test/data/accessibility/bdo-expected-mac.txt
+++ b/content/test/data/accessibility/bdo-expected-mac.txt
@@ -2,6 +2,6 @@
 # wrong, so we assume this is correct.
 AXWebArea
     AXGroup
-        AXStaticText value='Some LTR text'
-        AXStaticText value='Some RTL text '
-        AXStaticText value='with some LTR text embedded'
+        AXStaticText AXValue='Some LTR text'
+        AXStaticText AXValue='Some RTL text '
+        AXStaticText AXValue='with some LTR text embedded'
diff --git a/content/test/data/accessibility/bdo.html b/content/test/data/accessibility/bdo.html
index dc64edf..4b679f2 100644
--- a/content/test/data/accessibility/bdo.html
+++ b/content/test/data/accessibility/bdo.html
@@ -1,5 +1,5 @@
 <!--
-@MAC_ALLOW:subrole=*
+@MAC_ALLOW:AXSubrole=*
 @WIN_ALLOW:*
 -->
 <html>
diff --git a/content/test/data/accessibility/br-expected-mac.txt b/content/test/data/accessibility/br-expected-mac.txt
index 06846de..9fa5426 100644
--- a/content/test/data/accessibility/br-expected-mac.txt
+++ b/content/test/data/accessibility/br-expected-mac.txt
@@ -1,4 +1,4 @@
 AXWebArea
     AXGroup
-        AXStaticText value='Text line 1 '
-        AXStaticText value='Text line 2'
+        AXStaticText AXValue='Text line 1 '
+        AXStaticText AXValue='Text line 2'
diff --git a/content/test/data/accessibility/button-name-calc-expected-mac.txt b/content/test/data/accessibility/button-name-calc-expected-mac.txt
index 952c013..75c006e 100644
--- a/content/test/data/accessibility/button-name-calc-expected-mac.txt
+++ b/content/test/data/accessibility/button-name-calc-expected-mac.txt
@@ -1,8 +1,8 @@
 AXWebArea
     AXGroup
-        AXButton title='InnerText0'
-        AXButton title='InnerText1' help='Title1'
-        AXButton title='InnerText2' description='AriaLabel2' help='Title2'
-        AXButton title='InnerText3' description='LabelledBy3' help='Title3'
-        AXButton title='InnerText4' description='LabelledBy4' help='DescribedBy4'
-        AXButton title='InnerText5' help='DescribedBy5'
+        AXButton AXTitle='InnerText0'
+        AXButton AXTitle='InnerText1' AXHelp='Title1'
+        AXButton AXTitle='InnerText2' AXDescription='AriaLabel2' AXHelp='Title2'
+        AXButton AXTitle='InnerText3' AXDescription='LabelledBy3' AXHelp='Title3'
+        AXButton AXTitle='InnerText4' AXDescription='LabelledBy4' AXHelp='DescribedBy4'
+        AXButton AXTitle='InnerText5' AXHelp='DescribedBy5'
diff --git a/content/test/data/accessibility/button-name-calc.html b/content/test/data/accessibility/button-name-calc.html
index c9d3778..4eace79 100644
--- a/content/test/data/accessibility/button-name-calc.html
+++ b/content/test/data/accessibility/button-name-calc.html
@@ -1,8 +1,8 @@
 <!--
 @WIN-ALLOW:description*
-@MAC-ALLOW:description*
-@MAC-ALLOW:help*
-@MAC-DENY:value*
+@MAC-ALLOW:AXDescription*
+@MAC-ALLOW:AXHelp*
+@MAC-DENY:AXValue*
 -->
 <html>
 <body>
diff --git a/content/test/data/accessibility/canvas-expected-mac.txt b/content/test/data/accessibility/canvas-expected-mac.txt
index 411c22f..d184251 100644
--- a/content/test/data/accessibility/canvas-expected-mac.txt
+++ b/content/test/data/accessibility/canvas-expected-mac.txt
@@ -1,7 +1,7 @@
 AXWebArea
     AXGroup
         AXImage
-            AXStaticText value='Static fallback'
+            AXStaticText AXValue='Static fallback'
         AXGroup
-            AXLink title='Interactive fallback'
-                AXStaticText value='Interactive fallback'
+            AXLink AXTitle='Interactive fallback'
+                AXStaticText AXValue='Interactive fallback'
diff --git a/content/test/data/accessibility/checkbox-name-calc-expected-mac.txt b/content/test/data/accessibility/checkbox-name-calc-expected-mac.txt
index 192dbc0..f8d9d09 100644
--- a/content/test/data/accessibility/checkbox-name-calc-expected-mac.txt
+++ b/content/test/data/accessibility/checkbox-name-calc-expected-mac.txt
@@ -1,8 +1,8 @@
 AXWebArea
     AXGroup
-        AXCheckBox description='Title0'
-        AXCheckBox title='Label1' help='Title1'
-        AXCheckBox description='AriaLabel2' help='Title2'
-        AXCheckBox description='LabelledBy3' help='Title3'
-        AXCheckBox description='LabelledBy4' help='DescribedBy4'
-        AXCheckBox help='DescribedBy5'
+        AXCheckBox AXDescription='Title0'
+        AXCheckBox AXTitle='Label1' AXHelp='Title1'
+        AXCheckBox AXDescription='AriaLabel2' AXHelp='Title2'
+        AXCheckBox AXDescription='LabelledBy3' AXHelp='Title3'
+        AXCheckBox AXDescription='LabelledBy4' AXHelp='DescribedBy4'
+        AXCheckBox AXHelp='DescribedBy5'
diff --git a/content/test/data/accessibility/checkbox-name-calc.html b/content/test/data/accessibility/checkbox-name-calc.html
index c6bf76a..c9aa59f 100644
--- a/content/test/data/accessibility/checkbox-name-calc.html
+++ b/content/test/data/accessibility/checkbox-name-calc.html
@@ -1,8 +1,8 @@
 <!--
 @WIN-ALLOW:description*
-@MAC-ALLOW:description*
-@MAC-ALLOW:help*
-@MAC-DENY:value*
+@MAC-ALLOW:AXDescription*
+@MAC-ALLOW:AXHelp*
+@MAC-DENY:AXValue*
 -->
 <html>
 <body>
diff --git a/content/test/data/accessibility/div-expected-mac.txt b/content/test/data/accessibility/div-expected-mac.txt
index d3ddd33..db92d6d 100644
--- a/content/test/data/accessibility/div-expected-mac.txt
+++ b/content/test/data/accessibility/div-expected-mac.txt
@@ -1,3 +1,3 @@
 AXWebArea
-    AXGroup title='Focusable div'
-        AXStaticText value='Focusable div'
+    AXGroup AXTitle='Focusable div'
+        AXStaticText AXValue='Focusable div'
diff --git a/content/test/data/accessibility/dl-expected-mac.txt b/content/test/data/accessibility/dl-expected-mac.txt
index 607ac4e..0fdb7ba 100644
--- a/content/test/data/accessibility/dl-expected-mac.txt
+++ b/content/test/data/accessibility/dl-expected-mac.txt
@@ -1,8 +1,8 @@
 AXWebArea
-    AXList subrole=AXDescriptionList
-        AXGroup subrole=AXTerm
-            AXStaticText value='Term'
-        AXGroup subrole=AXDescription
-            AXStaticText value='Description'
-    AXGroup subrole=AXDefinition
-        AXStaticText value='Definition'
+    AXList AXSubrole=AXDescriptionList
+        AXGroup AXSubrole=AXTerm
+            AXStaticText AXValue='Term'
+        AXGroup AXSubrole=AXDescription
+            AXStaticText AXValue='Description'
+    AXGroup AXSubrole=AXDefinition
+        AXStaticText AXValue='Definition'
diff --git a/content/test/data/accessibility/dl.html b/content/test/data/accessibility/dl.html
index 1e029f4..85e2601 100644
--- a/content/test/data/accessibility/dl.html
+++ b/content/test/data/accessibility/dl.html
@@ -1,6 +1,6 @@
 <!doctype html>
 <!--
-@MAC-ALLOW:subrole*
+@MAC-ALLOW:AXSubrole*
 -->
 <html>
 <body>
diff --git a/content/test/data/accessibility/em-expected-mac.txt b/content/test/data/accessibility/em-expected-mac.txt
index dd3c675..b6f59f5 100644
--- a/content/test/data/accessibility/em-expected-mac.txt
+++ b/content/test/data/accessibility/em-expected-mac.txt
@@ -1,5 +1,5 @@
 AXWebArea
     AXGroup
-        AXStaticText value='One word is '
-        AXStaticText value='emphasized'
-        AXStaticText value='.'
+        AXStaticText AXValue='One word is '
+        AXStaticText AXValue='emphasized'
+        AXStaticText AXValue='.'
diff --git a/content/test/data/accessibility/footer-expected-mac.txt b/content/test/data/accessibility/footer-expected-mac.txt
index 2147226..c104310 100644
--- a/content/test/data/accessibility/footer-expected-mac.txt
+++ b/content/test/data/accessibility/footer-expected-mac.txt
@@ -1,3 +1,3 @@
 AXWebArea
-    AXGroup subrole=AXLandmarkContentInfo roleDescription='footer'
-        AXStaticText value='Footer element'
+    AXGroup AXSubrole=AXLandmarkContentInfo AXRoleDescription='footer'
+        AXStaticText AXValue='Footer element'
diff --git a/content/test/data/accessibility/footer.html b/content/test/data/accessibility/footer.html
index 5996b5c..16d7044 100644
--- a/content/test/data/accessibility/footer.html
+++ b/content/test/data/accessibility/footer.html
@@ -1,6 +1,6 @@
 <!--
-@MAC-ALLOW:roleDescription='footer'
-@MAC-ALLOW:subrole*
+@MAC-ALLOW:AXRoleDescription='footer'
+@MAC-ALLOW:AXSubrole*
 -->
 <html>
 <body>
diff --git a/content/test/data/accessibility/form-expected-mac.txt b/content/test/data/accessibility/form-expected-mac.txt
index 9e7b4f7..5f7bb3a 100644
--- a/content/test/data/accessibility/form-expected-mac.txt
+++ b/content/test/data/accessibility/form-expected-mac.txt
@@ -1,3 +1,3 @@
 AXWebArea
     AXGroup
-        AXButton title='Submit'
+        AXButton AXTitle='Submit'
diff --git a/content/test/data/accessibility/heading-expected-mac.txt b/content/test/data/accessibility/heading-expected-mac.txt
index 41ea300..caeaa19 100644
--- a/content/test/data/accessibility/heading-expected-mac.txt
+++ b/content/test/data/accessibility/heading-expected-mac.txt
@@ -1,25 +1,25 @@
 AXWebArea
-    AXHeading title='Heading 1' value='1'
-        AXStaticText value='Heading 1'
-    AXHeading title='Heading 2' value='2'
-        AXStaticText value='Heading 2'
-    AXHeading title='Heading 3' value='3'
-        AXStaticText value='Heading 3'
-    AXHeading title='Heading 4' value='4'
-        AXStaticText value='Heading 4'
-    AXHeading title='Heading 5' value='5'
-        AXStaticText value='Heading 5'
-    AXHeading title='Heading 6' value='6'
-        AXStaticText value='Heading 6'
-    AXHeading title='ARIA Heading 1' value='1'
-        AXStaticText value='ARIA Heading 1'
-    AXHeading title='ARIA Heading 2' value='2'
-        AXStaticText value='ARIA Heading 2'
-    AXHeading title='ARIA Heading 3' value='3'
-        AXStaticText value='ARIA Heading 3'
-    AXHeading title='ARIA Heading 4' value='4'
-        AXStaticText value='ARIA Heading 4'
-    AXHeading title='ARIA Heading 5' value='5'
-        AXStaticText value='ARIA Heading 5'
-    AXHeading title='ARIA Heading 6' value='6'
-        AXStaticText value='ARIA Heading 6'
+    AXHeading AXTitle='Heading 1' AXValue='1'
+        AXStaticText AXValue='Heading 1'
+    AXHeading AXTitle='Heading 2' AXValue='2'
+        AXStaticText AXValue='Heading 2'
+    AXHeading AXTitle='Heading 3' AXValue='3'
+        AXStaticText AXValue='Heading 3'
+    AXHeading AXTitle='Heading 4' AXValue='4'
+        AXStaticText AXValue='Heading 4'
+    AXHeading AXTitle='Heading 5' AXValue='5'
+        AXStaticText AXValue='Heading 5'
+    AXHeading AXTitle='Heading 6' AXValue='6'
+        AXStaticText AXValue='Heading 6'
+    AXHeading AXTitle='ARIA Heading 1' AXValue='1'
+        AXStaticText AXValue='ARIA Heading 1'
+    AXHeading AXTitle='ARIA Heading 2' AXValue='2'
+        AXStaticText AXValue='ARIA Heading 2'
+    AXHeading AXTitle='ARIA Heading 3' AXValue='3'
+        AXStaticText AXValue='ARIA Heading 3'
+    AXHeading AXTitle='ARIA Heading 4' AXValue='4'
+        AXStaticText AXValue='ARIA Heading 4'
+    AXHeading AXTitle='ARIA Heading 5' AXValue='5'
+        AXStaticText AXValue='ARIA Heading 5'
+    AXHeading AXTitle='ARIA Heading 6' AXValue='6'
+        AXStaticText AXValue='ARIA Heading 6'
diff --git a/content/test/data/accessibility/iframe-coordinates-expected-mac.txt b/content/test/data/accessibility/iframe-coordinates-expected-mac.txt
deleted file mode 100644
index 9f2a91a..0000000
--- a/content/test/data/accessibility/iframe-coordinates-expected-mac.txt
+++ /dev/null
@@ -1,19 +0,0 @@
-AXWebArea position=(0, 0) size=(800, 600)
-    AXGroup position=(0, 0) size=(300, 150)
-        AXButton position=(25, 25) size=(250, 50)
-    AXGroup position=(0, 150) size=(300, 150)
-        AXButton position=(25, 175) size=(250, 50)
-    AXGroup position=(0, 300) size=(300, 150)
-        AXUnknown position=(0, 300) size=(300, 100)
-            AXUnknown position=(0, 0) size=(0, 0)
-                AXWebArea position=(0, 300) size=(300, 100)
-                    AXGroup position=(0, 300) size=(300, 100)
-                        AXButton position=(25, 325) size=(250, 50)
-    AXGroup position=(0, 450) size=(300, 150)
-        AXUnknown position=(0, 450) size=(150, 50)
-            AXUnknown position=(0, 0) size=(0, 0)
-                AXWebArea position=(0, 450) size=(300, 100)
-                    AXGroup position=(-150, 400) size=(300, 100)
-                        AXButton position=(-125, 425) size=(250, 50)
-                AXScrollBar position=(0, 0) size=(0, 0)
-                AXScrollBar position=(0, 0) size=(0, 0)
diff --git a/content/test/data/accessibility/iframe-coordinates.html b/content/test/data/accessibility/iframe-coordinates.html
index 1c1711b..0a9e958 100644
--- a/content/test/data/accessibility/iframe-coordinates.html
+++ b/content/test/data/accessibility/iframe-coordinates.html
@@ -1,7 +1,7 @@
 <!doctype html>
 <!--
-@MAC-DENY:title*
-@MAC-DENY:value*
+@MAC-DENY:AXTitle*
+@MAC-DENY:AXValue*
 @MAC-ALLOW:position*
 @MAC-ALLOW:size*
 
diff --git a/content/test/data/accessibility/input-button-expected-mac.txt b/content/test/data/accessibility/input-button-expected-mac.txt
index 4d52ae1..4b4ddba 100644
--- a/content/test/data/accessibility/input-button-expected-mac.txt
+++ b/content/test/data/accessibility/input-button-expected-mac.txt
@@ -1,3 +1,3 @@
 AXWebArea
     AXGroup
-        AXButton title='Button'
+        AXButton AXTitle='Button'
diff --git a/content/test/data/accessibility/input-button.html b/content/test/data/accessibility/input-button.html
index 3ac815e..14b6e84 100644
--- a/content/test/data/accessibility/input-button.html
+++ b/content/test/data/accessibility/input-button.html
@@ -1,6 +1,6 @@
 <!doctype html>
 <!--
-@MAC-DENY:value*
+@MAC-DENY:AXValue*
 -->
 <html>
   <body>
diff --git a/content/test/data/accessibility/input-color-expected-mac.txt b/content/test/data/accessibility/input-color-expected-mac.txt
index ecfb7a0..4c426aa 100644
--- a/content/test/data/accessibility/input-color-expected-mac.txt
+++ b/content/test/data/accessibility/input-color-expected-mac.txt
@@ -1,3 +1,3 @@
 AXWebArea
     AXGroup
-        AXColorWell value='rgb 1.00000 0.60000 0.00000 1'
+        AXColorWell AXValue='rgb 1.00000 0.60000 0.00000 1'
diff --git a/content/test/data/accessibility/input-color.html b/content/test/data/accessibility/input-color.html
index d2832cc..f6e1eca 100644
--- a/content/test/data/accessibility/input-color.html
+++ b/content/test/data/accessibility/input-color.html
@@ -1,6 +1,6 @@
 <!doctype html>
 <!--
-@MAC-DENY:title*
+@MAC-DENY:AXTitle*
 @WIN-ALLOW:value*
 @WIN-DENY:value='file://*
 -->
diff --git a/content/test/data/accessibility/input-range-expected-mac.txt b/content/test/data/accessibility/input-range-expected-mac.txt
index 2d9c3e8..366f98e 100644
--- a/content/test/data/accessibility/input-range-expected-mac.txt
+++ b/content/test/data/accessibility/input-range-expected-mac.txt
@@ -1,3 +1,3 @@
 AXWebArea
     AXGroup
-        AXSlider value='5'
+        AXSlider AXValue='5'
diff --git a/content/test/data/accessibility/label-expected-mac.txt b/content/test/data/accessibility/label-expected-mac.txt
index 120d0a8..ecbf184 100644
--- a/content/test/data/accessibility/label-expected-mac.txt
+++ b/content/test/data/accessibility/label-expected-mac.txt
@@ -1,4 +1,4 @@
 AXWebArea
     AXGroup
         AXGroup
-            AXStaticText value='Label'
+            AXStaticText AXValue='Label'
diff --git a/content/test/data/accessibility/list-markers-expected-mac.txt b/content/test/data/accessibility/list-markers-expected-mac.txt
index fb55b8c..064c829 100644
--- a/content/test/data/accessibility/list-markers-expected-mac.txt
+++ b/content/test/data/accessibility/list-markers-expected-mac.txt
@@ -1,17 +1,17 @@
 AXWebArea
-    AXList subrole=AXContentList
+    AXList AXSubrole=AXContentList
         AXGroup
-            AXListMarker value='•'
-            AXStaticText value='First item properly groups itself despite '
-            AXStaticText value='bolded'
-            AXStaticText value=' text.'
+            AXListMarker AXValue='•'
+            AXStaticText AXValue='First item properly groups itself despite '
+            AXStaticText AXValue='bolded'
+            AXStaticText AXValue=' text.'
         AXGroup
-            AXListMarker value='•'
-            AXStaticText value='This should also be '
-            AXStaticText value='seen'
-            AXStaticText value=' as a group.'
+            AXListMarker AXValue='•'
+            AXStaticText AXValue='This should also be '
+            AXStaticText AXValue='seen'
+            AXStaticText AXValue=' as a group.'
         AXGroup
-            AXListMarker value='•'
-            AXStaticText value='Some '
-            AXStaticText value='more'
-            AXStaticText value=' text.'
+            AXListMarker AXValue='•'
+            AXStaticText AXValue='Some '
+            AXStaticText AXValue='more'
+            AXStaticText AXValue=' text.'
diff --git a/content/test/data/accessibility/list-markers.html b/content/test/data/accessibility/list-markers.html
index 6a92bfd..edba4c6 100644
--- a/content/test/data/accessibility/list-markers.html
+++ b/content/test/data/accessibility/list-markers.html
@@ -1,5 +1,5 @@
 <!--
-@MAC-ALLOW:subrole*
+@MAC-ALLOW:AXSubrole*
 -->
 <html>
   <body>
diff --git a/content/test/data/accessibility/p-expected-mac.txt b/content/test/data/accessibility/p-expected-mac.txt
index 53ebca6..5429233 100644
--- a/content/test/data/accessibility/p-expected-mac.txt
+++ b/content/test/data/accessibility/p-expected-mac.txt
@@ -1,7 +1,7 @@
 AXWebArea
     AXGroup
-        AXStaticText value='Before'
+        AXStaticText AXValue='Before'
     AXGroup
-        AXStaticText value='Paragraph'
+        AXStaticText AXValue='Paragraph'
     AXGroup
-        AXStaticText value='After'
+        AXStaticText AXValue='After'
diff --git a/content/test/data/accessibility/select-expected-mac.txt b/content/test/data/accessibility/select-expected-mac.txt
index 117da80..ed7fc5d 100644
--- a/content/test/data/accessibility/select-expected-mac.txt
+++ b/content/test/data/accessibility/select-expected-mac.txt
@@ -1,17 +1,17 @@
-AXWebArea roleDescription='HTML content'
-    AXGroup roleDescription='group'
-        AXPopUpButton roleDescription='pop up button' value='Placeholder option'
-            AXUnknown roleDescription='unknown'
-                AXMenuItem roleDescription='menu item' value='Placeholder option'
-                AXMenuItem roleDescription='menu item' value='Option 1'
-                AXMenuItem roleDescription='menu item' value='Option 2'
-        AXPopUpButton roleDescription='pop up button' value='Option 2'
-            AXUnknown roleDescription='unknown'
-                AXMenuItem roleDescription='menu item' value='Option 1'
-                AXMenuItem roleDescription='menu item' value='Option 2'
-                AXMenuItem roleDescription='menu item' value='Option 3'
-        AXPopUpButton roleDescription='pop up button' value='Option 1'
-            AXUnknown roleDescription='unknown'
-                AXMenuItem roleDescription='menu item' value='Option 1'
-                AXMenuItem roleDescription='menu item' value='Option 2'
-                AXMenuItem roleDescription='menu item' value='Option 3'
+AXWebArea AXRoleDescription='HTML content'
+    AXGroup AXRoleDescription='group'
+        AXPopUpButton AXRoleDescription='pop up button' AXValue='Placeholder option'
+            AXUnknown AXRoleDescription='unknown'
+                AXMenuItem AXRoleDescription='menu item' AXValue='Placeholder option'
+                AXMenuItem AXRoleDescription='menu item' AXValue='Option 1'
+                AXMenuItem AXRoleDescription='menu item' AXValue='Option 2'
+        AXPopUpButton AXRoleDescription='pop up button' AXValue='Option 2'
+            AXUnknown AXRoleDescription='unknown'
+                AXMenuItem AXRoleDescription='menu item' AXValue='Option 1'
+                AXMenuItem AXRoleDescription='menu item' AXValue='Option 2'
+                AXMenuItem AXRoleDescription='menu item' AXValue='Option 3'
+        AXPopUpButton AXRoleDescription='pop up button' AXValue='Option 1'
+            AXUnknown AXRoleDescription='unknown'
+                AXMenuItem AXRoleDescription='menu item' AXValue='Option 1'
+                AXMenuItem AXRoleDescription='menu item' AXValue='Option 2'
+                AXMenuItem AXRoleDescription='menu item' AXValue='Option 3'
diff --git a/content/test/data/accessibility/select.html b/content/test/data/accessibility/select.html
index 7699486..c699247 100644
--- a/content/test/data/accessibility/select.html
+++ b/content/test/data/accessibility/select.html
@@ -1,5 +1,5 @@
 <!--
-@MAC-ALLOW:roleDescription=*
+@MAC-ALLOW:AXRoleDescription=*
 -->
 <html>
 <body>
diff --git a/content/test/data/accessibility/span-expected-mac.txt b/content/test/data/accessibility/span-expected-mac.txt
index 8bc3a10..8078c2a 100644
--- a/content/test/data/accessibility/span-expected-mac.txt
+++ b/content/test/data/accessibility/span-expected-mac.txt
@@ -1,5 +1,5 @@
 AXWebArea
     AXGroup
-        AXStaticText value='This paragraph has one '
-        AXStaticText value='word'
-        AXStaticText value=' in a span.'
+        AXStaticText AXValue='This paragraph has one '
+        AXStaticText AXValue='word'
+        AXStaticText AXValue=' in a span.'
diff --git a/content/test/data/accessibility/span.html b/content/test/data/accessibility/span.html
index 3dcf6a0..0609636 100644
--- a/content/test/data/accessibility/span.html
+++ b/content/test/data/accessibility/span.html
@@ -1,5 +1,5 @@
 <!--
-@MAC-DENY:title*
+@MAC-DENY:AXTitle*
 -->
 <!doctype html>
 <html>
diff --git a/content/test/data/accessibility/spinbutton-expected-mac.txt b/content/test/data/accessibility/spinbutton-expected-mac.txt
index c017dc4..ef75729 100644
--- a/content/test/data/accessibility/spinbutton-expected-mac.txt
+++ b/content/test/data/accessibility/spinbutton-expected-mac.txt
@@ -1,2 +1,2 @@
-AXWebArea roleDescription='HTML content'
-    AXSlider roleDescription='stepper' value='5'
+AXWebArea AXRoleDescription='HTML content'
+    AXSlider AXRoleDescription='stepper' AXValue='5'
diff --git a/content/test/data/accessibility/spinbutton.html b/content/test/data/accessibility/spinbutton.html
index 6978d68..fd2d494 100644
--- a/content/test/data/accessibility/spinbutton.html
+++ b/content/test/data/accessibility/spinbutton.html
@@ -1,5 +1,5 @@
 <!--
-@MAC-ALLOW:roleDescription*
+@MAC-ALLOW:AXRoleDescription*
 -->
 <html>
 <body>
diff --git a/content/test/data/accessibility/svg-expected-mac.txt b/content/test/data/accessibility/svg-expected-mac.txt
index eb2adbe..1352fa8 100644
--- a/content/test/data/accessibility/svg-expected-mac.txt
+++ b/content/test/data/accessibility/svg-expected-mac.txt
@@ -1,5 +1,5 @@
 AXWebArea
     AXGroup
-        AXGroup description='svg'
-            AXGroup title='Test'
-                AXStaticText value='Test'
+        AXGroup AXDescription='svg'
+            AXGroup AXTitle='Test'
+                AXStaticText AXValue='Test'
diff --git a/content/test/data/accessibility/svg.html b/content/test/data/accessibility/svg.html
index 446cd98..1b7a175 100644
--- a/content/test/data/accessibility/svg.html
+++ b/content/test/data/accessibility/svg.html
@@ -1,5 +1,5 @@
 <!--
-@MAC-ALLOW:description='svg'
+@MAC-ALLOW:AXDescription='svg'
 -->
 <!doctype html>
 <html>
diff --git a/content/test/data/accessibility/tab-expected-mac.txt b/content/test/data/accessibility/tab-expected-mac.txt
index dc69430..b76698e 100644
--- a/content/test/data/accessibility/tab-expected-mac.txt
+++ b/content/test/data/accessibility/tab-expected-mac.txt
@@ -1,4 +1,4 @@
 AXWebArea
     AXTabGroup
-        AXRadioButton title='Tab 1' value='0'
-        AXRadioButton title='Tab 2' value='0'
+        AXRadioButton AXTitle='Tab 1' AXValue='0'
+        AXRadioButton AXTitle='Tab 2' AXValue='0'
diff --git a/content/test/data/accessibility/table-simple-expected-mac.txt b/content/test/data/accessibility/table-simple-expected-mac.txt
new file mode 100644
index 0000000..798e4c7
--- /dev/null
+++ b/content/test/data/accessibility/table-simple-expected-mac.txt
@@ -0,0 +1,20 @@
+AXWebArea AXTitle='Table example'
+    AXTable
+        AXRow AXIndex='0'
+            AXCell AXColumnIndexRange={"len":1,"loc":0} AXRowIndexRange={"len":1,"loc":0}
+                AXStaticText AXValue='A'
+            AXCell AXColumnIndexRange={"len":1,"loc":1} AXRowIndexRange={"len":1,"loc":0}
+                AXStaticText AXValue='B'
+            AXCell AXColumnIndexRange={"len":1,"loc":2} AXRowIndexRange={"len":1,"loc":0}
+                AXStaticText AXValue='C'
+        AXRow AXIndex='1'
+            AXCell AXColumnIndexRange={"len":1,"loc":0} AXRowIndexRange={"len":1,"loc":1}
+                AXStaticText AXValue='D'
+            AXCell AXColumnIndexRange={"len":1,"loc":1} AXRowIndexRange={"len":1,"loc":1}
+                AXStaticText AXValue='E'
+            AXCell AXColumnIndexRange={"len":1,"loc":2} AXRowIndexRange={"len":1,"loc":1}
+                AXStaticText AXValue='F'
+        AXColumn AXIndex='0'
+        AXColumn AXIndex='1'
+        AXColumn AXIndex='2'
+        AXGroup
diff --git a/content/test/data/accessibility/table-simple-expected-win.txt b/content/test/data/accessibility/table-simple-expected-win.txt
new file mode 100644
index 0000000..839b7a2
--- /dev/null
+++ b/content/test/data/accessibility/table-simple-expected-win.txt
@@ -0,0 +1 @@
+#<skip - we don't dump table attrs on win yet>
diff --git a/content/test/data/accessibility/table-simple.html b/content/test/data/accessibility/table-simple.html
new file mode 100644
index 0000000..9bfbbf8
--- /dev/null
+++ b/content/test/data/accessibility/table-simple.html
@@ -0,0 +1,27 @@
+<!doctype html>
+<!--
+@MAC-ALLOW:AXIndex=*
+@MAC-ALLOW:AXColumnIndexRange=*
+@MAC-ALLOW:AXRowIndexRange=*
+-->
+<html>
+<head>
+  <title>Table example</title>
+</head>
+<body>
+
+<table border=1>
+  <tr>
+    <td>A</td>
+    <td>B</td>
+    <td>C</td>
+  </tr>
+  <tr>
+    <td>D</td>
+    <td>E</td>
+    <td>F</td>
+  </tr>
+</table>
+
+</body>
+</html>
diff --git a/content/test/data/accessibility/table-spans-expected-mac.txt b/content/test/data/accessibility/table-spans-expected-mac.txt
new file mode 100644
index 0000000..55160c1
--- /dev/null
+++ b/content/test/data/accessibility/table-spans-expected-mac.txt
@@ -0,0 +1,13 @@
+AXWebArea AXTitle='Table example with rowspan and colspan'
+    AXTable
+        AXRow AXIndex='0'
+            AXCell AXColumnIndexRange={"len":1,"loc":0} AXRowIndexRange={"len":2,"loc":0}
+                AXStaticText AXValue='AD'
+            AXCell AXColumnIndexRange={"len":2,"loc":1} AXRowIndexRange={"len":1,"loc":0}
+                AXStaticText AXValue='BC'
+        AXRow AXIndex='1'
+            AXCell AXColumnIndexRange={"len":2,"loc":1} AXRowIndexRange={"len":1,"loc":1}
+                AXStaticText AXValue='EF'
+        AXColumn AXIndex='0'
+        AXColumn AXIndex='1'
+        AXGroup
diff --git a/content/test/data/accessibility/table-spans-expected-win.txt b/content/test/data/accessibility/table-spans-expected-win.txt
new file mode 100644
index 0000000..839b7a2
--- /dev/null
+++ b/content/test/data/accessibility/table-spans-expected-win.txt
@@ -0,0 +1 @@
+#<skip - we don't dump table attrs on win yet>
diff --git a/content/test/data/accessibility/table-spans.html b/content/test/data/accessibility/table-spans.html
new file mode 100644
index 0000000..608b321
--- /dev/null
+++ b/content/test/data/accessibility/table-spans.html
@@ -0,0 +1,24 @@
+<!doctype html>
+<!--
+@MAC-ALLOW:AXIndex=*
+@MAC-ALLOW:AXColumnIndexRange=*
+@MAC-ALLOW:AXRowIndexRange=*
+-->
+<html>
+<head>
+  <title>Table example with rowspan and colspan</title>
+</head>
+<body>
+
+<table border=1>
+  <tr>
+    <td rowspan="2">AD</td>
+    <td colspan="2">BC</td>
+  </tr>
+  <tr>
+    <td colspan="2">EF</td>
+  </tr>
+</table>
+
+</body>
+</html>
diff --git a/content/test/data/accessibility/togglebutton-expected-mac.txt b/content/test/data/accessibility/togglebutton-expected-mac.txt
index 3544dbf..6710157 100644
--- a/content/test/data/accessibility/togglebutton-expected-mac.txt
+++ b/content/test/data/accessibility/togglebutton-expected-mac.txt
@@ -1,3 +1,3 @@
 AXWebArea
-    AXButton title='Regular button'
-    AXButton title='Toggle button'
+    AXButton AXTitle='Regular button'
+    AXButton AXTitle='Toggle button'
diff --git a/content/test/data/accessibility/toolbar-expected-mac.txt b/content/test/data/accessibility/toolbar-expected-mac.txt
index 0b2df0f..91db02e 100644
--- a/content/test/data/accessibility/toolbar-expected-mac.txt
+++ b/content/test/data/accessibility/toolbar-expected-mac.txt
@@ -1,3 +1,3 @@
-AXWebArea roleDescription='HTML content'
-    AXToolbar roleDescription='toolbar'
-        AXStaticText roleDescription='text' value='A toolbar'
+AXWebArea AXRoleDescription='HTML content'
+    AXToolbar AXRoleDescription='toolbar'
+        AXStaticText AXRoleDescription='text' AXValue='A toolbar'
diff --git a/content/test/data/accessibility/toolbar.html b/content/test/data/accessibility/toolbar.html
index 7f4f541..f0274c5 100644
--- a/content/test/data/accessibility/toolbar.html
+++ b/content/test/data/accessibility/toolbar.html
@@ -1,5 +1,5 @@
 <!--
-@MAC-ALLOW:roleDescription=*
+@MAC-ALLOW:AXRoleDescription=*
 @WIN-DENY:name=''
 -->
 <html>
diff --git a/content/test/data/accessibility/ul-expected-mac.txt b/content/test/data/accessibility/ul-expected-mac.txt
index 317db0a..776cf1b 100644
--- a/content/test/data/accessibility/ul-expected-mac.txt
+++ b/content/test/data/accessibility/ul-expected-mac.txt
@@ -1,11 +1,11 @@
 AXWebArea
-    AXList subrole=AXContentList
+    AXList AXSubrole=AXContentList
         AXGroup
-            AXListMarker value='•'
-            AXStaticText value='Item 1'
+            AXListMarker AXValue='•'
+            AXStaticText AXValue='Item 1'
         AXGroup
-            AXListMarker value='•'
-            AXStaticText value='Item 2'
+            AXListMarker AXValue='•'
+            AXStaticText AXValue='Item 2'
         AXGroup
-            AXListMarker value='•'
-            AXStaticText value='Item 3'
+            AXListMarker AXValue='•'
+            AXStaticText AXValue='Item 3'
diff --git a/content/test/data/accessibility/ul.html b/content/test/data/accessibility/ul.html
index 3520fe5..b500201 100644
--- a/content/test/data/accessibility/ul.html
+++ b/content/test/data/accessibility/ul.html
@@ -1,5 +1,5 @@
 <!--
-@MAC-ALLOW:subrole*
+@MAC-ALLOW:AXSubrole*
 -->
 <html>
 <body>
diff --git a/content/test/data/accessibility/wbr-expected-mac.txt b/content/test/data/accessibility/wbr-expected-mac.txt
index b8bf1ea..5611f0d 100644
--- a/content/test/data/accessibility/wbr-expected-mac.txt
+++ b/content/test/data/accessibility/wbr-expected-mac.txt
@@ -2,6 +2,6 @@
 # wrong, so we assume this is correct.
 AXWebArea
     AXGroup
-        AXStaticText value='Supercali'
-        AXStaticText value='fragilistic'
-        AXStaticText value='expialidocious'
+        AXStaticText AXValue='Supercali'
+        AXStaticText AXValue='fragilistic'
+        AXStaticText AXValue='expialidocious'
diff --git a/content/test/data/dom_serializer/html_doc_has_base_tag.htm b/content/test/data/dom_serializer/html_doc_has_base_tag.htm
new file mode 100644
index 0000000..f2b43d8
--- /dev/null
+++ b/content/test/data/dom_serializer/html_doc_has_base_tag.htm
@@ -0,0 +1,13 @@
+<html>
+<head>
+<base href="http://www.youtube.com">
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<script>
+document.write("<base href=\"http://www.youtube.com\">");
+</script>
+</head>
+<body>
+<a href="/signup">Sign Up</a>
+<a href="/forgot_username?next=/">Forgot Username</a>
+</body>
+</html>
diff --git a/content/test/data/dom_serializer/iframe-src-is-exe.htm b/content/test/data/dom_serializer/iframe-src-is-exe.htm
new file mode 100644
index 0000000..ed32b12
--- /dev/null
+++ b/content/test/data/dom_serializer/iframe-src-is-exe.htm
@@ -0,0 +1,8 @@
+<html>

+<body>

+This tests that we can serialize a page that has a downloaded url in an iframe without crashing.

+

+<iframe src="dummy.exe"></iframe>

+

+</body>

+</html>
\ No newline at end of file
diff --git a/content/test/data/dom_serializer/non_html_namespace.htm b/content/test/data/dom_serializer/non_html_namespace.htm
new file mode 100644
index 0000000..ec3a50a
--- /dev/null
+++ b/content/test/data/dom_serializer/non_html_namespace.htm
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+<body>
+<script>
+window.onload = function() {
+    var input = document.createElementNS("urn:x-foo", "input");
+    input.setAttribute("type", "image");
+    input.setAttribute("src", "bar.png");
+    document.body.appendChild(input);
+};
+</script>
+</body>
+</html>
diff --git a/content/test/data/dom_serializer/nonstandard_htmlentities.htm b/content/test/data/dom_serializer/nonstandard_htmlentities.htm
new file mode 100644
index 0000000..17cd529
--- /dev/null
+++ b/content/test/data/dom_serializer/nonstandard_htmlentities.htm
@@ -0,0 +1 @@
+<HTML><BODY title="&percnt;&nsup;&sup1;&apos;">&percnt;&nsup;&sup1;&apos;</BODY></HTML>
diff --git a/content/test/data/dom_serializer/note.html b/content/test/data/dom_serializer/note.html
new file mode 100644
index 0000000..69b83a6
--- /dev/null
+++ b/content/test/data/dom_serializer/note.html
@@ -0,0 +1,5 @@
+<html>
+  <body>
+    <iframe src="note.xml"></iframe>
+  </body>
+</html>
diff --git a/content/test/data/dom_serializer/note.xml b/content/test/data/dom_serializer/note.xml
new file mode 100644
index 0000000..cef4920
--- /dev/null
+++ b/content/test/data/dom_serializer/note.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<note>
+<to>&lt;Johnny&gt;</to>
+<from>&lt;Boss&gt;</from>
+<heading>Reminder</heading>
+<body>Get "review" and 'check' in code!</body>
+</note>
\ No newline at end of file
diff --git a/content/test/data/dom_serializer/youtube_1.htm b/content/test/data/dom_serializer/youtube_1.htm
new file mode 100644
index 0000000..0e1f92a
--- /dev/null
+++ b/content/test/data/dom_serializer/youtube_1.htm
@@ -0,0 +1,19 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd">
+<html lang="en">
+<head>
+  <title>YouTube - Broadcast Yourself.</title>
+  <link rel="stylesheet" href="file:///c:/yt/css/base_all-vfl36460.css" type="text/css">
+  <link rel="search" type="application/opensearchdescription+xml" href="http://www.youtube.com/opensearch?locale=en_US" title="YouTube Video Search">
+  <link rel="icon" href="http://s.ytimg.com/yt/favicon-vfl1123.ico" type="image/x-icon">
+  <link rel="shortcut icon" href="http://s.ytimg.com/yt/favicon-vfl1123.ico" type="image/x-icon">
+  <meta name="description" content="Share your videos with friends and family">
+  <meta name="keywords" content="video,sharing,camera phone,video phone">
+  <link rel="alternate" type="application/rss+xml" title="YouTube - [RSS]" href="/rssls">
+  <link rel="alternate" media="handheld" href="http://m.youtube.com">
+  <script type="text/javascript" src="file:///c:/yt/js/base_all_with_bidi-vfl36451.js"></script>
+</head>
+<body>
+  <div id="baseDiv"><img src="file:///c:/yt/img/pixel-vfl73.gif" width="132" height="63" border="0" alt=""/>contents in youtube_1</div>
+  <iframe width="300" height="300" src="./youtube_2.htm">
+</body>
+</html>
diff --git a/content/test/data/dom_serializer/youtube_2.htm b/content/test/data/dom_serializer/youtube_2.htm
new file mode 100644
index 0000000..790dad6
--- /dev/null
+++ b/content/test/data/dom_serializer/youtube_2.htm
@@ -0,0 +1,17 @@
+<html lang="en">
+<head>
+  <title>YouTube - Broadcast Yourself.</title>
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+  <link rel="search" type="application/opensearchdescription+xml" href="http://www.youtube.com/opensearch?locale=en_US" title="YouTube Video Search">
+  <link rel="icon" href="http://s.ytimg.com/yt/favicon-vfl1123.ico" type="image/x-icon">
+  <link rel="shortcut icon" href="http://s.ytimg.com/yt/favicon-vfl1123.ico" type="image/x-icon">
+  <meta http-equiv="Content-Type" content="text/html; charset=GB2312">
+  <meta name="description" content="Share your videos with friends and family">
+  <meta name="keywords" content="video,sharing,camera phone,video phone">
+  <link rel="alternate" type="application/rss+xml" title="YouTube - [RSS]" href="/rssls">
+  <link rel="alternate" media="handheld" href="http://m.youtube.com">
+</head>
+<body>
+  <div id="baseDiv">contents in youtube_2</div>
+</body>
+</html>
diff --git a/content/test/data/gpu/functional_3d_css.html b/content/test/data/gpu/functional_3d_css.html
new file mode 100644
index 0000000..6bee8d0
--- /dev/null
+++ b/content/test/data/gpu/functional_3d_css.html
@@ -0,0 +1,16 @@
+<html>
+<head>
+<style> 
+  div {
+    width:200px;
+    height:100px;
+    background-color:black;
+    color:#ffffff;
+    -webkit-transform:translateZ(0);
+  }
+</style>
+</head>
+<body>
+<div>3D CSS</div>
+</body>
+</html>
\ No newline at end of file
diff --git a/content/test/data/gpu/functional_canvas_demo.html b/content/test/data/gpu/functional_canvas_demo.html
new file mode 100644
index 0000000..cf6ef03
--- /dev/null
+++ b/content/test/data/gpu/functional_canvas_demo.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html><head><meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>Canvas Demo</title>
+</head>
+<body>
+<canvas id="canv" class="output" width="600" height="400" style="width:600px;height:400px;border:2px solid #c3c3c3;">
+ <p><b>Browser doesn't support canvas</b></p>
+</canvas>
+<script>
+  var c = document.getElementById('canv');
+  var ctx = c.getContext('2d');
+  ctx.fillStyle = "#000000";
+  ctx.fillRect(10, 10, 250, 250);
+</script>
+</body>
+</html>
\ No newline at end of file
diff --git a/content/test/data/gpu/functional_color2.ogv b/content/test/data/gpu/functional_color2.ogv
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/content/test/data/gpu/functional_color2.ogv
diff --git a/content/test/data/gpu/functional_files/context.js b/content/test/data/gpu/functional_files/context.js
new file mode 100644
index 0000000..af56f6f
--- /dev/null
+++ b/content/test/data/gpu/functional_files/context.js
@@ -0,0 +1,33 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Global variable.
+var gl_context;
+
+initializeWebGL = function(canvas) {
+  gl_context = null;
+  // Try to grab the standard context.
+  gl_context = canvas.getContext("webgl") ||
+               canvas.getContext("experimental-webgl");
+  // If we don't have a GL context, give up now
+  if (!gl_context) {
+    alert("Unable to initialize WebGL. Your browser may not support it.");
+  }
+}
+
+startWebGLContext = function() {
+  var canvas = document.getElementById("glcanvas");
+  // Initialize the GL context.
+  initializeWebGL(canvas);
+
+  // Only continue if WebGL is available and working.
+  if (gl_context) {
+    gl_context.clearColor(0.0, 0.0, 0.0, 1.0);
+    gl_context.enable(gl_context.DEPTH_TEST);
+    gl_context.depthFunc(gl_context.LEQUAL);
+    gl_context.clearDepth(1);
+    gl_context.clear(gl_context.COLOR_BUFFER_BIT |
+                     gl_context.DEPTH_BUFFER_BIT);
+  }
+}
\ No newline at end of file
diff --git a/content/test/data/gpu/functional_webgl.html b/content/test/data/gpu/functional_webgl.html
new file mode 100644
index 0000000..abb0fe0
--- /dev/null
+++ b/content/test/data/gpu/functional_webgl.html
@@ -0,0 +1,8 @@
+<html>
+<script type="text/javascript" src="./functional_files/context.js"></script>
+<body onload="startWebGLContext()">
+  <canvas id="glcanvas" width="640" height="480">
+    Your browser doesn't appear to support the HTML5 <code>&lt;canvas&gt;</code> element.
+  </canvas>
+</body>
+</html>
\ No newline at end of file
diff --git a/content/test/data/media/encrypted_media_utils.js b/content/test/data/media/encrypted_media_utils.js
index a29c0f5..e5d4230 100644
--- a/content/test/data/media/encrypted_media_utils.js
+++ b/content/test/data/media/encrypted_media_utils.js
@@ -41,12 +41,10 @@
 function isHeartbeatMessage(msg) {
   if (msg.length < HEART_BEAT_HEADER.length)
     return false;
-
   for (var i = 0; i < HEART_BEAT_HEADER.length; ++i) {
     if (String.fromCharCode(msg[i]) != HEART_BEAT_HEADER[i])
       return false;
   }
-
   return true;
 }
 
@@ -87,6 +85,7 @@
   video.receivedKeyAdded = false;
   video.receivedHeartbeat = false;
   video.isHeartbeatExpected = keySystem === EXTERNAL_CLEAR_KEY_KEY_SYSTEM;
+  video.receivedKeyMessage = false;
 
   if (!(video && mediaFile && keySystem && key))
     failTest('Missing parameters in loadEncryptedMedia().');
@@ -126,6 +125,7 @@
   }
 
   function onKeyMessage(e) {
+    video.receivedKeyMessage = true;
     if (!e.keySystem) {
       failTest('keymessage without a keySystem: ' + e.keySystem);
       return;
@@ -180,7 +180,9 @@
   mediaSource.addEventListener('webkitsourceopen', onSourceOpen);
   video.addEventListener('webkitneedkey', onNeedKey);
   video.addEventListener('webkitkeymessage', onKeyMessage);
-  video.addEventListener('webkitkeyerror', failTest);
+  video.addEventListener('webkitkeyerror', function() {
+      setResultInTitle("WebKitKeyError");
+  });
   video.addEventListener('webkitkeyadded', onKeyAdded);
   installTitleEventHandler(video, 'error');
 
diff --git a/content/test/data/media/getusermedia.html b/content/test/data/media/getusermedia.html
new file mode 100644
index 0000000..429dd66
--- /dev/null
+++ b/content/test/data/media/getusermedia.html
@@ -0,0 +1,76 @@
+<html>
+<head>
+  <script type="text/javascript" src="webrtc_test_utilities.js"></script>
+  <script type="text/javascript">
+  $ = function(id) {
+    return document.getElementById(id);
+  };
+  
+  var gLocalStream = null;
+    
+  setAllEventsOccuredHandler(function() {
+    gLocalStream.stop();
+    document.title = 'OK';      
+  });
+  
+  // This test that a MediaStream can be created and a local preview 
+  // rendered.
+  function getUserMedia(constraints) {
+    navigator.webkitGetUserMedia(constraints, displayAndWaitForVideo,
+        failedCallback);
+  }
+  
+  // This test that a MediaStream can be cloned and that the clone can 
+  // be rendered.
+  function getUserMediaAndClone() {
+    navigator.webkitGetUserMedia({video: true, audio: true},
+        createAndRenderClone, failedCallback);
+  }
+    
+  function failedCallback(error) {
+    document.title = 'GetUserMedia call failed with code ' + error.code;
+  }
+
+  function displayAndWaitForVideo(stream) {
+    gLocalStream = stream;
+    var localStreamUrl = webkitURL.createObjectURL(stream);
+    $('local-view').src = localStreamUrl;
+    waitForVideo('local-view');   
+  }
+  
+  function createAndRenderClone(stream) {
+    gLocalStream = stream;
+    // TODO(perkj):  --use-fake-device-for-media-stream do not currently
+    // work with audio devices and not all bots has a microphone.    
+    new_stream = new webkitMediaStream();
+    new_stream.addTrack(stream.getVideoTracks()[0]);
+    expectEquals(new_stream.getVideoTracks().length, 1);
+    if (stream.getAudioTracks().length > 0) {
+      new_stream.addTrack(stream.getAudioTracks()[0]);
+      expectEquals(new_stream.getAudioTracks().length, 1);
+      new_stream.removeTrack(new_stream.getAudioTracks()[0]);
+      expectEquals(new_stream.getAudioTracks().length, 0);
+    }
+    
+    var newStreamUrl = webkitURL.createObjectURL(new_stream);
+    $('local-view').src = newStreamUrl;  
+    waitForVideo('local-view');
+  }
+  
+  </script>  
+</head>
+<body>
+  <table border="0">
+    <tr>
+      <td>Local Preview</td>
+    </tr>
+    <tr>
+      <td><video width="320" height="240" id="local-view"
+          autoplay="autoplay"></video></td>      
+      <!-- Canvases are named after their corresponding video elements. -->
+      <td><canvas width="320" height="240" id="local-view-canvas"
+          style="display:none"></canvas></td>
+    </tr>
+  </table>
+</body>
+</html>
\ No newline at end of file
diff --git a/content/test/data/media/getusermedia_and_stop.html b/content/test/data/media/getusermedia_and_stop.html
deleted file mode 100644
index f1c43be..0000000
--- a/content/test/data/media/getusermedia_and_stop.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<html>
-<head>
-  <script type="text/javascript">
-  function getUserMedia(constraints) {
-    navigator.webkitGetUserMedia(constraints, okCallback, failedCallback);
-  }
-
-  function failedCallback(error) {
-    document.title = 'GetUserMedia call failed with code ' + error.code;
-  }
-
-  function okCallback(stream) {
-    stream.stop();
-    document.title = 'OK';
-  }
-  </script>
-</head>
-</html>
\ No newline at end of file
diff --git a/content/test/data/media/peerconnection-call.html b/content/test/data/media/peerconnection-call.html
index 4a85e9c..a157213 100644
--- a/content/test/data/media/peerconnection-call.html
+++ b/content/test/data/media/peerconnection-call.html
@@ -1,28 +1,22 @@
 <html>
 <head>
+  <script type="text/javascript" src="webrtc_test_utilities.js"></script>
   <script type="text/javascript">
   $ = function(id) {
     return document.getElementById(id);
   };
 
-  // These must match with how the video and canvas tags are declared in html.
-  const VIDEO_TAG_WIDTH = 320;
-  const VIDEO_TAG_HEIGHT = 240;
-
   var gFirstConnection = null;
   var gSecondConnection = null;
   var gTestWithoutMsidAndBundle = false;
 
-  // Number of test events to occur before the test pass. When the test pass,
-  // the document title change to OK.
-  var gNumberOfExpectedEvents = 0;
-
-  // Number of events that currently have occured.
-  var gNumberOfEvents = 0;
-
   var gLocalStream = null;
   var gSentTones = '';
 
+  setAllEventsOccuredHandler(function() {
+    document.title = 'OK';
+  });
+
   // Test that we can setup call with an audio and video track.
   function call(constraints) {
     createConnections(null);
@@ -50,8 +44,7 @@
     gTestWithoutMsidAndBundle = true;
     navigator.webkitGetUserMedia({audio:true, video:true},
       addStreamToBothConnectionsAndNegotiate, printGetUserMediaError);
-    // TODO(phoglund): this should work but it doesn't! http://crbug.com/177443.
-    // waitForVideo('remote-view-1');
+    waitForVideo('remote-view-1');
     waitForVideo('remote-view-2');
   }
 
@@ -75,10 +68,6 @@
 
   // Test call with a data channel and later add audio and video.
   function callWithDataAndLaterAddMedia() {
-    // TODO(perkj): This is needed for now until
-    // https://code.google.com/p/webrtc/issues/detail?id=1203 is fixed.
-    gTestWithoutMsidAndBundle = true;
-
     createConnections({optional:[{RtpDataChannels: true}]});
     setupDataChannel();
     gFirstConnection.createOffer(onOfferCreated);
@@ -115,6 +104,79 @@
     detectVideoIn('remote-view-2', onCallEstablished);
   }
 
+  // Test call with a new Video MediaStream that has been created based on a
+  // stream generated by getUserMedia.
+  function callWithNewVideoMediaStream() {
+    createConnections(null);
+    navigator.webkitGetUserMedia({audio:true, video:true},
+        createNewVideoStreamAndAddToBothConnections, printGetUserMediaError);
+    waitForVideo('remote-view-1');
+    waitForVideo('remote-view-2');
+  }
+
+  // Test call with a new Video MediaStream that has been created based on a
+  // stream generated by getUserMedia. When Video is flowing, an audio track
+  // is added to the sent stream and the video track is removed. This
+  // is to test that adding and removing of remote tracks on an existing
+  // mediastream works.
+  function callWithNewVideoMediaStreamLaterSwitchToAudio() {
+    createConnections(null);
+    navigator.webkitGetUserMedia({audio:true, video:true},
+        createNewVideoStreamAndAddToBothConnections, printGetUserMediaError);
+
+    waitForVideo('remote-view-1');
+    waitForVideo('remote-view-2');
+
+    // Set an event handler for when video is playing.
+    setAllEventsOccuredHandler(function() {
+      // Add an audio track to the local stream and remove the video track and
+      // then renegotiate. But first - setup the expectations.
+      local_stream = gFirstConnection.getLocalStreams()[0];
+
+      remote_stream_1 = gFirstConnection.getRemoteStreams()[0];
+      // Add an expected event that onaddtrack will be called on the remote
+      // mediastream received on gFirstConnection when the audio track is
+      // received.
+      addExpectedEvent();
+      remote_stream_1.onaddtrack = function(){
+        expectEquals(remote_stream_1.getAudioTracks()[0].id,
+                     local_stream.getAudioTracks()[0].id);
+        eventOccured();
+      }
+
+      // Add an expectation that the received video track is removed from
+      // gFirstConnection.
+      addExpectedEvent();
+      remote_stream_1.onremovetrack = function() {
+        eventOccured();
+      }
+
+      // Add an expected event that onaddtrack will be called on the remote
+      // mediastream received on gSecondConnection when the audio track is
+      // received.
+      remote_stream_2 = gSecondConnection.getRemoteStreams()[0];
+      addExpectedEvent();
+      remote_stream_2.onaddtrack = function() {
+        expectEquals(remote_stream_2.getAudioTracks()[0].id,
+                     local_stream.getAudioTracks()[0].id);
+        eventOccured();
+      }
+
+      // Add an expectation that the received video track is removed from
+      // gSecondConnection.
+      addExpectedEvent();
+      remote_stream_2.onremovetrack = function() {
+        eventOccured();
+      }
+      // When all the above events have occurred- the test pass.
+      setAllEventsOccuredHandler(function() { document.title = 'OK'; });
+
+      local_stream.addTrack(gLocalStream.getAudioTracks()[0]);
+      local_stream.removeTrack(local_stream.getVideoTracks()[0]);
+      negotiate();
+    });  // End of setAllEventsOccuredHandler.
+  }
+
   // This function is used for setting up a test that:
   // 1. Creates a data channel on |gFirstConnection| and sends data to
   //    |gSecondConnection|.
@@ -209,6 +271,18 @@
     negotiate();
   }
 
+  // Called if getUserMedia succeeds when we want to send a modified
+  // MediaStream. A new MediaStream is created and the video track from
+  // |localStream| is added.
+  function createNewVideoStreamAndAddToBothConnections(localStream) {
+    displayAndRemember(localStream);
+    var new_stream = new webkitMediaStream();
+    new_stream.addTrack(localStream.getVideoTracks()[0]);
+    gFirstConnection.addStream(new_stream);
+    gSecondConnection.addStream(new_stream);
+    negotiate();
+  }
+
   function negotiate() {
     gFirstConnection.createOffer(onOfferCreated);
   }
@@ -243,10 +317,13 @@
   function onAnswerCreated(answer) {
     gSecondConnection.setLocalDescription(answer);
     expectEquals('stable', gSecondConnection.signalingState);
-    handleAnswer(answer.sdp);
+    receiveAnswer(answer.sdp);
   }
 
-  function handleAnswer(answerSdp) {
+  function receiveAnswer(answerSdp) {
+    if (gTestWithoutMsidAndBundle) {
+      answerSdp = removeMsidAndBundle(answerSdp);
+    }
     var parsedAnswer = new RTCSessionDescription({ type: 'answer',
                                                    sdp: answerSdp });
     gFirstConnection.setRemoteDescription(parsedAnswer);
@@ -268,9 +345,9 @@
   }
 
   function onRemoteStream(e, target) {
-    if (gTestWithoutMsidAndBundle && e.stream.label != "default") {
+    if (gTestWithoutMsidAndBundle && e.stream.id != "default") {
       document.title = 'a default remote stream was expected but instead ' +
-          e.stream.label + ' was received.';
+          e.stream.id + ' was received.';
       return;
     }
     var remoteStreamUrl = webkitURL.createObjectURL(e.stream);
@@ -278,65 +355,6 @@
     remoteVideo.src = remoteStreamUrl;
   }
 
-  // TODO(phoglund): perhaps use the video detector in chrome/test/data/webrtc/?
-  function detectVideoIn(videoElementName, callback) {
-    var width = VIDEO_TAG_WIDTH;
-    var height = VIDEO_TAG_HEIGHT;
-    var videoElement = $(videoElementName);
-    var canvas = $(videoElementName + '-canvas');
-    var waitVideo = setInterval(function() {
-      var context = canvas.getContext('2d');
-      context.drawImage(videoElement, 0, 0, width, height);
-      var pixels = context.getImageData(0, 0, width, height).data;
-
-      if (isVideoPlaying(pixels, width, height)) {
-        clearInterval(waitVideo);
-        callback();
-      }
-    }, 100);
-  }
-
-  function waitForVideo(videoElement) {
-    document.title = 'Waiting for video...';
-    addExpectedEvent();
-    detectVideoIn(videoElement, function () { eventOccured(); });
-  }
-
-  // This very basic video verification algorithm will be satisfied if any
-  // pixels are nonzero in a small sample area in the middle. It relies on the
-  // assumption that a video element with null source just presents zeroes.
-  function isVideoPlaying(pixels, width, height) {
-    // Sample somewhere near the middle of the image.
-    var middle = width * height / 2;
-    for (var i = 0; i < 20; i++) {
-      if (pixels[middle + i] > 0) {
-        return true;
-      }
-    }
-    return false;
-  }
-
-
-  // This function matches |left| and |right| and throws an exception if the
-  // values don't match.
-  function expectEquals(left, right) {
-    if (left != right) {
-      var s = "expectEquals failed left: " + left + " right: " + right;
-      document.title = s;
-      throw s;
-    }
-  }
-
-  function addExpectedEvent() {
-    ++gNumberOfExpectedEvents;
-  }
-
-  function eventOccured() {
-    ++gNumberOfEvents;
-    if (gNumberOfEvents == gNumberOfExpectedEvents) {
-      document.title = 'OK';
-    }
-  }
   </script>
 </head>
 <body>
diff --git a/content/test/data/media/webrtc_test_utilities.js b/content/test/data/media/webrtc_test_utilities.js
new file mode 100644
index 0000000..dae549f
--- /dev/null
+++ b/content/test/data/media/webrtc_test_utilities.js
@@ -0,0 +1,80 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// These must match with how the video and canvas tags are declared in html.
+const VIDEO_TAG_WIDTH = 320;
+const VIDEO_TAG_HEIGHT = 240;
+
+// Number of test events to occur before the test pass. When the test pass,
+// the function gAllEventsOccured is called.
+var gNumberOfExpectedEvents = 0;
+
+// Number of events that currently have occurred.
+var gNumberOfEvents = 0;
+
+var gAllEventsOccured = function () {};
+
+// Use this function to set a function that will be called once all expected
+// events has occurred.
+function setAllEventsOccuredHandler(handler) {
+  gAllEventsOccured = handler;
+}
+
+function detectVideoIn(videoElementName, callback) {
+  var width = VIDEO_TAG_WIDTH;
+  var height = VIDEO_TAG_HEIGHT;
+  var videoElement = $(videoElementName);
+  var canvas = $(videoElementName + '-canvas');
+  var waitVideo = setInterval(function() {
+    var context = canvas.getContext('2d');
+    context.drawImage(videoElement, 0, 0, width, height);
+    var pixels = context.getImageData(0, 0, width, height).data;
+
+    if (isVideoPlaying(pixels, width, height)) {
+      clearInterval(waitVideo);
+      callback();
+    }
+  }, 100);
+}
+
+function waitForVideo(videoElement) {
+  document.title = 'Waiting for video...';
+  addExpectedEvent();
+  detectVideoIn(videoElement, function () { eventOccured(); });
+}
+
+function addExpectedEvent() {
+  ++gNumberOfExpectedEvents;
+}
+
+function eventOccured() {
+  ++gNumberOfEvents;
+  if (gNumberOfEvents == gNumberOfExpectedEvents) {
+    gAllEventsOccured();
+  }
+}
+
+// This very basic video verification algorithm will be satisfied if any
+// pixels are nonzero in a small sample area in the middle. It relies on the
+// assumption that a video element with null source just presents zeroes.
+function isVideoPlaying(pixels, width, height) {
+  // Sample somewhere near the middle of the image.
+  var middle = width * height / 2;
+  for (var i = 0; i < 20; i++) {
+    if (pixels[middle + i] > 0) {
+      return true;
+    }
+  }
+  return false;
+}
+
+// This function matches |left| and |right| and throws an exception if the
+// values don't match.
+function expectEquals(left, right) {
+  if (left != right) {
+    var s = "expectEquals failed left: " + left + " right: " + right;
+    document.title = s;
+    throw s;
+  }
+}
\ No newline at end of file
diff --git a/content/test/data/rwh_simple.html b/content/test/data/rwh_simple.html
new file mode 100644
index 0000000..940fee6
--- /dev/null
+++ b/content/test/data/rwh_simple.html
@@ -0,0 +1,4 @@
+<html>
+<head><title>The background is red.</title></head>
+<body style="background-color:#FF0000"></body>
+</html>
diff --git a/content/test/data/touch_selection.html b/content/test/data/touch_selection.html
new file mode 100644
index 0000000..0c4721a
--- /dev/null
+++ b/content/test/data/touch_selection.html
@@ -0,0 +1,35 @@
+<html>
+<div id='textDiv'>Some text we can select</div>
+<input id='textfield' type="text" value="Text in a textfield">
+<script>
+
+function select_all_text() {
+  var div = document.getElementById("textDiv");
+  var range = document.createRange();
+  range.selectNodeContents(div);
+  var sel = window.getSelection();
+  sel.removeAllRanges();
+  sel.addRange(range);
+}
+
+function get_selection() {
+  return (window.getSelection() + "");
+}
+
+function focus_textfield() {
+  document.getElementById("textfield").focus();
+}
+
+function get_cursor_position() {
+  var div = document.getElementById("textfield");
+  var start = div.selectionStart;
+  var end = div.selectionEnd;
+  if (start == end)
+    return start;
+  else
+    return -1;
+}
+
+</script>
+
+</html>
diff --git a/content/test/gpu/OWNERS b/content/test/gpu/OWNERS
index 5b3dc2a..eea0460 100644
--- a/content/test/gpu/OWNERS
+++ b/content/test/gpu/OWNERS
@@ -1,3 +1,3 @@
 kbr@chromium.org
 zmo@chromium.org
-jbates@chromium.org
+apatrick@chromium.org
diff --git a/content/test/gpu/gpu_test_config_unittest.cc b/content/test/gpu/gpu_test_config_unittest.cc
index f58139f..a87d215 100644
--- a/content/test/gpu/gpu_test_config_unittest.cc
+++ b/content/test/gpu/gpu_test_config_unittest.cc
@@ -148,7 +148,7 @@
   config.set_gpu_device_id(0x0640);
   EXPECT_TRUE(config.IsValid());
 
-  EXPECT_TRUE(config.Matches(""));
+  EXPECT_TRUE(config.Matches(std::string()));
 
   // os matching
   EXPECT_TRUE(config.Matches("WIN"));
diff --git a/content/test/gpu/gpu_tests/bootstrap_deps b/content/test/gpu/gpu_tests/bootstrap_deps
index c56d53b..2e683cb 100644
--- a/content/test/gpu/gpu_tests/bootstrap_deps
+++ b/content/test/gpu/gpu_tests/bootstrap_deps
@@ -12,6 +12,8 @@
     "https://src.chromium.org/chrome/trunk/src/content/test/gpu/gpu_tests",
   "src/content/test/gpu/page_sets":
     "https://src.chromium.org/chrome/trunk/src/content/test/gpu/page_sets",
+  "src/third_party/webgl_conformance":
+    "https://src.chromium.org/chrome/trunk/deps/third_party/webgl/sdk/tests",
   }
 
 # gpu_tests depends on Telemetry, so pull in the Telemetry deps, too.
diff --git a/content/test/gpu/gpu_tests/webgl_conformance_test.py b/content/test/gpu/gpu_tests/webgl_conformance_test.py
new file mode 100644
index 0000000..cbc5609
--- /dev/null
+++ b/content/test/gpu/gpu_tests/webgl_conformance_test.py
@@ -0,0 +1,126 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import os
+import sys
+import json
+
+from telemetry.page import page_set
+from telemetry.page import page_test
+from telemetry.core import util
+
+src_path = os.path.join(os.path.dirname(__file__), '..', '..', '..', '..')
+conformance_path = os.path.join(src_path, 'third_party', 'webgl_conformance')
+
+conformance_harness_script = r"""
+  var testHarness = {};
+  testHarness._allTestSucceeded = true;
+  testHarness._messages = '';
+  testHarness._failures = 0;
+  testHarness._finished = false;
+
+  testHarness.reportResults = function(success, msg) {
+    testHarness._allTestSucceeded = testHarness._allTestSucceeded && !!success;
+    if(!success) {
+      testHarness._failures++;
+      if(msg) {
+        testHarness._messages += msg + "\n";
+      }
+    }
+  };
+  testHarness.notifyFinished = function() {
+    testHarness._finished = true;
+  };
+  testHarness.navigateToPage = function(src) {
+    var testFrame = document.getElementById("test-frame");
+    testFrame.src = src;
+  };
+
+  window.webglTestHarness = testHarness;
+  window.parent.webglTestHarness = testHarness;
+  console.log("Harness injected.");
+"""
+
+def _DidWebGLTestSucceed(tab):
+  return tab.EvaluateJavaScript('webglTestHarness._allTestSucceeded')
+
+def _WebGLTestMessages(tab):
+  return tab.EvaluateJavaScript('webglTestHarness._messages')
+
+class WebGLConformanceTest(page_test.PageTest):
+  def __init__(self):
+    super(WebGLConformanceTest, self).__init__('ValidatePage')
+
+  def CreatePageSet(self, options):
+    tests = WebGLConformanceTest._ParseTests('00_test_list.txt')
+
+    page_set_dict = {
+      'description': 'Executes WebGL conformance tests',
+      'user_agent_type': 'desktop',
+      'serving_dirs': [
+        '../../../../third_party/webgl_conformance'
+      ],
+      'pages': []
+    }
+
+    pages = page_set_dict['pages']
+
+    for test in tests:
+      pages.append({
+        'url': 'file:///../../../../third_party/webgl_conformance/' + test,
+        'script_to_evaluate_on_commit': conformance_harness_script,
+        'wait_for_javascript_expression': 'webglTestHarness._finished'
+      })
+
+    return page_set.PageSet.FromDict(page_set_dict, __file__)
+
+  def ValidatePage(self, page, tab, results):
+    if _DidWebGLTestSucceed(tab):
+      results.AddSuccess(page)
+    else:
+      results.AddFailure(page, _WebGLTestMessages(tab), None)
+
+  @staticmethod
+  def _ParseTests(path, version = None):
+    test_paths = []
+    current_dir = os.path.dirname(path)
+    full_path = os.path.normpath(os.path.join(conformance_path, path))
+
+    if not os.path.exists(full_path):
+      raise Exception('The WebGL conformance test path specified ' +
+        'does not exist: ' + full_path)
+
+    with open(full_path, 'r') as f:
+      for line in f:
+        line = line.strip()
+
+        if not line:
+          continue
+
+        if line.startswith('//') or line.startswith('#'):
+          continue
+
+        line_tokens = line.split(' ')
+
+        i = 0
+        while i < len(line_tokens):
+          token = line_tokens[i]
+          if token == '--min-version':
+            i += 1
+            min_version = line_tokens[i]
+          i += 1
+
+        if version and version < min_version:
+          continue
+
+        test_name = line_tokens[-1]
+
+        if '.txt' in test_name:
+          include_path = os.path.join(current_dir, test_name)
+          test_paths += WebGLConformanceTest._ParseTests(
+            include_path, version)
+        else:
+          test = os.path.join(current_dir, test_name)
+          test_paths.append(test)
+
+    return test_paths
diff --git a/content/test/layout_browsertest.cc b/content/test/layout_browsertest.cc
index 4c34a38..3425ac6 100644
--- a/content/test/layout_browsertest.cc
+++ b/content/test/layout_browsertest.cc
@@ -73,7 +73,7 @@
 }
 
 InProcessBrowserLayoutTest::~InProcessBrowserLayoutTest() {
-  if (test_http_server_.get())
+  if (test_http_server_)
     CHECK(test_http_server_->Stop());
 }
 
@@ -155,8 +155,8 @@
   test_controller_->set_printer(printer.release());
 
   LOG(INFO) << "Navigating to URL " << url << " and blocking.";
-  ASSERT_TRUE(
-      test_controller_->PrepareForLayoutTest(url, layout_test_dir_, false, ""));
+  ASSERT_TRUE(test_controller_->PrepareForLayoutTest(
+      url, layout_test_dir_, false, std::string()));
   base::RunLoop run_loop;
   run_loop.Run();
   LOG(INFO) << "Navigation completed.";
@@ -195,9 +195,10 @@
 std::string InProcessBrowserLayoutTest::SaveResults(const std::string& expected,
                                                     const std::string& actual) {
   base::FilePath cwd;
-  EXPECT_TRUE(file_util::CreateNewTempDirectory(FILE_PATH_LITERAL(""), &cwd));
-  base::FilePath expected_filename = cwd.Append(
-      FILE_PATH_LITERAL("expected.txt"));
+  EXPECT_TRUE(file_util::CreateNewTempDirectory(
+      base::FilePath::StringType(), &cwd));
+  base::FilePath expected_filename =
+      cwd.Append(FILE_PATH_LITERAL("expected.txt"));
   base::FilePath actual_filename = cwd.Append(FILE_PATH_LITERAL("actual.txt"));
   EXPECT_NE(-1, file_util::WriteFile(expected_filename,
                                      expected.c_str(),
diff --git a/content/test/layout_test_http_server.cc b/content/test/layout_test_http_server.cc
index 23c972a..a9ba553 100644
--- a/content/test/layout_test_http_server.cc
+++ b/content/test/layout_test_http_server.cc
@@ -32,7 +32,7 @@
   script_path = script_path.AppendASCII("WebKit");
   script_path = script_path.AppendASCII("Tools");
   script_path = script_path.AppendASCII("Scripts");
-  script_path = script_path.AppendASCII("new-run-webkit-httpd");
+  script_path = script_path.AppendASCII("run-blink-httpd");
 
   cmd_line->AppendArgPath(script_path);
   return true;
diff --git a/content/test/layouttest_support.cc b/content/test/layouttest_support.cc
index efa333a..bd85a4f 100644
--- a/content/test/layouttest_support.cc
+++ b/content/test/layouttest_support.cc
@@ -15,6 +15,10 @@
 #include "third_party/WebKit/Source/Platform/chromium/public/WebGamepads.h"
 #include "third_party/WebKit/Tools/DumpRenderTree/chromium/TestRunner/public/WebTestProxy.h"
 
+#if defined(OS_WIN) && !defined(USE_AURA)
+#include "content/browser/web_contents/web_contents_drag_win.h"
+#endif
+
 using WebKit::WebGamepads;
 using WebTestRunner::WebTestProxy;
 using WebTestRunner::WebTestProxyBase;
@@ -100,4 +104,10 @@
       ->SetDeviceScaleFactorForTesting(factor);
 }
 
+void DisableSystemDragDrop() {
+#if defined(OS_WIN) && !defined(USE_AURA)
+  WebContentsDragWin::DisableDragDropForTesting();
+#endif
+}
+
 }  // namespace content
diff --git a/content/test/net/url_request_abort_on_end_job.cc b/content/test/net/url_request_abort_on_end_job.cc
index 4d49145..2173887 100644
--- a/content/test/net/url_request_abort_on_end_job.cc
+++ b/content/test/net/url_request_abort_on_end_job.cc
@@ -70,7 +70,7 @@
     net::URLRequest* request, net::NetworkDelegate* network_delegate)
     : URLRequestJob(request, network_delegate),
       sent_data_(false),
-      ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) {
+      weak_factory_(this) {
 }
 
 URLRequestAbortOnEndJob::~URLRequestAbortOnEndJob() {
@@ -91,7 +91,7 @@
 }
 
 void URLRequestAbortOnEndJob::Start() {
-  MessageLoop::current()->PostTask(
+  base::MessageLoop::current()->PostTask(
       FROM_HERE,
       base::Bind(&URLRequestAbortOnEndJob::StartAsync,
                  weak_factory_.GetWeakPtr()));
diff --git a/content/test/net/url_request_failed_job.cc b/content/test/net/url_request_failed_job.cc
index 79df121..dfeac52 100644
--- a/content/test/net/url_request_failed_job.cc
+++ b/content/test/net/url_request_failed_job.cc
@@ -46,15 +46,14 @@
                                          int net_error)
     : net::URLRequestJob(request, network_delegate),
       net_error_(net_error),
-      ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) {}
+      weak_factory_(this) {}
 
 URLRequestFailedJob::~URLRequestFailedJob() {}
 
 void URLRequestFailedJob::Start() {
-  MessageLoop::current()->PostTask(
+  base::MessageLoop::current()->PostTask(
       FROM_HERE,
-      base::Bind(&URLRequestFailedJob::StartAsync,
-                 weak_factory_.GetWeakPtr()));
+      base::Bind(&URLRequestFailedJob::StartAsync, weak_factory_.GetWeakPtr()));
 }
 
 // static
diff --git a/content/test/net/url_request_prepackaged_interceptor.cc b/content/test/net/url_request_prepackaged_interceptor.cc
index f8603ef..9150a7e 100644
--- a/content/test/net/url_request_prepackaged_interceptor.cc
+++ b/content/test/net/url_request_prepackaged_interceptor.cc
@@ -38,23 +38,26 @@
 class URLRequestPrepackagedInterceptor::Delegate
     : public net::URLRequestJobFactory::ProtocolHandler {
  public:
-  Delegate() : hit_count_(0) {}
+  Delegate(const std::string& scheme, const std::string& hostname)
+    : scheme_(scheme), hostname_(hostname), hit_count_(0) {}
   virtual ~Delegate() {}
 
   void Register() {
     net::URLRequestFilter::GetInstance()->AddHostnameProtocolHandler(
-        "http", "localhost",
+        scheme_, hostname_,
         scoped_ptr<net::URLRequestJobFactory::ProtocolHandler>(this));
   }
 
-  static void Unregister() {
-    net::URLRequestFilter::GetInstance()->RemoveHostnameHandler("http",
-                                                                "localhost");
+  static void Unregister(
+      const std::string& scheme,
+      const std::string& hostname) {
+    net::URLRequestFilter::GetInstance()->RemoveHostnameHandler(scheme,
+                                                                hostname);
   }
 
   // When requests for |url| arrive, respond with the contents of |path|. The
-  // hostname of |url| must be "localhost" to avoid DNS lookups, and the scheme
-  // must be "http".
+  // hostname and scheme of |url| must match the corresponding parameters
+  // passed as constructor arguments.
   void SetResponse(const GURL& url,
                    const base::FilePath& path,
                    bool ignore_query) {
@@ -84,8 +87,8 @@
       net::URLRequest* request,
       net::NetworkDelegate* network_delegate) const OVERRIDE {
     CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-    if (request->url().scheme() != "http" ||
-        request->url().host() != "localhost") {
+    if (request->url().scheme() != scheme_ ||
+        request->url().host() != hostname_) {
       return NULL;
     }
 
@@ -112,6 +115,9 @@
                                         it->second);
   }
 
+  const std::string scheme_;
+  const std::string hostname_;
+
   ResponseMap responses_;
   ResponseMap ignore_query_responses_;
 
@@ -122,8 +128,12 @@
 };
 
 
-URLRequestPrepackagedInterceptor::URLRequestPrepackagedInterceptor()
-    : delegate_(new Delegate) {
+URLRequestPrepackagedInterceptor::URLRequestPrepackagedInterceptor(
+    const std::string& scheme,
+    const std::string& hostname)
+    : scheme_(scheme),
+      hostname_(hostname),
+      delegate_(new Delegate(scheme, hostname)) {
   BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
                           base::Bind(&Delegate::Register,
                                      base::Unretained(delegate_)));
@@ -131,13 +141,16 @@
 
 URLRequestPrepackagedInterceptor::~URLRequestPrepackagedInterceptor() {
   BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
-                          base::Bind(&Delegate::Unregister));
+                          base::Bind(&Delegate::Unregister,
+                                     scheme_,
+                                     hostname_));
 }
 
-void URLRequestPrepackagedInterceptor::SetResponse(const GURL& url,
-                                                   const base::FilePath& path) {
-  CHECK_EQ("http", url.scheme());
-  CHECK_EQ("localhost", url.host());
+void URLRequestPrepackagedInterceptor::SetResponse(
+    const GURL& url,
+    const base::FilePath& path) {
+  CHECK_EQ(scheme_, url.scheme());
+  CHECK_EQ(hostname_, url.host());
   BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
                           base::Bind(&Delegate::SetResponse,
                                      base::Unretained(delegate_), url, path,
@@ -147,8 +160,8 @@
 void URLRequestPrepackagedInterceptor::SetResponseIgnoreQuery(
     const GURL& url,
     const base::FilePath& path) {
-  CHECK_EQ("http", url.scheme());
-  CHECK_EQ("localhost", url.host());
+  CHECK_EQ(scheme_, url.scheme());
+  CHECK_EQ(hostname_, url.host());
   BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
                           base::Bind(&Delegate::SetResponse,
                                      base::Unretained(delegate_), url, path,
@@ -159,4 +172,10 @@
   return delegate_->GetHitCount();
 }
 
+
+URLLocalHostRequestPrepackagedInterceptor
+  ::URLLocalHostRequestPrepackagedInterceptor()
+    : URLRequestPrepackagedInterceptor("http", "localhost") {
+}
+
 }  // namespace content
diff --git a/content/test/net/url_request_prepackaged_interceptor.h b/content/test/net/url_request_prepackaged_interceptor.h
index edb65c5..cc5736d 100644
--- a/content/test/net/url_request_prepackaged_interceptor.h
+++ b/content/test/net/url_request_prepackaged_interceptor.h
@@ -5,6 +5,8 @@
 #ifndef CHROME_BROWSER_COMPONENT_UPDATER_COMPONENT_UPDATER_INTERCEPTOR_H_
 #define CHROME_BROWSER_COMPONENT_UPDATER_COMPONENT_UPDATER_INTERCEPTOR_H_
 
+#include <string>
+
 #include "base/basictypes.h"
 
 class GURL;
@@ -20,12 +22,15 @@
 // occurs while the URLRequestPrepackagedInterceptor is alive.
 class URLRequestPrepackagedInterceptor {
  public:
-  URLRequestPrepackagedInterceptor();
+  // Registers an interceptor for urls using |scheme| and |hostname|. Urls
+  // passed to "SetResponse" are required to use |scheme| and |hostname|.
+  URLRequestPrepackagedInterceptor(const std::string& scheme,
+                                   const std::string& hostname);
   virtual ~URLRequestPrepackagedInterceptor();
 
   // When requests for |url| arrive, respond with the contents of |path|. The
-  // hostname of |url| must be "localhost" to avoid DNS lookups, and the scheme
-  // must be "http".
+  // hostname and scheme of |url| must match the corresponding parameters
+  // passed as constructor arguments.
   void SetResponse(const GURL& url, const base::FilePath& path);
 
   // Identical to SetResponse except that query parameters are ignored on
@@ -38,6 +43,9 @@
  private:
   class Delegate;
 
+  const std::string scheme_;
+  const std::string hostname_;
+
   // After creation, |delegate_| lives on the IO thread, and a task to delete
   // it is posted from ~URLRequestPrepackagedInterceptor().
   Delegate* delegate_;
@@ -45,6 +53,17 @@
   DISALLOW_COPY_AND_ASSIGN(URLRequestPrepackagedInterceptor);
 };
 
+// Specialization of URLRequestPrepackagedInterceptor where scheme is "http" and
+// hostname is "localhost".
+class URLLocalHostRequestPrepackagedInterceptor
+    : public URLRequestPrepackagedInterceptor {
+ public:
+  URLLocalHostRequestPrepackagedInterceptor();
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(URLLocalHostRequestPrepackagedInterceptor);
+};
+
 }  // namespace content
 
 #endif  // CHROME_BROWSER_COMPONENT_UPDATER_COMPONENT_UPDATER_INTERCEPTOR_H_
diff --git a/content/test/net/url_request_slow_download_job.cc b/content/test/net/url_request_slow_download_job.cc
index 62e3829..7b46136 100644
--- a/content/test/net/url_request_slow_download_job.cc
+++ b/content/test/net/url_request_slow_download_job.cc
@@ -37,7 +37,7 @@
     URLRequestSlowDownloadJob::pending_requests_ = LAZY_INSTANCE_INITIALIZER;
 
 void URLRequestSlowDownloadJob::Start() {
-  MessageLoop::current()->PostTask(
+  base::MessageLoop::current()->PostTask(
       FROM_HERE,
       base::Bind(&URLRequestSlowDownloadJob::StartAsync,
                  weak_factory_.GetWeakPtr()));
@@ -102,7 +102,7 @@
       should_error_download_(false),
       should_finish_download_(false),
       buffer_size_(0),
-      ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) {
+      weak_factory_(this) {
 }
 
 void URLRequestSlowDownloadJob::StartAsync() {
@@ -186,7 +186,7 @@
       buffer_ = buf;
       buffer_size_ = buf_size;
       SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0));
-      MessageLoop::current()->PostDelayedTask(
+      base::MessageLoop::current()->PostDelayedTask(
           FROM_HERE,
           base::Bind(&URLRequestSlowDownloadJob::CheckDoneStatus,
                      weak_factory_.GetWeakPtr()),
@@ -215,7 +215,7 @@
     NotifyDone(net::URLRequestStatus(
         net::URLRequestStatus::FAILED, net::ERR_CONNECTION_RESET));
   } else {
-    MessageLoop::current()->PostDelayedTask(
+    base::MessageLoop::current()->PostDelayedTask(
         FROM_HERE,
         base::Bind(&URLRequestSlowDownloadJob::CheckDoneStatus,
                    weak_factory_.GetWeakPtr()),
diff --git a/content/test/test_content_client.cc b/content/test/test_content_client.cc
index fa09e9f..abd1aea 100644
--- a/content/test/test_content_client.cc
+++ b/content/test/test_content_client.cc
@@ -8,7 +8,7 @@
 #include "base/files/file_path.h"
 #include "base/logging.h"
 #include "base/path_service.h"
-#include "base/string_piece.h"
+#include "base/strings/string_piece.h"
 
 namespace content {
 
diff --git a/content/test/test_web_contents.cc b/content/test/test_web_contents.cc
index 678aa1f..a51be65 100644
--- a/content/test/test_web_contents.cc
+++ b/content/test/test_web_contents.cc
@@ -88,7 +88,7 @@
   DidNavigate(render_view_host, params);
 }
 
-webkit_glue::WebPreferences TestWebContents::TestGetWebkitPrefs() {
+WebPreferences TestWebContents::TestGetWebkitPrefs() {
   return GetWebkitPrefs();
 }
 
diff --git a/content/test/test_web_contents.h b/content/test/test_web_contents.h
index 644c45d..569edb9 100644
--- a/content/test/test_web_contents.h
+++ b/content/test/test_web_contents.h
@@ -42,7 +42,7 @@
                                            const GURL& url,
                                            const Referrer& referrer,
                                            PageTransition transition) OVERRIDE;
-  virtual webkit_glue::WebPreferences TestGetWebkitPrefs() OVERRIDE;
+  virtual WebPreferences TestGetWebkitPrefs() OVERRIDE;
 
   TestRenderViewHost* pending_test_rvh() const;
 
diff --git a/content/test/webrtc_audio_device_test.cc b/content/test/webrtc_audio_device_test.cc
index 1ebcce9..7bd5b30 100644
--- a/content/test/webrtc_audio_device_test.cc
+++ b/content/test/webrtc_audio_device_test.cc
@@ -43,11 +43,6 @@
 #include "base/win/scoped_com_initializer.h"
 #endif
 
-#if defined(OS_ANDROID)
-#include "base/android/jni_android.h"
-#include "media/audio/audio_manager_base.h"
-#endif
-
 using media::AudioParameters;
 using media::ChannelLayout;
 using testing::_;
@@ -87,12 +82,11 @@
 class ReplaceContentClientRenderer {
  public:
   explicit ReplaceContentClientRenderer(ContentRendererClient* new_renderer) {
-    saved_renderer_ = GetContentClient()->renderer();
-    GetContentClient()->set_renderer_for_testing(new_renderer);
+    saved_renderer_ = SetRendererClientForTesting(new_renderer);
   }
   ~ReplaceContentClientRenderer() {
     // Restore the original renderer.
-    GetContentClient()->set_renderer_for_testing(saved_renderer_);
+    SetRendererClientForTesting(saved_renderer_);
   }
  private:
   ContentRendererClient* saved_renderer_;
@@ -123,7 +117,7 @@
 };
 
 ACTION_P(QuitMessageLoop, loop_or_proxy) {
-  loop_or_proxy->PostTask(FROM_HERE, MessageLoop::QuitClosure());
+  loop_or_proxy->PostTask(FROM_HERE, base::MessageLoop::QuitClosure());
 }
 
 WebRTCAudioDeviceTest::WebRTCAudioDeviceTest()
@@ -134,11 +128,6 @@
 WebRTCAudioDeviceTest::~WebRTCAudioDeviceTest() {}
 
 void WebRTCAudioDeviceTest::SetUp() {
-#if defined(OS_ANDROID)
-    media::AudioManagerBase::RegisterAudioManager(
-        base::android::AttachCurrentThread());
-#endif
-
   // This part sets up a RenderThread environment to ensure that
   // RenderThread::current() (<=> TLS pointer) is valid.
   // Main parts are inspired by the RenderViewFakeResourcesTest.
@@ -146,8 +135,8 @@
   saved_content_renderer_.reset(
       new ReplaceContentClientRenderer(&content_renderer_client_));
   mock_process_.reset(new WebRTCMockRenderProcess());
-  ui_thread_.reset(new TestBrowserThread(BrowserThread::UI,
-                                         MessageLoop::current()));
+  ui_thread_.reset(
+      new TestBrowserThread(BrowserThread::UI, base::MessageLoop::current()));
 
   // Construct the resource context on the UI thread.
   resource_context_.reset(new MockRTCResourceContext);
@@ -213,8 +202,8 @@
 #endif
 
   // Set the current thread as the IO thread.
-  io_thread_.reset(new TestBrowserThread(BrowserThread::IO,
-                                         MessageLoop::current()));
+  io_thread_.reset(
+      new TestBrowserThread(BrowserThread::IO, base::MessageLoop::current()));
 
   // Populate our resource context.
   test_request_context_.reset(new net::TestURLRequestContext());
@@ -296,13 +285,13 @@
       return true;
   }
 
-  if (audio_render_host_.get()) {
+  if (audio_render_host_) {
     bool message_was_ok = false;
     if (audio_render_host_->OnMessageReceived(message, &message_was_ok))
       return true;
   }
 
-  if (audio_input_renderer_host_.get()) {
+  if (audio_input_renderer_host_) {
     bool message_was_ok = false;
     if (audio_input_renderer_host_->OnMessageReceived(message, &message_was_ok))
       return true;
@@ -328,7 +317,7 @@
 }
 
 void WebRTCAudioDeviceTest::WaitForAudioManagerCompletion() {
-  if (audio_manager_.get())
+  if (audio_manager_)
     WaitForMessageLoopCompletion(audio_manager_->GetMessageLoop());
 }
 
diff --git a/content/test/webrtc_audio_device_test.h b/content/test/webrtc_audio_device_test.h
index ed9760d..f15e3bb 100644
--- a/content/test/webrtc_audio_device_test.h
+++ b/content/test/webrtc_audio_device_test.h
@@ -151,7 +151,7 @@
   std::string GetTestDataPath(const base::FilePath::StringType& file_name);
 
   scoped_ptr<ReplaceContentClientRenderer> saved_content_renderer_;
-  MessageLoopForUI message_loop_;
+  base::MessageLoopForUI message_loop_;
   ContentRendererClient content_renderer_client_;
   RenderThreadImpl* render_thread_;  // Owned by mock_process_.
   scoped_ptr<WebRTCMockRenderProcess> mock_process_;
diff --git a/content/utility/utility_main.cc b/content/utility/utility_main.cc
index 549af2c..04f7714 100644
--- a/content/utility/utility_main.cc
+++ b/content/utility/utility_main.cc
@@ -5,9 +5,10 @@
 #include "base/command_line.h"
 #include "base/hi_res_timer_manager.h"
 #include "base/message_loop.h"
-#include "base/system_monitor/system_monitor.h"
+#include "base/power_monitor/power_monitor.h"
 #include "base/threading/platform_thread.h"
 #include "content/common/child_process.h"
+#include "content/common/sandbox_linux.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/common/main_function_params.h"
 #include "content/public/common/sandbox_init.h"
@@ -22,15 +23,15 @@
 // Mainline routine for running as the utility process.
 int UtilityMain(const MainFunctionParams& parameters) {
   // The main message loop of the utility process.
-  MessageLoop main_message_loop;
+  base::MessageLoop main_message_loop;
   base::PlatformThread::SetName("CrUtilityMain");
 
-  base::SystemMonitor system_monitor;
+  base::PowerMonitor power_monitor;
   HighResolutionTimerManager hi_res_timer_manager;
 
 #if defined(OS_LINUX)
   // Initialize the sandbox before any thread is created.
-  InitializeSandbox();
+  LinuxSandbox::InitializeSandbox();
 #endif
 
   ChildProcess utility_process;
@@ -47,7 +48,7 @@
   }
 #endif
 
-  MessageLoop::current()->Run();
+  base::MessageLoop::current()->Run();
 
   return 0;
 }
diff --git a/content/utility/utility_thread_impl.cc b/content/utility/utility_thread_impl.cc
index 4febffa..eed1704 100644
--- a/content/utility/utility_thread_impl.cc
+++ b/content/utility/utility_thread_impl.cc
@@ -45,6 +45,9 @@
 }
 
 UtilityThreadImpl::~UtilityThreadImpl() {
+}
+
+void UtilityThreadImpl::Shutdown() {
   WebKit::shutdown();
 }
 
diff --git a/content/utility/utility_thread_impl.h b/content/utility/utility_thread_impl.h
index da2ffbd..31c51a1 100644
--- a/content/utility/utility_thread_impl.h
+++ b/content/utility/utility_thread_impl.h
@@ -27,6 +27,7 @@
  public:
   UtilityThreadImpl();
   virtual ~UtilityThreadImpl();
+  virtual void Shutdown() OVERRIDE;
 
   virtual bool Send(IPC::Message* msg) OVERRIDE;
   virtual void ReleaseProcessIfNeeded() OVERRIDE;
diff --git a/content/worker/websharedworker_stub.cc b/content/worker/websharedworker_stub.cc
index f51487f..39986cc 100644
--- a/content/worker/websharedworker_stub.cc
+++ b/content/worker/websharedworker_stub.cc
@@ -23,7 +23,7 @@
     const WorkerAppCacheInitInfo& appcache_init_info)
     : route_id_(route_id),
       appcache_init_info_(appcache_init_info),
-      ALLOW_THIS_IN_INITIALIZER_LIST(client_(route_id, this)),
+      client_(route_id, this),
       name_(name),
       started_(false),
       worker_devtools_agent_(NULL) {
diff --git a/content/worker/websharedworkerclient_proxy.cc b/content/worker/websharedworkerclient_proxy.cc
index 049361e..4db74b8 100644
--- a/content/worker/websharedworkerclient_proxy.cc
+++ b/content/worker/websharedworkerclient_proxy.cc
@@ -44,7 +44,7 @@
     : route_id_(route_id),
       appcache_host_id_(0),
       stub_(stub),
-      ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)),
+      weak_factory_(this),
       devtools_agent_(NULL) {
 }
 
@@ -207,10 +207,10 @@
   // process, and avoids the crashed worker infobar from appearing to the new
   // page. It's ok to post several of theese, because the first executed task
   // will exit the message loop and subsequent ones won't be executed.
-  MessageLoop::current()->PostDelayedTask(FROM_HERE,
-      base::Bind(
-          &WebSharedWorkerClientProxy::workerContextDestroyed,
-          weak_factory_.GetWeakPtr()),
+  base::MessageLoop::current()->PostDelayedTask(
+      FROM_HERE,
+      base::Bind(&WebSharedWorkerClientProxy::workerContextDestroyed,
+                 weak_factory_.GetWeakPtr()),
       base::TimeDelta::FromSeconds(kMaxTimeForRunawayWorkerSeconds));
 }
 
diff --git a/content/worker/worker_main.cc b/content/worker/worker_main.cc
index 192cc57..459e907 100644
--- a/content/worker/worker_main.cc
+++ b/content/worker/worker_main.cc
@@ -6,10 +6,11 @@
 #include "base/command_line.h"
 #include "base/hi_res_timer_manager.h"
 #include "base/message_loop.h"
+#include "base/power_monitor/power_monitor.h"
 #include "base/string_util.h"
-#include "base/system_monitor/system_monitor.h"
 #include "base/threading/platform_thread.h"
 #include "content/common/child_process.h"
+#include "content/common/sandbox_linux.h"
 #include "content/public/common/main_function_params.h"
 #include "content/public/common/sandbox_init.h"
 #include "content/worker/worker_thread.h"
@@ -27,10 +28,10 @@
 // Mainline routine for running as the worker process.
 int WorkerMain(const MainFunctionParams& parameters) {
   // The main message loop of the worker process.
-  MessageLoop main_message_loop;
+  base::MessageLoop main_message_loop;
   base::PlatformThread::SetName("CrWorkerMain");
 
-  base::SystemMonitor system_monitor;
+  base::PowerMonitor power_monitor;
   HighResolutionTimerManager hi_res_timer_manager;
 
 #if defined(OS_WIN)
@@ -53,7 +54,7 @@
 #elif defined(OS_LINUX)
   // On Linux, the sandbox must be initialized early, before any thread is
   // created.
-  InitializeSandbox();
+  LinuxSandbox::InitializeSandbox();
 #endif
 
   ChildProcess worker_process;
@@ -66,7 +67,7 @@
 
   // Load the accelerator table from the browser executable and tell the
   // message loop to use it when translating messages.
-  MessageLoop::current()->Run();
+  base::MessageLoop::current()->Run();
 
   return 0;
 }
diff --git a/content/worker/worker_thread.cc b/content/worker/worker_thread.cc
index e7cc319..a88f615 100644
--- a/content/worker/worker_thread.cc
+++ b/content/worker/worker_thread.cc
@@ -18,7 +18,6 @@
 #include "ipc/ipc_sync_channel.h"
 #include "third_party/WebKit/Source/Platform/chromium/public/WebBlobRegistry.h"
 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDatabase.h"
-#include "third_party/WebKit/Source/WebKit/chromium/public/WebIDBFactory.h"
 #include "third_party/WebKit/Source/WebKit/chromium/public/WebKit.h"
 #include "third_party/WebKit/Source/WebKit/chromium/public/WebRuntimeFeatures.h"
 #include "webkit/glue/webkit_glue.h"
@@ -66,9 +65,6 @@
       !command_line.HasSwitch(switches::kDisableDesktopNotifications));
 #endif
 
-  WebRuntimeFeatures::enableSockets(
-      !command_line.HasSwitch(switches::kDisableWebSockets));
-
   WebRuntimeFeatures::enableFileSystem(
       !command_line.HasSwitch(switches::kDisableFileSystem));
 
@@ -76,6 +72,9 @@
 }
 
 WorkerThread::~WorkerThread() {
+}
+
+void WorkerThread::Shutdown() {
   // Shutdown in reverse of the initialization order.
   channel()->RemoveFilter(indexed_db_message_filter_.get());
   indexed_db_message_filter_ = NULL;
diff --git a/content/worker/worker_thread.h b/content/worker/worker_thread.h
index aaa78a3..bc51f49 100644
--- a/content/worker/worker_thread.h
+++ b/content/worker/worker_thread.h
@@ -23,6 +23,7 @@
  public:
   WorkerThread();
   virtual ~WorkerThread();
+  virtual void Shutdown() OVERRIDE;
 
   // Returns the one worker thread.
   static WorkerThread* current();
diff --git a/content/worker/worker_webkitplatformsupport_impl.cc b/content/worker/worker_webkitplatformsupport_impl.cc
index b81990d..f6a9a20 100644
--- a/content/worker/worker_webkitplatformsupport_impl.cc
+++ b/content/worker/worker_webkitplatformsupport_impl.cc
@@ -89,13 +89,13 @@
 }
 
 WebFileSystem* WorkerWebKitPlatformSupportImpl::fileSystem() {
-  if (!web_file_system_.get())
+  if (!web_file_system_)
     web_file_system_.reset(new WebFileSystemImpl());
   return web_file_system_.get();
 }
 
 WebFileUtilities* WorkerWebKitPlatformSupportImpl::fileUtilities() {
-  if (!file_utilities_.get()) {
+  if (!file_utilities_) {
     file_utilities_.reset(new FileUtilities(thread_safe_sender_));
     file_utilities_->set_sandbox_enabled(sandboxEnabled());
   }
@@ -195,7 +195,7 @@
 }
 
 WebKit::WebIDBFactory* WorkerWebKitPlatformSupportImpl::idbFactory() {
-  if (!web_idb_factory_.get())
+  if (!web_idb_factory_)
     web_idb_factory_.reset(new RendererWebIDBFactoryImpl());
   return web_idb_factory_.get();
 }
@@ -282,7 +282,7 @@
 }
 
 WebBlobRegistry* WorkerWebKitPlatformSupportImpl::blobRegistry() {
-  if (!blob_registry_.get() && thread_safe_sender_.get())
+  if (!blob_registry_.get() && thread_safe_sender_)
     blob_registry_.reset(new WebBlobRegistryImpl(thread_safe_sender_));
   return blob_registry_.get();
 }
diff --git a/content/worker/worker_webkitplatformsupport_impl.h b/content/worker/worker_webkitplatformsupport_impl.h
index 7f95bd7..6274a74 100644
--- a/content/worker/worker_webkitplatformsupport_impl.h
+++ b/content/worker/worker_webkitplatformsupport_impl.h
@@ -7,8 +7,8 @@
 
 #include "base/memory/scoped_ptr.h"
 #include "content/common/webkitplatformsupport_impl.h"
+#include "third_party/WebKit/Source/Platform/chromium/public/WebIDBFactory.h"
 #include "third_party/WebKit/Source/Platform/chromium/public/WebMimeRegistry.h"
-#include "third_party/WebKit/Source/WebKit/chromium/public/WebIDBFactory.h"
 
 namespace WebKit {
 class WebFileUtilities;
diff --git a/content/zygote/zygote_linux.cc b/content/zygote/zygote_linux.cc
index b546e15..5d26a05 100644
--- a/content/zygote/zygote_linux.cc
+++ b/content/zygote/zygote_linux.cc
@@ -67,6 +67,8 @@
 
 }  // namespace
 
+const int Zygote::kMagicSandboxIPCDescriptor;
+
 Zygote::Zygote(int sandbox_flags,
                ZygoteForkDelegate* helper)
     : sandbox_flags_(sandbox_flags),
@@ -434,9 +436,6 @@
   if (!child_pid) {
     // This is the child process.
 
-    // At this point, we finally know our process type.
-    LinuxSandbox::GetInstance()->PreinitializeSandboxFinish(process_type);
-
     close(kBrowserDescriptor);  // Our socket from the browser.
     if (UsingSUIDSandbox())
       close(kZygoteIdFd);  // Another socket from the browser.
diff --git a/content/zygote/zygote_main.h b/content/zygote/zygote_main.h
new file mode 100644
index 0000000..6470232
--- /dev/null
+++ b/content/zygote/zygote_main.h
@@ -0,0 +1,18 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_ZYGOTE_ZYGOTE_MAIN_H_
+#define CONTENT_ZYGOTE_ZYGOTE_MAIN_H_
+
+namespace content {
+
+struct MainFunctionParams;
+class ZygoteForkDelegate;
+
+bool ZygoteMain(const MainFunctionParams& params,
+                ZygoteForkDelegate* forkdelegate);
+
+}  // namespace content
+
+#endif  // CONTENT_ZYGOTE_ZYGOTE_MAIN_H_
diff --git a/content/zygote/zygote_main_linux.cc b/content/zygote/zygote_main_linux.cc
index fd4a709..ca75518 100644
--- a/content/zygote/zygote_main_linux.cc
+++ b/content/zygote/zygote_main_linux.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 "content/zygote/zygote_main.h"
+
 #include <dlfcn.h>
 #include <fcntl.h>
 #include <pthread.h>
@@ -38,6 +40,7 @@
 #include "sandbox/linux/services/libc_urandom_override.h"
 #include "sandbox/linux/suid/client/setuid_sandbox_client.h"
 #include "third_party/icu/public/i18n/unicode/timezone.h"
+#include "third_party/libjingle/overrides/init_webrtc.h"
 #include "third_party/skia/include/ports/SkFontConfigInterface.h"
 
 #if defined(OS_LINUX)
@@ -279,6 +282,9 @@
   // Ensure access to the Pepper plugins before the sandbox is turned on.
   PepperPluginRegistry::PreloadModules();
 #endif
+#if defined(ENABLE_WEBRTC)
+  InitializeWebRtcModule();
+#endif
 }
 
 #if !defined(CHROMIUM_SELINUX)
@@ -439,7 +445,7 @@
 
   PreSandboxInit();
   SkFontConfigInterface::SetGlobal(
-      new FontConfigIPC(Zygote::kMagicSandboxIPCDescriptor)))->unref();
+      new FontConfigIPC(Zygote::kMagicSandboxIPCDescriptor))->unref();
   return true;
 }
 
@@ -454,10 +460,7 @@
 
   LinuxSandbox* linux_sandbox = LinuxSandbox::GetInstance();
   // This will pre-initialize the various sandboxes that need it.
-  // There need to be a corresponding call to PreinitializeSandboxFinish()
-  // for each new process, this will be done in the Zygote child, once we know
-  // our process type.
-  linux_sandbox->PreinitializeSandboxBegin();
+  linux_sandbox->PreinitializeSandbox();
 
   sandbox::SetuidSandboxClient* setuid_sandbox =
       linux_sandbox->setuid_sandbox_client();