Revved to chromium e3159f0995c1a21e0d97edce19ca3048b314a9cb refs/remotes/origin/HEAD

filter gyp out of build/landmines.py

filter pepper out of mojo/examples/BUILD.gn

filter html_viewer out of mojo/services/BUILD.gn

filter js out of mojo/BUILD.gn

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

applied patch gpu_media.patch

applied patch cc_strip_video.patch

applied patch ui_test_support.patch

applied patch remove_ipc_deps.patch

applied patch ui_compositor.patch

applied patch net_sql.patch
diff --git a/AUTHORS b/AUTHORS
index a6a5491..a61c7a6 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -96,6 +96,7 @@
 Daegyu Lee <na7jun8gi@gmail.com>
 Dai Chunyang <chunyang.dai@intel.com>
 Daniel Bomar <dbdaniel42@gmail.com>
+Daniel Imms <daniimms@amazon.com>
 Daniel Johnson <danielj41@gmail.com>
 Daniel Nishi <dhnishi@gmail.com>
 Daniel Shaulov <dshaulov@ptc.com>
diff --git a/DEPS b/DEPS
index 2301210..0811444 100644
--- a/DEPS
+++ b/DEPS
@@ -30,16 +30,16 @@
   'skia_git': 'https://skia.googlesource.com',
   'boringssl_git': 'https://boringssl.googlesource.com',
   'sfntly_revision': '1bdaae8fc788a5ac8936d68bf24f37d977a13dac',
-  'skia_revision': '783991585be67da3286680d850a99c5410885965',
+  'skia_revision': '43b8b36b20ae00e2d78421c4cda1f3f922983a20',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and V8 without interference from each other.
   'v8_branch': 'trunk',
-  'v8_revision': 'b287d3641c8169c74f83a44b33ada13cf3cefaf2', # from svn revision 24398
+  'v8_revision': '2f51c28a975ceaa07ce8f8b2e42ac0f0c5a57802', # from svn revision 24723
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ANGLE
   # and whatever else without interference from each other.
-  "angle_revision": "5e0c80adc9d9e7b4a7f5c89c4fe21be192c51774",
+  "angle_revision": "8e92923010c568a445c0f22e1a36f462fcabc8f3",
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling build tools
   # and whatever else without interference from each other.
@@ -151,7 +151,7 @@
         Var('chromium_git') + '/external/jsr-305.git' + '@' + '642c508235471f7220af6d5df2d3210e3bfc0919',
 
     'src/third_party/android_tools':
-       Var('chromium_git') + '/android_tools.git' + '@' + 'd2b86205ff973a3844020feacb35ca6b1d82efbe',
+     Var('chromium_git') + '/android_tools.git' + '@' + '36bf7ac9a608f95f642ec64a743feea3b2e5a8d5',
 
     'src/third_party/freetype':
        Var('chromium_git') + '/chromium/src/third_party/freetype.git' + '@' + 'a2b9955b49034a51dfbc8bf9f4e9d312149cecac',
diff --git a/base/BUILD.gn b/base/BUILD.gn
index d783ee0..0bbc91b 100644
--- a/base/BUILD.gn
+++ b/base/BUILD.gn
@@ -39,6 +39,8 @@
     "android/fifo_utils.h",
     "android/important_file_writer_android.cc",
     "android/important_file_writer_android.h",
+    "android/locale_utils.cc",
+    "android/locale_utils.h",
     "android/scoped_java_ref.cc",
     "android/scoped_java_ref.h",
     "android/jni_android.cc",
@@ -1398,6 +1400,7 @@
       "android/java/src/org/chromium/base/ImportantFileWriterAndroid.java",
       "android/java/src/org/chromium/base/JNIUtils.java",
       "android/java/src/org/chromium/base/library_loader/LibraryLoader.java",
+      "android/java/src/org/chromium/base/LocaleUtils.java",
       "android/java/src/org/chromium/base/MemoryPressureListener.java",
       "android/java/src/org/chromium/base/JavaHandlerThread.java",
       "android/java/src/org/chromium/base/PathService.java",
diff --git a/base/android/base_jni_registrar.cc b/base/android/base_jni_registrar.cc
index b6d8a28..c0f0af7 100644
--- a/base/android/base_jni_registrar.cc
+++ b/base/android/base_jni_registrar.cc
@@ -16,6 +16,7 @@
 #include "base/android/jni_android.h"
 #include "base/android/jni_registrar.h"
 #include "base/android/jni_utils.h"
+#include "base/android/locale_utils.h"
 #include "base/android/memory_pressure_listener_android.h"
 #include "base/android/path_service_android.h"
 #include "base/android/path_utils.h"
@@ -42,6 +43,7 @@
   { "ImportantFileWriterAndroid",
     base::android::RegisterImportantFileWriterAndroid },
   { "JNIUtils", base::android::RegisterJNIUtils },
+  { "LocaleUtils", base::android::RegisterLocaleUtils },
   { "MemoryPressureListenerAndroid",
       base::android::MemoryPressureListenerAndroid::Register },
   { "JavaHandlerThread", base::android::JavaHandlerThread::RegisterBindings },
diff --git a/base/android/java/src/org/chromium/base/BaseSwitches.java b/base/android/java/src/org/chromium/base/BaseSwitches.java
index fe13d7b..11e10f5 100644
--- a/base/android/java/src/org/chromium/base/BaseSwitches.java
+++ b/base/android/java/src/org/chromium/base/BaseSwitches.java
@@ -23,6 +23,9 @@
     // Adds additional thread idle time information into the trace event output.
     public static final String ENABLE_IDLE_TRACING = "enable-idle-tracing";
 
+    // Default country code to be used for search engine localization.
+    public static final String DEFAULT_COUNTRY_CODE_AT_INSTALL = "default-country-code";
+
     // Prevent instantiation.
     private BaseSwitches() {}
 }
diff --git a/base/android/java/src/org/chromium/base/LocaleUtils.java b/base/android/java/src/org/chromium/base/LocaleUtils.java
index 31d4127..4f97d3a 100644
--- a/base/android/java/src/org/chromium/base/LocaleUtils.java
+++ b/base/android/java/src/org/chromium/base/LocaleUtils.java
@@ -20,6 +20,7 @@
      * @return the default locale, translating Android deprecated
      * language codes into the modern ones used by Chromium.
      */
+    @CalledByNative
     public static String getDefaultLocale() {
         Locale locale = Locale.getDefault();
         String language = locale.getLanguage();
@@ -38,4 +39,17 @@
         }
         return country.isEmpty() ? language : language + "-" + country;
     }
+
+    /**
+     * Get the default country code set during install.
+     * @return country code.
+     */
+    @CalledByNative
+    private static String getDefaultCountryCode() {
+        CommandLine commandLine = CommandLine.getInstance();
+        return commandLine.hasSwitch(BaseSwitches.DEFAULT_COUNTRY_CODE_AT_INSTALL) ?
+                commandLine.getSwitchValue(BaseSwitches.DEFAULT_COUNTRY_CODE_AT_INSTALL) :
+                Locale.getDefault().getCountry();
+    }
+
 }
diff --git a/base/android/java/src/org/chromium/base/library_loader/LibraryLoader.java b/base/android/java/src/org/chromium/base/library_loader/LibraryLoader.java
index 86bca43..dcf0754 100644
--- a/base/android/java/src/org/chromium/base/library_loader/LibraryLoader.java
+++ b/base/android/java/src/org/chromium/base/library_loader/LibraryLoader.java
@@ -307,6 +307,12 @@
     }
 
     // Called after all native initializations are complete.
+    public static void onNativeInitializationComplete(Context context) {
+        onNativeInitializationComplete();
+    }
+
+    // Called after all native initializations are complete.
+    @Deprecated
     public static void onNativeInitializationComplete() {
         recordBrowserProcessHistogram();
         nativeRecordNativeLibraryHack(sNativeLibraryHackWasUsed);
diff --git a/base/android/linker/linker_jni.cc b/base/android/linker/linker_jni.cc
index 81c6647..a545c52 100644
--- a/base/android/linker/linker_jni.cc
+++ b/base/android/linker/linker_jni.cc
@@ -599,19 +599,18 @@
       __FUNCTION__, apkfile_name_c_str);
   void* address = mmap(NULL, PAGE_SIZE, PROT_EXEC, MAP_PRIVATE, fd, 0);
 
-  jboolean success;
+  jboolean status;
   if (address == MAP_FAILED) {
-    success = false;
+    status = false;
   } else {
-    success = true;
+    status = true;
     munmap(address, PAGE_SIZE);
   }
 
   close(fd);
 
-  LOG_INFO("  %ssupported\n", success ? "" : "NOT ");
-  return success;
-
+  LOG_INFO("%s: %s\n", __FUNCTION__, status ? "Supported" : "NOT supported");
+  return status;
 }
 
 const JNINativeMethod kNativeMethods[] = {
diff --git a/base/android/locale_utils.cc b/base/android/locale_utils.cc
new file mode 100644
index 0000000..af46f89
--- /dev/null
+++ b/base/android/locale_utils.cc
@@ -0,0 +1,31 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/android/locale_utils.h"
+
+#include "base/android/jni_android.h"
+#include "base/android/jni_string.h"
+#include "jni/LocaleUtils_jni.h"
+
+namespace base {
+namespace android {
+
+std::string GetDefaultCountryCode() {
+  JNIEnv* env = base::android::AttachCurrentThread();
+  return ConvertJavaStringToUTF8(Java_LocaleUtils_getDefaultCountryCode(env));
+}
+
+std::string GetDefaultLocale() {
+  JNIEnv* env = base::android::AttachCurrentThread();
+  ScopedJavaLocalRef<jstring> locale = Java_LocaleUtils_getDefaultLocale(
+      env);
+  return ConvertJavaStringToUTF8(locale);
+}
+
+bool RegisterLocaleUtils(JNIEnv* env) {
+  return RegisterNativesImpl(env);
+}
+
+}  // namespace android
+}  // namespace base
diff --git a/base/android/locale_utils.h b/base/android/locale_utils.h
new file mode 100644
index 0000000..9e03b83
--- /dev/null
+++ b/base/android/locale_utils.h
@@ -0,0 +1,27 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_ANDROID_LOCALE_UTILS_H_
+#define BASE_ANDROID_LOCALE_UTILS_H_
+
+#include <jni.h>
+
+#include <string>
+
+#include "base/base_export.h"
+
+namespace base {
+namespace android {
+
+BASE_EXPORT std::string GetDefaultCountryCode();
+
+// Return the current default locale of the device.
+BASE_EXPORT std::string GetDefaultLocale();
+
+BASE_EXPORT bool RegisterLocaleUtils(JNIEnv* env);
+
+}  // namespace android
+}  // namespace base
+
+#endif  // BASE_ANDROID_LOCALE_UTILS_H_
diff --git a/base/base.gyp b/base/base.gyp
index 95f6f7d..871b8e5 100644
--- a/base/base.gyp
+++ b/base/base.gyp
@@ -1276,6 +1276,7 @@
             'android/java/src/org/chromium/base/ImportantFileWriterAndroid.java',
             'android/java/src/org/chromium/base/JNIUtils.java',
             'android/java/src/org/chromium/base/library_loader/LibraryLoader.java',
+            'android/java/src/org/chromium/base/LocaleUtils.java',
             'android/java/src/org/chromium/base/MemoryPressureListener.java',
             'android/java/src/org/chromium/base/JavaHandlerThread.java',
             'android/java/src/org/chromium/base/PathService.java',
diff --git a/base/base.gypi b/base/base.gypi
index 5cd8b8c..2dfde09 100644
--- a/base/base.gypi
+++ b/base/base.gypi
@@ -45,6 +45,8 @@
           'android/fifo_utils.h',
           'android/important_file_writer_android.cc',
           'android/important_file_writer_android.h',
+          'android/locale_utils.h',
+          'android/locale_utils.cc',
           'android/scoped_java_ref.cc',
           'android/scoped_java_ref.h',
           'android/jni_android.cc',
diff --git a/base/files/file.h b/base/files/file.h
index 1913bc7..4110d51 100644
--- a/base/files/file.h
+++ b/base/files/file.h
@@ -249,7 +249,8 @@
   // doesn't exist, |false| is returned.
   bool SetLength(int64 length);
 
-  // Flushes the buffers.
+  // Instructs the filesystem to flush the file to disk. (POSIX: fsync, Windows:
+  // FlushFileBuffers).
   bool Flush();
 
   // Updates the file times.
diff --git a/base/files/important_file_writer.cc b/base/files/important_file_writer.cc
index c996da2..d7579ab 100644
--- a/base/files/important_file_writer.cc
+++ b/base/files/important_file_writer.cc
@@ -33,6 +33,7 @@
   FAILED_CLOSING,
   FAILED_WRITING,
   FAILED_RENAMING,
+  FAILED_FLUSHING,
   TEMP_FILE_FAILURE_MAX
 };
 
@@ -69,7 +70,7 @@
   CHECK_LE(data.length(), static_cast<size_t>(kint32max));
   int bytes_written = tmp_file.Write(0, data.data(),
                                      static_cast<int>(data.length()));
-  tmp_file.Flush();  // Ignore return value.
+  bool flush_success = tmp_file.Flush();
   tmp_file.Close();
 
   if (bytes_written < static_cast<int>(data.length())) {
@@ -79,6 +80,12 @@
     return false;
   }
 
+  if (!flush_success) {
+    LogFailure(path, FAILED_FLUSHING, "error flushing");
+    base::DeleteFile(tmp_file_path, false);
+    return false;
+  }
+
   if (!base::ReplaceFile(tmp_file_path, path, NULL)) {
     LogFailure(path, FAILED_RENAMING, "could not rename temporary file");
     base::DeleteFile(tmp_file_path, false);
diff --git a/base/mac/scoped_sending_event_unittest.mm b/base/mac/scoped_sending_event_unittest.mm
index 9ae9985..95f6eba 100644
--- a/base/mac/scoped_sending_event_unittest.mm
+++ b/base/mac/scoped_sending_event_unittest.mm
@@ -4,12 +4,39 @@
 
 #import "base/mac/scoped_sending_event.h"
 
+#import <Foundation/Foundation.h>
+
+#include "base/mac/scoped_nsobject.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
+@interface ScopedSendingEventTestCrApp : NSObject <CrAppControlProtocol> {
+ @private
+  BOOL handlingSendEvent_;
+}
+@property(nonatomic, assign, getter=isHandlingSendEvent) BOOL handlingSendEvent;
+@end
+
+@implementation ScopedSendingEventTestCrApp
+@synthesize handlingSendEvent = handlingSendEvent_;
+@end
+
 namespace {
 
+class ScopedSendingEventTest : public testing::Test {
+ public:
+  ScopedSendingEventTest() : app_([[ScopedSendingEventTestCrApp alloc] init]) {
+    NSApp = app_.get();
+  }
+  virtual ~ScopedSendingEventTest() {
+    NSApp = nil;
+  }
+
+ private:
+  base::scoped_nsobject<ScopedSendingEventTestCrApp> app_;
+};
+
 // Sets the flag within scope, resets when leaving scope.
-TEST(ScopedSendingEventTest, SetHandlingSendEvent) {
+TEST_F(ScopedSendingEventTest, SetHandlingSendEvent) {
   id<CrAppProtocol> app = NSApp;
   EXPECT_FALSE([app isHandlingSendEvent]);
   {
@@ -20,7 +47,7 @@
 }
 
 // Nested call restores previous value rather than resetting flag.
-TEST(ScopedSendingEventTest, NestedSetHandlingSendEvent) {
+TEST_F(ScopedSendingEventTest, NestedSetHandlingSendEvent) {
   id<CrAppProtocol> app = NSApp;
   EXPECT_FALSE([app isHandlingSendEvent]);
   {
diff --git a/base/mac/sdk_forward_declarations.h b/base/mac/sdk_forward_declarations.h
index 1729ea5..234b268 100644
--- a/base/mac/sdk_forward_declarations.h
+++ b/base/mac/sdk_forward_declarations.h
@@ -211,11 +211,10 @@
 BASE_EXPORT extern "C" NSString* const NSWindowDidEnterFullScreenNotification;
 BASE_EXPORT extern "C" NSString* const NSWindowDidExitFullScreenNotification;
 
-BASE_EXPORT extern "C" NSString* const
-    NSWindowDidFailToEnterFullScreenNotification;
-
-BASE_EXPORT extern "C" NSString* const
-    NSWindowDidFailToExitFullScreenNotification;
+@protocol NSWindowDelegateFullScreenAdditions
+- (void)windowDidFailToEnterFullScreen:(NSWindow*)window;
+- (void)windowDidFailToExitFullScreen:(NSWindow*)window;
+@end
 
 #endif  // MAC_OS_X_VERSION_10_7
 
diff --git a/base/mac/sdk_forward_declarations.mm b/base/mac/sdk_forward_declarations.mm
index 06d10f2..8f77422 100644
--- a/base/mac/sdk_forward_declarations.mm
+++ b/base/mac/sdk_forward_declarations.mm
@@ -20,12 +20,6 @@
 NSString* const NSWindowDidExitFullScreenNotification =
     @"NSWindowDidExitFullScreenNotification";
 
-NSString* const NSWindowDidFailToEnterFullScreenNotification =
-    @"NSWindowDidFailToEnterFullScreenNotification";
-
-NSString* const NSWindowDidFailToExitFullScreenNotification =
-    @"NSWindowDidFailToExitFullScreenNotification";
-
 #endif  // MAC_OS_X_VERSION_10_7
 
 // Replicate specific 10.10 SDK declarations for building with prior SDKs.
diff --git a/base/test/test_suite.cc b/base/test/test_suite.cc
index 23ffa1e..206507b 100644
--- a/base/test/test_suite.cc
+++ b/base/test/test_suite.cc
@@ -32,8 +32,6 @@
 #include "base/mac/scoped_nsautorelease_pool.h"
 #if defined(OS_IOS)
 #include "base/test/test_listener_ios.h"
-#else
-#include "base/test/mock_chrome_application_mac.h"
 #endif  // OS_IOS
 #endif  // OS_MACOSX
 
@@ -287,11 +285,6 @@
   }
 #endif
 
-#if defined(OS_MACOSX) && !defined(OS_IOS)
-  // Some of the app unit tests spin runloops.
-  mock_cr_app::RegisterMockCrApp();
-#endif
-
 #if defined(OS_IOS)
   InitIOSTestMessageLoop();
 #endif  // OS_IOS
diff --git a/base/threading/thread_restrictions.h b/base/threading/thread_restrictions.h
index 39f32a7..7c46fd2 100644
--- a/base/threading/thread_restrictions.h
+++ b/base/threading/thread_restrictions.h
@@ -19,7 +19,6 @@
 class HistogramSynchronizer;
 class NativeBackendKWallet;
 class ScopedAllowWaitForLegacyWebViewApi;
-class TestingAutomationProvider;
 
 namespace cc {
 class CompletionEvent;
@@ -177,7 +176,6 @@
   friend class content::ScopedAllowWaitForAndroidLayoutTests;
   friend class ::HistogramSynchronizer;
   friend class ::ScopedAllowWaitForLegacyWebViewApi;
-  friend class ::TestingAutomationProvider;
   friend class cc::CompletionEvent;
   friend class mojo::common::WatcherThreadManager;
   friend class remoting::AutoThread;
diff --git a/build/android/adb_logcat_monitor.py b/build/android/adb_logcat_monitor.py
index a2acfd1..a5ae785 100755
--- a/build/android/adb_logcat_monitor.py
+++ b/build/android/adb_logcat_monitor.py
@@ -83,7 +83,7 @@
                                 stderr=subprocess.PIPE).communicate()
     if err:
       logging.warning('adb device error %s', err.strip())
-    return re.findall('^(\w+)\tdevice$', out, re.MULTILINE)
+    return re.findall('^(\S+)\tdevice$', out, re.MULTILINE)
   except TimeoutException:
     logging.warning('"adb devices" command timed out')
     return []
diff --git a/build/android/adb_logcat_printer.py b/build/android/adb_logcat_printer.py
index f79a9e4..55176ab 100755
--- a/build/android/adb_logcat_printer.py
+++ b/build/android/adb_logcat_printer.py
@@ -78,7 +78,7 @@
   Returns:
     Mapping of device_id to a sorted list of file paths for a given device
   """
-  logcat_filter = re.compile(r'^logcat_(\w+)_(\d+)$')
+  logcat_filter = re.compile(r'^logcat_(\S+)_(\d+)$')
   # list of tuples (<device_id>, <seq num>, <full file path>)
   filtered_list = []
   for cur_file in os.listdir(base_dir):
diff --git a/build/android/finalize_apk_action.gypi b/build/android/finalize_apk_action.gypi
index 6187239..5ffbffa 100644
--- a/build/android/finalize_apk_action.gypi
+++ b/build/android/finalize_apk_action.gypi
@@ -25,7 +25,7 @@
     'conditions': [
         # Webview doesn't use zipalign or rezip_apk_jar.
         ['android_webview_build==0', {
-          'zipalign_path%': ['<!@(find <(android_sdk_root) -name zipalign)'],
+          'zipalign_path%': '<(android_sdk_tools)/zipalign',
           'rezip_apk_jar_path%': '<(PRODUCT_DIR)/lib.java/rezip_apk.jar'
         }, {
           'zipalign_path%': "",
diff --git a/build/android/gyp/javac.py b/build/android/gyp/javac.py
index b0ef7fd..6a3024b 100755
--- a/build/android/gyp/javac.py
+++ b/build/android/gyp/javac.py
@@ -77,11 +77,7 @@
       '-classpath', ':'.join(classpath),
       '-d', classes_dir]
   if chromium_code:
-    javac_args.extend(['-Xlint:unchecked'])
-    # TODO(aurimas): re-enable this after the L SDK is launched and make
-    # everyone fix new deprecation warnings correctly.
-    # http://crbug.com/405174,398669,411361,411366,411367,411376,416041
-    # '-Xlint:deprecation'
+    javac_args.extend(['-Xlint:unchecked', '-Xlint:deprecation'])
   else:
     # XDignore.symbol.file makes javac compile against rt.jar instead of
     # ct.sym. This means that using a java internal package/class will not
@@ -264,3 +260,5 @@
 
 if __name__ == '__main__':
   sys.exit(main(sys.argv[1:]))
+
+
diff --git a/build/android/pylib/cmd_helper.py b/build/android/pylib/cmd_helper.py
index aba00be..ab91054 100644
--- a/build/android/pylib/cmd_helper.py
+++ b/build/android/pylib/cmd_helper.py
@@ -9,6 +9,7 @@
 import pipes
 import select
 import signal
+import string
 import StringIO
 import subprocess
 import time
@@ -19,6 +20,52 @@
 except ImportError:
   fcntl = None
 
+_SafeShellChars = frozenset(string.ascii_letters + string.digits + '@%_-+=:,./')
+
+def SingleQuote(s):
+  """Return an shell-escaped version of the string using single quotes.
+
+  Reliably quote a string which may contain unsafe characters (e.g. space,
+  quote, or other special characters such as '$').
+
+  The returned value can be used in a shell command line as one token that gets
+  to be interpreted literally.
+
+  Args:
+    s: The string to quote.
+
+  Return:
+    The string quoted using single quotes.
+  """
+  return pipes.quote(s)
+
+def DoubleQuote(s):
+  """Return an shell-escaped version of the string using double quotes.
+
+  Reliably quote a string which may contain unsafe characters (e.g. space
+  or quote characters), while retaining some shell features such as variable
+  interpolation.
+
+  The returned value can be used in a shell command line as one token that gets
+  to be further interpreted by the shell.
+
+  The set of characters that retain their special meaning may depend on the
+  shell implementation. This set usually includes: '$', '`', '\', '!', '*',
+  and '@'.
+
+  Args:
+    s: The string to quote.
+
+  Return:
+    The string quoted using double quotes.
+  """
+  if not s:
+    return '""'
+  elif all(c in _SafeShellChars for c in s):
+    return s
+  else:
+    return '"' + s.replace('"', '\\"') + '"'
+
 
 def Popen(args, stdout=None, stderr=None, shell=None, cwd=None, env=None):
   return subprocess.Popen(
@@ -88,7 +135,7 @@
   elif shell:
     raise Exception('array args must be run with shell=False')
   else:
-    args_repr = ' '.join(map(pipes.quote, args))
+    args_repr = ' '.join(map(SingleQuote, args))
 
   s = '[host]'
   if cwd:
diff --git a/build/android/pylib/cmd_helper_test.py b/build/android/pylib/cmd_helper_test.py
new file mode 100644
index 0000000..8b5680d
--- /dev/null
+++ b/build/android/pylib/cmd_helper_test.py
@@ -0,0 +1,53 @@
+# 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.
+
+"""Tests for the cmd_helper module."""
+
+import unittest
+
+from pylib import cmd_helper
+
+# TODO(jbudorick) Make these tests run on the bots.
+
+
+class CmdHelperSingleQuoteTest(unittest.TestCase):
+
+  def testSingleQuote_basic(self):
+    self.assertEquals('hello',
+                      cmd_helper.SingleQuote('hello'))
+
+  def testSingleQuote_withSpaces(self):
+    self.assertEquals("'hello world'",
+                      cmd_helper.SingleQuote('hello world'))
+
+  def testSingleQuote_withUnsafeChars(self):
+    self.assertEquals("""'hello'"'"'; rm -rf /'""",
+                      cmd_helper.SingleQuote("hello'; rm -rf /"))
+
+  def testSingleQuote_dontExpand(self):
+    test_string = 'hello $TEST_VAR'
+    cmd = 'TEST_VAR=world; echo %s' % cmd_helper.SingleQuote(test_string)
+    self.assertEquals(test_string,
+                      cmd_helper.GetCmdOutput(cmd, shell=True).rstrip())
+
+
+class CmdHelperDoubleQuoteTest(unittest.TestCase):
+
+  def testDoubleQuote_basic(self):
+    self.assertEquals('hello',
+                      cmd_helper.DoubleQuote('hello'))
+
+  def testDoubleQuote_withSpaces(self):
+    self.assertEquals('"hello world"',
+                      cmd_helper.DoubleQuote('hello world'))
+
+  def testDoubleQuote_withUnsafeChars(self):
+    self.assertEquals('''"hello\\"; rm -rf /"''',
+                      cmd_helper.DoubleQuote('hello"; rm -rf /'))
+
+  def testSingleQuote_doExpand(self):
+    test_string = 'hello $TEST_VAR'
+    cmd = 'TEST_VAR=world; echo %s' % cmd_helper.DoubleQuote(test_string)
+    self.assertEquals('hello world',
+                      cmd_helper.GetCmdOutput(cmd, shell=True).rstrip())
diff --git a/build/android/pylib/constants.py b/build/android/pylib/constants.py
index 35b4342..d324946 100644
--- a/build/android/pylib/constants.py
+++ b/build/android/pylib/constants.py
@@ -146,8 +146,8 @@
 
 SCREENSHOTS_DIR = os.path.join(DIR_SOURCE_ROOT, 'out_screenshots')
 
-ANDROID_SDK_VERSION = 20
-ANDROID_SDK_BUILD_TOOLS_VERSION = '20.0.0'
+ANDROID_SDK_VERSION = 21
+ANDROID_SDK_BUILD_TOOLS_VERSION = '21.0.0'
 ANDROID_SDK_ROOT = os.path.join(DIR_SOURCE_ROOT,
                                 'third_party/android_tools/sdk')
 ANDROID_SDK_TOOLS = os.path.join(ANDROID_SDK_ROOT,
diff --git a/build/android/pylib/device/adb_wrapper.py b/build/android/pylib/device/adb_wrapper.py
index f4a5931..f6ac660 100644
--- a/build/android/pylib/device/adb_wrapper.py
+++ b/build/android/pylib/device/adb_wrapper.py
@@ -171,18 +171,27 @@
     if expect_rc is None:
       actual_command = command
     else:
-      actual_command = '%s; echo $?;' % command
+      actual_command = '%s; echo %%$?;' % command.rstrip()
     output = self._DeviceAdbCmd(
         ['shell', actual_command], timeout, retries, check_error=False)
     if expect_rc is not None:
-      output_end = output.rstrip().rfind('\n') + 1
-      rc = output[output_end:].strip()
-      output = output[:output_end]
-      if int(rc) != expect_rc:
+      output_end = output.rfind('%')
+      if output_end < 0:
+        # causes the string for rc to become empty and also raise a ValueError
+        output_end = len(output)
+
+      try:
+        rc = int(output[output_end+1:])
+      except ValueError:
         raise device_errors.AdbCommandFailedError(
-            ['shell', command],
-            'shell command exited with code: %s' % rc,
+            ['shell'], 'command %r on device produced output %r where no'
+            ' valid return code was found' % (actual_command, output),
             self._device_serial)
+
+      output = output[:output_end]
+      if rc != expect_rc:
+        raise device_errors.AdbShellCommandFailedError(
+            command, rc, output, self._device_serial)
     return output
 
   def Logcat(self, filter_spec=None, timeout=_DEFAULT_TIMEOUT,
diff --git a/build/android/pylib/device/adb_wrapper_test.py b/build/android/pylib/device/adb_wrapper_test.py
index 08b7fcc..208196a 100644
--- a/build/android/pylib/device/adb_wrapper_test.py
+++ b/build/android/pylib/device/adb_wrapper_test.py
@@ -41,8 +41,8 @@
     self.assertEqual(output.strip(), 'test')
     output = self._adb.Shell('echo test')
     self.assertEqual(output.strip(), 'test')
-    self.assertRaises(device_errors.AdbCommandFailedError, self._adb.Shell,
-        'echo test', expect_rc=1)
+    self.assertRaises(device_errors.AdbShellCommandFailedError,
+        self._adb.Shell, 'echo test', expect_rc=1)
 
   def testPushPull(self):
     path = self._MakeTempFile('foo')
diff --git a/build/android/pylib/device/device_errors.py b/build/android/pylib/device/device_errors.py
index acc7603..7d1ebe6 100644
--- a/build/android/pylib/device/device_errors.py
+++ b/build/android/pylib/device/device_errors.py
@@ -24,10 +24,23 @@
 
   def __init__(self, cmd, msg, device=None):
     super(AdbCommandFailedError, self).__init__(
-        'adb command \'%s\' failed with message: \'%s\'' % (' '.join(cmd), msg),
+        'adb command %r failed with message: %s' % (' '.join(cmd), msg),
         device=device)
 
 
+class AdbShellCommandFailedError(AdbCommandFailedError):
+  """Exception for adb shell command failing with non-zero return code."""
+
+  def __init__(self, cmd, return_code, output, device=None):
+    super(AdbShellCommandFailedError, self).__init__(
+        ['shell'],
+        'command %r on device failed with return code %d and output %r'
+        % (cmd, return_code, output),
+        device=device)
+    self.return_code = return_code
+    self.output = output
+
+
 class CommandTimeoutError(BaseError):
   """Exception for command timeouts."""
   pass
diff --git a/build/android/pylib/device/device_utils.py b/build/android/pylib/device/device_utils.py
index b726cb9..b2fa1ff 100644
--- a/build/android/pylib/device/device_utils.py
+++ b/build/android/pylib/device/device_utils.py
@@ -11,13 +11,14 @@
 import logging
 import multiprocessing
 import os
-import pipes
+import re
 import sys
 import tempfile
 import time
 import zipfile
 
 import pylib.android_commands
+from pylib import cmd_helper
 from pylib.device import adb_wrapper
 from pylib.device import decorators
 from pylib.device import device_errors
@@ -54,6 +55,8 @@
 
 class DeviceUtils(object):
 
+  _VALID_SHELL_VARIABLE = re.compile('^[a-zA-Z_][a-zA-Z0-9_]*$')
+
   def __init__(self, device, default_timeout=_DEFAULT_TIMEOUT,
                default_retries=_DEFAULT_RETRIES):
     """DeviceUtils constructor.
@@ -87,6 +90,7 @@
     self._commands_installed = None
     self._default_timeout = default_timeout
     self._default_retries = default_retries
+    self._cache = {}
     assert(hasattr(self, decorators.DEFAULT_TIMEOUT_ATTR))
     assert(hasattr(self, decorators.DEFAULT_RETRIES_ATTR))
 
@@ -127,7 +131,11 @@
     return self._HasRootImpl()
 
   def _HasRootImpl(self):
-    return self.old_interface.IsRootEnabled()
+    try:
+      self._RunShellCommandImpl('ls /root', check_return=True)
+      return True
+    except device_errors.AdbShellCommandFailedError:
+      return False
 
   @decorators.WithTimeoutAndRetriesFromInstance()
   def EnableRoot(self, timeout=None, retries=None):
@@ -182,11 +190,17 @@
     return self._GetExternalStoragePathImpl()
 
   def _GetExternalStoragePathImpl(self):
-    try:
-      return self.old_interface.GetExternalStorage()
-    except AssertionError as e:
-      raise device_errors.CommandFailedError(
-          str(e), device=str(self)), None, sys.exc_info()[2]
+    if 'external_storage' in self._cache:
+      return self._cache['external_storage']
+
+    value = self._RunShellCommandImpl('echo $EXTERNAL_STORAGE',
+                                      single_line=True,
+                                      check_return=True)
+    if not value:
+      raise device_errors.CommandFailedError('$EXTERNAL_STORAGE is not set',
+                                             str(self))
+    self._cache['external_storage'] = value
+    return value
 
   @decorators.WithTimeoutAndRetriesFromInstance()
   def WaitUntilFullyBooted(self, wifi=False, timeout=None, retries=None):
@@ -216,7 +230,7 @@
     self.old_interface.WaitForSdCardReady(timeout)
     if wifi:
       while not 'Wi-Fi is enabled' in (
-          self._RunShellCommandImpl('dumpsys wifi')):
+          self.old_interface.RunShellCommand('dumpsys wifi')):
         time.sleep(1)
 
   REBOOT_DEFAULT_TIMEOUT = 10 * _DEFAULT_TIMEOUT
@@ -292,58 +306,98 @@
             str(e), device=str(self)), None, sys.exc_info()[2]
 
   @decorators.WithTimeoutAndRetriesFromInstance()
-  def RunShellCommand(self, cmd, check_return=False, as_root=False, cwd=None,
-                      env=None, timeout=None, retries=None):
+  def RunShellCommand(self, cmd, check_return=False, cwd=None, env=None,
+                      as_root=False, single_line=False,
+                      timeout=None, retries=None):
     """Run an ADB shell command.
 
-    TODO(jbudorick) Switch the default value of check_return to True after
-    AndroidCommands is gone.
+    The command to run |cmd| should be a sequence of program arguments or else
+    a single string.
+
+    When |cmd| is a sequence, it is assumed to contain the name of the command
+    to run followed by its arguments. In this case, arguments are passed to the
+    command exactly as given, without any further processing by the shell. This
+    allows to easily pass arguments containing spaces or special characters
+    without having to worry about getting quoting right. Whenever possible, it
+    is recomended to pass |cmd| as a sequence.
+
+    When |cmd| is given as a string, it will be interpreted and run by the
+    shell on the device.
+
+    This behaviour is consistent with that of command runners in cmd_helper as
+    well as Python's own subprocess.Popen.
+
+    TODO(perezju) Change the default of |check_return| to True when callers
+      have switched to the new behaviour.
 
     Args:
-      cmd: A list containing the command to run on the device and any arguments.
+      cmd: A string with the full command to run on the device, or a sequence
+        containing the command and its arguments.
       check_return: A boolean indicating whether or not the return code should
-                    be checked.
-      as_root: A boolean indicating whether the shell command should be run
-               with root privileges.
+        be checked.
       cwd: The device directory in which the command should be run.
       env: The environment variables with which the command should be run.
+      as_root: A boolean indicating whether the shell command should be run
+        with root privileges.
+      single_line: A boolean indicating if a single line of output is expected,
+        and the caller wants to retrieve the value of that line. The default
+        behaviour is to return a list of output lines.
       timeout: timeout in seconds
       retries: number of retries
 
     Returns:
-      The output of the command.
+      The output of the command either as list of lines or, when single_line is
+        True, the value contained in the single expected line of output.
 
     Raises:
-      CommandFailedError if check_return is True and the return code is nozero.
+      AdbShellCommandFailedError if check_return is True and the exit code of
+        the command run on the device is non-zero.
+      CommandFailedError if single_line is True but the output consists of
+        either zero or more than one lines.
       CommandTimeoutError on timeout.
       DeviceUnreachableError on missing device.
     """
-    return self._RunShellCommandImpl(
-        cmd, check_return=check_return, as_root=as_root, cwd=cwd, env=env,
-        timeout=timeout)
+    return self._RunShellCommandImpl(cmd, check_return=check_return, cwd=cwd,
+        env=env, as_root=as_root, single_line=single_line, timeout=timeout)
 
-  def _RunShellCommandImpl(self, cmd, check_return=False, as_root=False,
-                           cwd=None, env=None, timeout=None):
-    # TODO(jbudorick): Remove the timeout parameter once this is no longer
-    # backed by AndroidCommands.
-    if isinstance(cmd, list):
-      cmd = ' '.join(cmd)
+  def _RunShellCommandImpl(self, cmd, check_return=False, cwd=None, env=None,
+                           as_root=False, single_line=False, timeout=None):
+    def env_quote(key, value):
+      if not DeviceUtils._VALID_SHELL_VARIABLE.match(key):
+        raise KeyError('Invalid shell variable name %r' % key)
+      # using double quotes here to allow interpolation of shell variables
+      return '%s=%s' % (key, cmd_helper.DoubleQuote(value))
+
+    if not isinstance(cmd, basestring):
+      cmd = ' '.join(cmd_helper.SingleQuote(s) for s in cmd)
     if as_root and not self._HasRootImpl():
       cmd = 'su -c %s' % cmd
     if env:
-      cmd = '%s %s' % (
-          ' '.join('%s=%s' % (k, v) for k, v in env.iteritems()), cmd)
+      env = ' '.join(env_quote(k, v) for k, v in env.iteritems())
+      cmd = '%s %s' % (env, cmd)
     if cwd:
-      cmd = 'cd %s && %s' % (cwd, cmd)
-    if check_return:
-      code, output = self.old_interface.GetShellCommandStatusAndOutput(
-          cmd, timeout_time=timeout)
-      if int(code) != 0:
-        raise device_errors.AdbCommandFailedError(
-            cmd.split(), 'Nonzero exit code (%d)' % code, device=str(self))
+      cmd = 'cd %s && %s' % (cmd_helper.SingleQuote(cwd), cmd)
+    if timeout is None:
+      timeout = self._default_timeout
+
+    try:
+      # TODO(perezju) still need to make sure that we call a version of
+      # adb.Shell without a timeout-and-retries wrapper.
+      output = self.adb.Shell(cmd, expect_rc=0, timeout=timeout, retries=0)
+    except device_errors.AdbShellCommandFailedError as e:
+      if check_return:
+        raise
+      else:
+        output = e.output
+
+    output = output.splitlines()
+    if single_line:
+      if len(output) != 1:
+        msg = 'exactly one line of output expected, but got: %s'
+        raise device_errors.CommandFailedError(msg % output)
+      return output[0]
     else:
-      output = self.old_interface.RunShellCommand(cmd, timeout_time=timeout)
-    return output
+      return output
 
   @decorators.WithTimeoutAndRetriesFromInstance()
   def KillAll(self, process_name, signum=9, as_root=False, blocking=False,
@@ -371,8 +425,8 @@
       raise device_errors.CommandFailedError(
           'No process "%s"' % process_name, device=str(self))
 
-    cmd = 'kill -%d %s' % (signum, ' '.join(pids.values()))
-    self._RunShellCommandImpl(cmd, as_root=as_root)
+    cmd = ['kill', '-%d' % signum] + pids.values()
+    self._RunShellCommandImpl(cmd, as_root=as_root, check_return=True)
 
     if blocking:
       wait_period = 0.1
@@ -523,8 +577,7 @@
     files = []
     for h, d in host_device_tuples:
       if os.path.isdir(h):
-        self._RunShellCommandImpl(['mkdir', '-p', '"%s"' % d],
-                                  check_return=True)
+        self._RunShellCommandImpl(['mkdir', '-p', d], check_return=True)
       files += self._GetChangedFilesImpl(h, d)
 
     if not files:
@@ -558,14 +611,13 @@
       self._PushChangedFilesZipped(files)
       self._RunShellCommandImpl(
           ['chmod', '-R', '777'] + [d for _, d in host_device_tuples],
-          as_root=True)
+          as_root=True, check_return=True)
 
   def _GetChangedFilesImpl(self, host_path, device_path):
     real_host_path = os.path.realpath(host_path)
     try:
       real_device_path = self._RunShellCommandImpl(
-          ['realpath', device_path], check_return=True)
-      real_device_path = real_device_path[0]
+          ['realpath', device_path], single_line=True, check_return=True)
     except device_errors.CommandFailedError:
       return [(host_path, device_path)]
 
@@ -657,13 +709,14 @@
         self.adb.Push(zip_file.name, zip_on_device)
         self._RunShellCommandImpl(
             ['unzip', zip_on_device],
-            as_root=True, check_return=True,
-            env={'PATH': '$PATH:%s' % install_commands.BIN_DIR})
+            as_root=True,
+            env={'PATH': '$PATH:%s' % install_commands.BIN_DIR},
+            check_return=True)
       finally:
         if zip_proc.is_alive():
           zip_proc.terminate()
         if self._IsOnlineImpl():
-          self._RunShellCommandImpl(['rm', zip_on_device])
+          self._RunShellCommandImpl(['rm', zip_on_device], check_return=True)
 
   @staticmethod
   def _CreateDeviceZip(zip_path, host_device_tuples):
@@ -799,8 +852,9 @@
       CommandTimeoutError on timeout.
       DeviceUnreachableError on missing device.
     """
-    self._RunShellCommandImpl('echo {1} > {0}'.format(device_path,
-        pipes.quote(text)), check_return=True, as_root=as_root)
+    cmd = 'echo %s > %s' % (cmd_helper.SingleQuote(text),
+                            cmd_helper.SingleQuote(device_path))
+    self._RunShellCommandImpl(cmd, as_root=as_root, check_return=True)
 
   @decorators.WithTimeoutAndRetriesFromInstance()
   def Ls(self, device_path, timeout=None, retries=None):
@@ -917,7 +971,7 @@
 
   def _GetPidsImpl(self, process_name):
     procs_pids = {}
-    for line in self._RunShellCommandImpl('ps'):
+    for line in self._RunShellCommandImpl('ps', check_return=True):
       try:
         ps_data = line.split()
         if process_name in ps_data[-1]:
diff --git a/build/android/pylib/device/device_utils_test.py b/build/android/pylib/device/device_utils_test.py
index 513b538..6638fad 100755
--- a/build/android/pylib/device/device_utils_test.py
+++ b/build/android/pylib/device/device_utils_test.py
@@ -218,6 +218,73 @@
         '0123456789abcdef', default_timeout=1, default_retries=0)
 
 
+class Args:
+  def __init__(self, *args, **kwargs):
+    self.args = args
+    self.kwargs = kwargs
+
+  def __eq__(self, other):
+    return (self.args, self.kwargs) == (other.args, other.kwargs)
+
+  def __repr__(self):
+    return '%s(%s)' % (type(self).__name__, str(self))
+
+  def __str__(self):
+    toks = (['%r' % v for v in self.args] +
+            ['%s=%r' % (k, self.kwargs[k]) for k in sorted(self.kwargs)])
+    return ', '.join(toks)
+
+
+class MockCallSequence(object):
+  def __init__(self, test_case, obj, method, calls):
+    def assert_and_return(*args, **kwargs):
+      received_args = Args(*args, **kwargs)
+      test_case.assertTrue(
+          self._calls,
+          msg=('Unexpected call\n'
+               '  received: %s(%s)\n' % (self._method, received_args)))
+      expected_args, return_value = self._calls.pop(0)
+      test_case.assertTrue(
+          received_args == expected_args,
+          msg=('Call does not match expected args\n'
+               '  received: %s(%s)\n'
+               '  expected: %s(%s)\n'
+               % (self._method, received_args,
+                  self._method, expected_args)))
+      if isinstance(return_value, Exception):
+        raise return_value
+      else:
+        return return_value
+
+    self._calls = list(calls)
+    self._test_case = test_case
+    self._method = method
+    self._patched = mock.patch.object(obj, self._method,
+                                      side_effect=assert_and_return)
+
+  def __enter__(self):
+    return self._patched.__enter__()
+
+  def __exit__(self, exc_type, exc_val, exc_tb):
+    self._patched.__exit__(exc_type, exc_val, exc_tb)
+    if exc_type is None:
+      missing = ''.join('  expected: %s(%s)\n'
+                        % (self._method, expected_args)
+                        for expected_args, _ in self._calls)
+      self._test_case.assertTrue(
+          not missing,
+          msg=('Expected calls not found\n' + missing))
+
+
+class _ShellError:
+  def __init__(self, output=None, return_code=1):
+    if output is None:
+      self.output = 'Permission denied\r\n'
+    else:
+      self.output = output
+    self.return_code = return_code
+
+
 class DeviceUtilsNewImplTest(unittest.TestCase):
 
   def setUp(self):
@@ -228,6 +295,28 @@
     self.device = device_utils.DeviceUtils(
         self.adb, default_timeout=1, default_retries=0)
 
+  def assertShellCallSequence(self, calls):
+    '''Assert that we expect a sequence of calls to adb.Shell.
+
+    Args:
+      calls: a sequence of (cmd, return_value) pairs, where |cmd| is the
+        expected shell command to run on the device (with any quoting already
+        applied), and |return_value| is either a string to give as mock output
+        or a _ShellError object to raise an AdbShellCommandFailedError.
+    '''
+    def mk_expected_call(cmd, return_value):
+      expected_args = Args(cmd, expect_rc=0, timeout=1, retries=0)
+      if isinstance(return_value, _ShellError):
+        return_value = device_errors.AdbShellCommandFailedError(cmd,
+            return_value.return_code, return_value.output, str(self.device))
+      return (expected_args, return_value)
+
+    expected_calls = (mk_expected_call(a, r) for a, r in calls)
+    return MockCallSequence(self, self.adb, 'Shell', expected_calls)
+
+  def assertShellCall(self, cmd, return_value=''):
+    return self.assertShellCallSequence([(cmd, return_value)])
+
 
 class DeviceUtilsHybridImplTest(DeviceUtilsOldImplTest):
 
@@ -248,16 +337,14 @@
       self.assertFalse(self.device.IsOnline())
 
 
-class DeviceUtilsHasRootTest(DeviceUtilsOldImplTest):
+class DeviceUtilsHasRootTest(DeviceUtilsNewImplTest):
 
   def testHasRoot_true(self):
-    with self.assertCalls("adb -s 0123456789abcdef shell 'ls /root'",
-                                 'foo\r\n'):
+    with self.assertShellCall('ls /root', 'foo\r\n'):
       self.assertTrue(self.device.HasRoot())
 
   def testHasRoot_false(self):
-    with self.assertCalls("adb -s 0123456789abcdef shell 'ls /root'",
-                                 'Permission denied\r\n'):
+    with self.assertShellCall('ls /root', _ShellError()):
       self.assertFalse(self.device.HasRoot())
 
 
@@ -303,19 +390,17 @@
       self.assertFalse(self.device.IsUserBuild())
 
 
-class DeviceUtilsGetExternalStoragePathTest(DeviceUtilsOldImplTest):
+class DeviceUtilsGetExternalStoragePathTest(DeviceUtilsNewImplTest):
 
   def testGetExternalStoragePath_succeeds(self):
     fakeStoragePath = '/fake/storage/path'
-    with self.assertCalls(
-        "adb -s 0123456789abcdef shell 'echo $EXTERNAL_STORAGE'",
-        '%s\r\n' % fakeStoragePath):
+    with self.assertShellCall('echo $EXTERNAL_STORAGE',
+                              '%s\r\n' % fakeStoragePath):
       self.assertEquals(fakeStoragePath,
                         self.device.GetExternalStoragePath())
 
   def testGetExternalStoragePath_fails(self):
-    with self.assertCalls(
-        "adb -s 0123456789abcdef shell 'echo $EXTERNAL_STORAGE'", '\r\n'):
+    with self.assertShellCall('echo $EXTERNAL_STORAGE', '\r\n'):
       with self.assertRaises(device_errors.CommandFailedError):
         self.device.GetExternalStoragePath()
 
@@ -544,101 +629,156 @@
           self.device.Install('/fake/test/app.apk', retries=0)
 
 
-class DeviceUtilsRunShellCommandTest(DeviceUtilsOldImplTest):
-
+class DeviceUtilsRunShellCommandTest(DeviceUtilsNewImplTest):
   def testRunShellCommand_commandAsList(self):
-    with self.assertCalls(
-        "adb -s 0123456789abcdef shell 'pm list packages'",
-        'pacakge:android\r\n'):
+    with self.assertShellCall('pm list packages'):
       self.device.RunShellCommand(['pm', 'list', 'packages'])
 
+  def testRunShellCommand_commandAsListQuoted(self):
+    with self.assertShellCall("echo 'hello world' '$10'"):
+      self.device.RunShellCommand(['echo', 'hello world', '$10'])
+
   def testRunShellCommand_commandAsString(self):
-    with self.assertCalls(
-        "adb -s 0123456789abcdef shell 'dumpsys wifi'",
-        'Wi-Fi is enabled\r\n'):
-      self.device.RunShellCommand('dumpsys wifi')
+    with self.assertShellCall('echo "$VAR"'):
+      self.device.RunShellCommand('echo "$VAR"')
+
+  def testNewRunShellImpl_withEnv(self):
+    with self.assertShellCall('VAR=some_string echo "$VAR"'):
+      self.device.RunShellCommand('echo "$VAR"', env={'VAR': 'some_string'})
+
+  def testNewRunShellImpl_withEnvQuoted(self):
+    with self.assertShellCall('PATH="$PATH:/other/path" run_this'):
+      self.device.RunShellCommand('run_this', env={'PATH': '$PATH:/other/path'})
+
+  def testNewRunShellImpl_withEnv_failure(self):
+    with self.assertRaises(KeyError):
+      self.device.RunShellCommand('some_cmd', env={'INVALID NAME': 'value'})
+
+  def testNewRunShellImpl_withCwd(self):
+    with self.assertShellCall('cd /some/test/path && ls'):
+      self.device.RunShellCommand('ls', cwd='/some/test/path')
+
+  def testNewRunShellImpl_withCwdQuoted(self):
+    with self.assertShellCall("cd '/some test/path with/spaces' && ls"):
+      self.device.RunShellCommand('ls', cwd='/some test/path with/spaces')
 
   def testRunShellCommand_withSu(self):
-    with self.assertCallsSequence([
-        ("adb -s 0123456789abcdef shell 'ls /root'", 'Permission denied\r\n'),
-        ("adb -s 0123456789abcdef shell 'su -c setprop service.adb.root 0'",
-         '')]):
+    with self.assertShellCallSequence([
+        ('ls /root', _ShellError()),
+        ('su -c setprop service.adb.root 0', '')]):
       self.device.RunShellCommand('setprop service.adb.root 0', as_root=True)
 
   def testRunShellCommand_withRoot(self):
-    with self.assertCallsSequence([
-        ("adb -s 0123456789abcdef shell 'ls /root'", 'hello\r\nworld\r\n'),
-        ("adb -s 0123456789abcdef shell 'setprop service.adb.root 0'", '')]):
+    with self.assertShellCallSequence([
+        ('ls /root', '\r\n'),
+        ('setprop service.adb.root 0', '')]):
       self.device.RunShellCommand('setprop service.adb.root 0', as_root=True)
 
+  def testRunShellCommand_manyLines(self):
+    cmd = 'ls /some/path'
+    with self.assertShellCall(cmd, 'file1\r\nfile2\r\nfile3\r\n'):
+      self.assertEquals(['file1', 'file2', 'file3'],
+                        self.device.RunShellCommand(cmd))
+
+  def testRunShellCommand_singleLine_success(self):
+    cmd = 'echo $VALUE'
+    with self.assertShellCall(cmd, 'some value\r\n'):
+      self.assertEquals('some value',
+                        self.device.RunShellCommand(cmd, single_line=True))
+
+  def testRunShellCommand_singleLine_successEmptyLine(self):
+    cmd = 'echo $VALUE'
+    with self.assertShellCall(cmd, '\r\n'):
+      self.assertEquals('',
+                        self.device.RunShellCommand(cmd, single_line=True))
+
+  def testRunShellCommand_singleLine_successWithoutEndLine(self):
+    cmd = 'echo -n $VALUE'
+    with self.assertShellCall(cmd, 'some value'):
+      self.assertEquals('some value',
+                        self.device.RunShellCommand(cmd, single_line=True))
+
+  def testRunShellCommand_singleLine_failNoLines(self):
+    cmd = 'echo $VALUE'
+    with self.assertShellCall(cmd, ''):
+      with self.assertRaises(device_errors.CommandFailedError):
+        self.device.RunShellCommand(cmd, single_line=True)
+
+  def testRunShellCommand_singleLine_failTooManyLines(self):
+    cmd = 'echo $VALUE'
+    with self.assertShellCall(cmd, 'some value\r\nanother value\r\n'):
+      with self.assertRaises(device_errors.CommandFailedError):
+        self.device.RunShellCommand(cmd, single_line=True)
+
   def testRunShellCommand_checkReturn_success(self):
-    with self.assertCalls(
-        "adb -s 0123456789abcdef shell 'echo $ANDROID_DATA; echo %$?'",
-        '/data\r\n%0\r\n'):
-      self.device.RunShellCommand('echo $ANDROID_DATA', check_return=True)
+    cmd = 'echo $ANDROID_DATA'
+    output = '/data\r\n'
+    with self.assertShellCall(cmd, output):
+      self.assertEquals([output.rstrip()],
+                        self.device.RunShellCommand(cmd, check_return=True))
 
   def testRunShellCommand_checkReturn_failure(self):
-    with self.assertCalls(
-        "adb -s 0123456789abcdef shell 'echo $ANDROID_DATA; echo %$?'",
-        '\r\n%1\r\n'):
-      with self.assertRaises(device_errors.CommandFailedError):
-        self.device.RunShellCommand('echo $ANDROID_DATA', check_return=True)
+    cmd = 'ls /root'
+    output = 'opendir failed, Permission denied\r\n'
+    with self.assertShellCall(cmd, _ShellError(output)):
+      with self.assertRaises(device_errors.AdbShellCommandFailedError):
+        self.device.RunShellCommand(cmd, check_return=True)
+
+  def testRunShellCommand_checkReturn_disabled(self):
+    cmd = 'ls /root'
+    output = 'opendir failed, Permission denied\r\n'
+    with self.assertShellCall(cmd, _ShellError(output)):
+      self.assertEquals([output.rstrip()],
+                        self.device.RunShellCommand(cmd, check_return=False))
 
 
-class DeviceUtilsKillAllTest(DeviceUtilsOldImplTest):
+class DeviceUtilsKillAllTest(DeviceUtilsNewImplTest):
 
   def testKillAll_noMatchingProcesses(self):
-    with self.assertCalls(
-        "adb -s 0123456789abcdef shell 'ps'",
-        'USER   PID   PPID  VSIZE  RSS   WCHAN    PC       NAME\r\n'):
+    output = 'USER   PID   PPID  VSIZE  RSS   WCHAN    PC       NAME\r\n'
+    with self.assertShellCallSequence([('ps', output)]):
       with self.assertRaises(device_errors.CommandFailedError):
         self.device.KillAll('test_process')
 
   def testKillAll_nonblocking(self):
-    with self.assertCallsSequence([
-        ("adb -s 0123456789abcdef shell 'ps'",
-         'USER   PID   PPID  VSIZE  RSS   WCHAN    PC       NAME\r\n'
-         'u0_a1  1234  174   123456 54321 ffffffff 456789ab '
-              'this.is.a.test.process\r\n'),
-        ("adb -s 0123456789abcdef shell 'kill -9 1234'", '')]):
+    with self.assertShellCallSequence([
+        ('ps', 'USER   PID   PPID  VSIZE  RSS   WCHAN    PC       NAME\r\n'
+               'u0_a1  1234  174   123456 54321 ffffffff 456789ab '
+               'this.is.a.test.process\r\n'),
+        ('kill -9 1234', '')]):
       self.assertEquals(1,
           self.device.KillAll('this.is.a.test.process', blocking=False))
 
   def testKillAll_blocking(self):
     with mock.patch('time.sleep'):
-      with self.assertCallsSequence([
-          ("adb -s 0123456789abcdef shell 'ps'",
-           'USER   PID   PPID  VSIZE  RSS   WCHAN    PC       NAME\r\n'
-           'u0_a1  1234  174   123456 54321 ffffffff 456789ab '
-                'this.is.a.test.process\r\n'),
-          ("adb -s 0123456789abcdef shell 'kill -9 1234'", ''),
-          ("adb -s 0123456789abcdef shell 'ps'",
-           'USER   PID   PPID  VSIZE  RSS   WCHAN    PC       NAME\r\n'
-           'u0_a1  1234  174   123456 54321 ffffffff 456789ab '
-                'this.is.a.test.process\r\n'),
-          ("adb -s 0123456789abcdef shell 'ps'",
-           'USER   PID   PPID  VSIZE  RSS   WCHAN    PC       NAME\r\n')]):
+      with self.assertShellCallSequence([
+        ('ps', 'USER   PID   PPID  VSIZE  RSS   WCHAN    PC       NAME\r\n'
+               'u0_a1  1234  174   123456 54321 ffffffff 456789ab '
+               'this.is.a.test.process\r\n'),
+        ('kill -9 1234', ''),
+        ('ps', 'USER   PID   PPID  VSIZE  RSS   WCHAN    PC       NAME\r\n'
+               'u0_a1  1234  174   123456 54321 ffffffff 456789ab '
+               'this.is.a.test.process\r\n'),
+        ('ps', 'USER   PID   PPID  VSIZE  RSS   WCHAN    PC       NAME\r\n')]):
         self.assertEquals(1,
             self.device.KillAll('this.is.a.test.process', blocking=True))
 
   def testKillAll_root(self):
-    with self.assertCallsSequence([
-          ("adb -s 0123456789abcdef shell 'ps'",
-           'USER   PID   PPID  VSIZE  RSS   WCHAN    PC       NAME\r\n'
-           'u0_a1  1234  174   123456 54321 ffffffff 456789ab '
-                'this.is.a.test.process\r\n'),
-          ("adb -s 0123456789abcdef shell 'ls /root'", 'Permission denied\r\n'),
-          ("adb -s 0123456789abcdef shell 'su -c kill -9 1234'", '')]):
+    with self.assertShellCallSequence([
+        ('ps', 'USER   PID   PPID  VSIZE  RSS   WCHAN    PC       NAME\r\n'
+               'u0_a1  1234  174   123456 54321 ffffffff 456789ab '
+               'this.is.a.test.process\r\n'),
+        ('ls /root', _ShellError()),
+        ('su -c kill -9 1234', '')]):
       self.assertEquals(1,
           self.device.KillAll('this.is.a.test.process', as_root=True))
 
   def testKillAll_sigterm(self):
-    with self.assertCallsSequence([
-        ("adb -s 0123456789abcdef shell 'ps'",
-         'USER   PID   PPID  VSIZE  RSS   WCHAN    PC       NAME\r\n'
-         'u0_a1  1234  174   123456 54321 ffffffff 456789ab '
-              'this.is.a.test.process\r\n'),
-        ("adb -s 0123456789abcdef shell 'kill -15 1234'", '')]):
+    with self.assertShellCallSequence([
+        ('ps', 'USER   PID   PPID  VSIZE  RSS   WCHAN    PC       NAME\r\n'
+               'u0_a1  1234  174   123456 54321 ffffffff 456789ab '
+               'this.is.a.test.process\r\n'),
+        ('kill -15 1234', '')]):
       self.assertEquals(1,
           self.device.KillAll('this.is.a.test.process', signum=signal.SIGTERM))
 
@@ -944,10 +1084,11 @@
     self.assertEqual(2, self.device._RunShellCommandImpl.call_count)
     self.device._RunShellCommandImpl.assert_any_call(
         ['unzip', '/test/device/external_dir/tmp.zip'],
-        as_root=True, check_return=True,
-        env={'PATH': '$PATH:/data/local/tmp/bin'})
+        as_root=True,
+        env={'PATH': '$PATH:/data/local/tmp/bin'},
+        check_return=True)
     self.device._RunShellCommandImpl.assert_any_call(
-        ['rm', '/test/device/external_dir/tmp.zip'])
+        ['rm', '/test/device/external_dir/tmp.zip'], check_return=True)
 
   def testPushChangedFilesZipped_multiple(self):
     test_files = [('/test/host/path/file1', '/test/device/path/file1'),
@@ -971,10 +1112,11 @@
     self.assertEqual(2, self.device._RunShellCommandImpl.call_count)
     self.device._RunShellCommandImpl.assert_any_call(
         ['unzip', '/test/device/external_dir/tmp.zip'],
-        as_root=True, check_return=True,
-        env={'PATH': '$PATH:/data/local/tmp/bin'})
+        as_root=True,
+        env={'PATH': '$PATH:/data/local/tmp/bin'},
+        check_return=True)
     self.device._RunShellCommandImpl.assert_any_call(
-        ['rm', '/test/device/external_dir/tmp.zip'])
+        ['rm', '/test/device/external_dir/tmp.zip'], check_return=True)
 
 
 class DeviceUtilsFileExistsTest(DeviceUtilsOldImplTest):
@@ -1202,44 +1344,22 @@
       self.device.WriteFile('/test/file/no.permissions.to.write',
                             'new test file contents', as_root=True)
 
-class DeviceUtilsWriteTextFileTest(DeviceUtilsOldImplTest):
+class DeviceUtilsWriteTextFileTest(DeviceUtilsNewImplTest):
 
   def testWriteTextFileTest_basic(self):
-    with self.assertCalls(
-        "adb -s 0123456789abcdef shell 'echo some.string"
-        " > /test/file/to.write; echo %$?'", '%0\r\n'):
+    with self.assertShellCall('echo some.string > /test/file/to.write'):
       self.device.WriteTextFile('/test/file/to.write', 'some.string')
 
-  def testWriteTextFileTest_stringWithSpaces(self):
-    with self.assertCalls(
-        "adb -s 0123456789abcdef shell 'echo '\\''some other string'\\''"
-        " > /test/file/to.write; echo %$?'", '%0\r\n'):
-      self.device.WriteTextFile('/test/file/to.write', 'some other string')
+  def testWriteTextFileTest_quoted(self):
+    with self.assertShellCall(
+        "echo 'some other string' > '/test/file/to write'"):
+      self.device.WriteTextFile('/test/file/to write', 'some other string')
 
-  def testWriteTextFileTest_asRoot_withSu(self):
-    with self.assertCallsSequence([
-        ("adb -s 0123456789abcdef shell 'ls /root'", 'Permission denied\r\n'),
-        ("adb -s 0123456789abcdef shell 'su -c echo some.string"
-          " > /test/file/to.write; echo %$?'", '%0\r\n')]):
-      self.device.WriteTextFile('/test/file/to.write', 'some.string',
-                                as_root=True)
-
-  def testWriteTextFileTest_asRoot_withRoot(self):
-    with self.assertCallsSequence([
-        ("adb -s 0123456789abcdef shell 'ls /root'", 'hello\r\nworld\r\n'),
-        ("adb -s 0123456789abcdef shell 'echo some.string"
-          " > /test/file/to.write; echo %$?'", '%0\r\n')]):
-      self.device.WriteTextFile('/test/file/to.write', 'some.string',
-                                as_root=True)
-
-  def testWriteTextFileTest_asRoot_rejected(self):
-    with self.assertCallsSequence([
-        ("adb -s 0123456789abcdef shell 'ls /root'", 'Permission denied\r\n'),
-        ("adb -s 0123456789abcdef shell 'su -c echo some.string"
-          " > /test/file/to.write; echo %$?'", '%1\r\n')]):
-      with self.assertRaises(device_errors.CommandFailedError):
-        self.device.WriteTextFile('/test/file/to.write', 'some.string',
-                                  as_root=True)
+  def testWriteTextFileTest_asRoot(self):
+    with self.assertShellCallSequence([
+        ('ls /root', _ShellError()),
+        ('su -c echo string > /test/file', '')]):
+      self.device.WriteTextFile('/test/file', 'string', as_root=True)
 
 class DeviceUtilsLsTest(DeviceUtilsOldImplTest):
 
@@ -1396,26 +1516,26 @@
       self.device.SetProp('this.is.a.test.property', 'test_property_value')
 
 
-class DeviceUtilsGetPidsTest(DeviceUtilsOldImplTest):
+class DeviceUtilsGetPidsTest(DeviceUtilsNewImplTest):
 
   def testGetPids_noMatches(self):
-    with self.assertCalls(
-        "adb -s 0123456789abcdef shell 'ps'",
+    with self.assertShellCall(
+        'ps',
         'USER   PID   PPID  VSIZE  RSS   WCHAN    PC       NAME\r\n'
         'user  1000    100   1024 1024   ffffffff 00000000 no.match\r\n'):
       self.assertEqual({}, self.device.GetPids('does.not.match'))
 
   def testGetPids_oneMatch(self):
-    with self.assertCalls(
-        "adb -s 0123456789abcdef shell 'ps'",
+    with self.assertShellCall(
+        'ps',
         'USER   PID   PPID  VSIZE  RSS   WCHAN    PC       NAME\r\n'
         'user  1000    100   1024 1024   ffffffff 00000000 not.a.match\r\n'
         'user  1001    100   1024 1024   ffffffff 00000000 one.match\r\n'):
       self.assertEqual({'one.match': '1001'}, self.device.GetPids('one.match'))
 
   def testGetPids_mutlipleMatches(self):
-    with self.assertCalls(
-        "adb -s 0123456789abcdef shell 'ps'",
+    with self.assertShellCall(
+        'ps',
         'USER   PID   PPID  VSIZE  RSS   WCHAN    PC       NAME\r\n'
         'user  1000    100   1024 1024   ffffffff 00000000 not\r\n'
         'user  1001    100   1024 1024   ffffffff 00000000 one.match\r\n'
@@ -1426,8 +1546,8 @@
           self.device.GetPids('match'))
 
   def testGetPids_exactMatch(self):
-    with self.assertCalls(
-        "adb -s 0123456789abcdef shell 'ps'",
+    with self.assertShellCall(
+        'ps',
         'USER   PID   PPID  VSIZE  RSS   WCHAN    PC       NAME\r\n'
         'user  1000    100   1024 1024   ffffffff 00000000 not.exact.match\r\n'
         'user  1234    100   1024 1024   ffffffff 00000000 exact.match\r\n'):
diff --git a/build/android/pylib/instrumentation/test_runner.py b/build/android/pylib/instrumentation/test_runner.py
index 0e6c168..821fec1 100644
--- a/build/android/pylib/instrumentation/test_runner.py
+++ b/build/android/pylib/instrumentation/test_runner.py
@@ -358,8 +358,8 @@
 
     cmd = ['am', 'instrument', '-r']
     for k, v in self._GetInstrumentationArgs().iteritems():
-      cmd.extend(['-e', k, "'%s'" % v])
-    cmd.extend(['-e', 'class', "'%s'" % test])
+      cmd.extend(['-e', k, v])
+    cmd.extend(['-e', 'class', test])
     cmd.extend(['-w', instrumentation_path])
     return self.device.RunShellCommand(cmd, timeout=timeout, retries=0)
 
diff --git a/build/android/pylib/instrumentation/test_runner_test.py b/build/android/pylib/instrumentation/test_runner_test.py
index 1a2b40f..039bb03 100755
--- a/build/android/pylib/instrumentation/test_runner_test.py
+++ b/build/android/pylib/instrumentation/test_runner_test.py
@@ -261,8 +261,8 @@
     self.instance._RunTest('test.package.TestClass#testMethod', 100)
     self.instance.device.RunShellCommand.assert_called_with(
         ['am', 'instrument', '-r',
-         '-e', 'test_arg_key', "'test_arg_value'",
-         '-e', 'class', "'test.package.TestClass#testMethod'",
+         '-e', 'test_arg_key', 'test_arg_value',
+         '-e', 'class', 'test.package.TestClass#testMethod',
          '-w', 'test.package/MyTestRunner'],
         timeout=100, retries=0)
 
diff --git a/build/common.gypi b/build/common.gypi
index e9e8a3e..e9b1476 100644
--- a/build/common.gypi
+++ b/build/common.gypi
@@ -1628,8 +1628,8 @@
             'android_sdk_root%': '<!(cd <(DEPTH) && pwd -P)/third_party/android_tools/sdk/',
             'android_host_arch%': '<!(uname -m)',
             # Android API-level of the SDK used for compilation.
-            'android_sdk_version%': '20',
-            'android_sdk_build_tools_version%': '20.0.0',
+            'android_sdk_version%': '21',
+            'android_sdk_build_tools_version%': '21.0.0',
             'host_os%': "<!(uname -s | sed -e 's/Linux/linux/;s/Darwin/mac/')",
           },
           # Copy conditionally-set variables out one scope.
@@ -1760,9 +1760,9 @@
         # Uses system APIs for decoding audio and video.
         'use_libffmpeg%': '0',
 
-        # When building as part of the Android system, use system libraries
-        # where possible to reduce ROM size.
-        'use_system_stlport%': '<(android_webview_build)',
+        # TODO(torne): Remove this unsupported option once all the places that
+        # test it have been updated.
+        'use_system_stlport%': 0,
 
         # Copy it out one scope.
         'android_webview_build%': '<(android_webview_build)',
@@ -4339,19 +4339,12 @@
         # build of chrome (e.g. where to find archived symbols).
         'chrome_build_id%': '',
         'conditions': [
-          # Use shared stlport library when system one used.
           # Figure this out early since it needs symbols from libgcc.a, so it
           # has to be before that in the set of libraries.
-          ['use_system_stlport==1', {
-            'android_stlport_library': 'stlport',
+          ['component=="shared_library"', {
+              'android_stlport_library': 'stlport_shared',
           }, {
-            'conditions': [
-              ['component=="shared_library"', {
-                  'android_stlport_library': 'stlport_shared',
-              }, {
-                  'android_stlport_library': 'stlport_static',
-              }],
-            ],
+              'android_stlport_library': 'stlport_static',
           }],
         ],
 
@@ -4443,17 +4436,8 @@
               '-pthread',  # Not supported by Android toolchain.
             ],
             'ldflags': [
-              '-nostdlib',
               '-Wl,--no-undefined',
             ],
-            'libraries': [
-              '-l<(android_stlport_library)',
-              # Manually link the libgcc.a that the cross compiler uses.
-              '<!(<(android_toolchain)/*-gcc -print-libgcc-file-name)',
-              '-lc',
-              '-ldl',
-              '-lm',
-            ],
             'conditions': [
               ['component=="static_library"', {
                 'ldflags': [
@@ -4526,13 +4510,18 @@
                 ],
                 'ldflags': [
                   '--sysroot=<(android_ndk_sysroot)',
+                  '-nostdlib',
+                ],
+                'libraries': [
+                  '-l<(android_stlport_library)',
+                  # Manually link the libgcc.a that the cross compiler uses.
+                  '<!(<(android_toolchain)/*-gcc -print-libgcc-file-name)',
+                  '-lc',
+                  '-ldl',
+                  '-lm',
                 ],
               }],
               ['android_webview_build==1', {
-                'include_dirs': [
-                  # OpenAL headers from the Android tree.
-                  '<(android_src)/frameworks/wilhelm/include',
-                ],
                 'cflags': [
                   # Android predefines this as 1; undefine it here so Chromium
                   # can redefine it later to be 2 for chromium code and unset
@@ -4552,6 +4541,9 @@
                   '-Wno-non-virtual-dtor',
                   '-Wno-sign-promo',
                 ],
+                'libraries': [
+                  '-ldl',
+                ],
               }],
               ['android_webview_build==1', {
                 'target_conditions': [
@@ -4584,19 +4576,20 @@
               # don't use '-isystem' because the arm-linux-androideabi-4.4.3
               # toolchain (circa Gingerbread) will exhibit strange errors.
               # The include ordering here is important; change with caution.
-              ['use_system_stlport==1', {
-                'cflags': [
-                  # For libstdc++/include, which is used by stlport.
-                  '-I<(android_src)/bionic',
-                  '-I<(android_src)/external/stlport/stlport',
-                ],
-              }, { # else: use_system_stlport!=1
+              ['android_webview_build==0', {
                 'cflags': [
                   '-isystem<(android_stlport_include)',
                 ],
                 'ldflags': [
                   '-L<(android_stlport_libs_dir)',
                 ],
+              }, { # else: android_webview_build!=0
+                'aosp_build_settings': {
+                  # Specify that we want to statically link stlport from the
+                  # NDK. This will provide all the include and library paths
+                  # automatically at build time, and link the right library.
+                  'LOCAL_NDK_STL_VARIANT': 'stlport_static',
+                },
               }],
               ['target_arch=="ia32"', {
                 # The x86 toolchain currently has problems with stack-protector.
diff --git a/build/config/android/config.gni b/build/config/android/config.gni
index a8701fb..d002ba2 100644
--- a/build/config/android/config.gni
+++ b/build/config/android/config.gni
@@ -10,7 +10,7 @@
     android_src = ""
 
     android_sdk_root = "//third_party/android_tools/sdk"
-    android_sdk_version = "20"
+    android_sdk_version = "21"
 
     # This is set when building the Android WebView inside the Android build
     # system, using the 'android' gyp backend. The WebView code is still built
@@ -68,7 +68,7 @@
   android_sdk = "${android_sdk_root}/platforms/android-${android_sdk_version}"
 
   android_sdk_tools = "${android_sdk_root}/tools"
-  android_sdk_build_tools = "${android_sdk_root}/build-tools/20.0.0"
+  android_sdk_build_tools = "${android_sdk_root}/build-tools/21.0.0"
 
   # Path to the SDK's android.jar
   android_sdk_jar = "$android_sdk/android.jar"
@@ -119,11 +119,7 @@
 
   # stlport stuff --------------------------------------------------------------
 
-  use_system_stlport = is_android_webview_build
-
-  if (use_system_stlport) {
-    android_stlport_library = "stlport"
-  } else if (component_mode == "shared_library") {
+  if (component_mode == "shared_library") {
     android_stlport_library = "stlport_shared"
   } else {
     android_stlport_library = "stlport_static"
@@ -149,5 +145,4 @@
   if (!defined(is_android_webview_build)) {
     is_android_webview_build = false
   }
-  use_system_stlport = false
 }
diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn
index dfe8af1..ba44d1a 100644
--- a/build/config/compiler/BUILD.gn
+++ b/build/config/compiler/BUILD.gn
@@ -458,30 +458,18 @@
     # arm-linux-androideabi-4.4.3 toolchain (circa Gingerbread) will exhibit
     # strange errors. The include ordering here is important; change with
     # caution.
-    if (use_system_stlport) {
-      cflags += [
-        # For libstdc++/include, which is used by stlport.
-        "-I" + rebase_path("$android_src/bionic", root_build_dir),
-        "-I" + rebase_path("$android_src/external/stlport/stlport",
-                           root_build_dir),
-      ]
-      libs += [
-        "stlport",
-      ]
+    android_stlport_root = "$android_ndk_root/sources/cxx-stl/stlport"
+
+    cflags += [
+      "-isystem" + rebase_path("$android_stlport_root/stlport",
+                               root_build_dir)
+    ]
+    lib_dirs += [ "$android_stlport_root/libs/$android_app_abi" ]
+
+    if (component_mode == "shared_library") {
+      libs += [ "stlport_shared" ]
     } else {
-      android_stlport_root = "$android_ndk_root/sources/cxx-stl/stlport"
-
-      cflags += [
-        "-isystem" + rebase_path("$android_stlport_root/stlport",
-                                 root_build_dir)
-      ]
-      lib_dirs += [ "$android_stlport_root/libs/$android_app_abi" ]
-
-      if (component_mode == "shared_library") {
-        libs += [ "stlport_shared" ]
-      } else {
-        libs += [ "stlport_static" ]
-      }
+      libs += [ "stlport_static" ]
     }
 
     if (cpu_arch == "mipsel") {
diff --git a/build/sanitizers/tsan_suppressions.cc b/build/sanitizers/tsan_suppressions.cc
index aa4b7c7..1775f86 100644
--- a/build/sanitizers/tsan_suppressions.cc
+++ b/build/sanitizers/tsan_suppressions.cc
@@ -304,6 +304,9 @@
 // http://crbug.com/415472
 "deadlock:base::debug::TraceLog::GetCategoryGroupEnabled\n"
 
+// http://crbug.com/425057
+"deadlock:webrtc::ViEChannelManagerScoped::ViEChannelManagerScoped\n"
+
 // End of suppressions.
 ;  // Please keep this semicolon.
 
diff --git a/cc/base/tiling_data.cc b/cc/base/tiling_data.cc
index a42fb3c..61bb851 100644
--- a/cc/base/tiling_data.cc
+++ b/cc/base/tiling_data.cc
@@ -510,7 +510,7 @@
   int around_left = 0;
   if (center.x() < 0 || center.IsEmpty())
     around_left = -1;
-  else if (center.x() > tiling_data->tiling_size().width())
+  else if (center.x() >= tiling_data->tiling_size().width())
     around_left = tiling_data->num_tiles_x();
   else
     around_left = tiling_data->TileXIndexFromSrcCoord(center.x());
@@ -519,7 +519,7 @@
   int around_top = 0;
   if (center.y() < 0 || center.IsEmpty())
     around_top = -1;
-  else if (center.y() > tiling_data->tiling_size().height())
+  else if (center.y() >= tiling_data->tiling_size().height())
     around_top = tiling_data->num_tiles_y();
   else
     around_top = tiling_data->TileYIndexFromSrcCoord(center.y());
@@ -529,7 +529,7 @@
   int around_right = 0;
   if (right_src_coord < 0 || center.IsEmpty()) {
     around_right = -1;
-  } else if (right_src_coord > tiling_data->tiling_size().width()) {
+  } else if (right_src_coord >= tiling_data->tiling_size().width()) {
     around_right = tiling_data->num_tiles_x();
   } else {
     around_right = tiling_data->TileXIndexFromSrcCoord(right_src_coord);
@@ -540,7 +540,7 @@
   int around_bottom = 0;
   if (bottom_src_coord < 0 || center.IsEmpty()) {
     around_bottom = -1;
-  } else if (bottom_src_coord > tiling_data->tiling_size().height()) {
+  } else if (bottom_src_coord >= tiling_data->tiling_size().height()) {
     around_bottom = tiling_data->num_tiles_y();
   } else {
     around_bottom = tiling_data->TileYIndexFromSrcCoord(bottom_src_coord);
@@ -652,6 +652,7 @@
 }
 
 void TilingData::SpiralDifferenceIterator::switch_direction() {
+  // Note that delta_x_ and delta_y_ always remain between -1 and 1.
   int new_delta_x_ = delta_y_;
   delta_y_ = -delta_x_;
   delta_x_ = new_delta_x_;
@@ -665,4 +666,265 @@
   }
 }
 
+TilingData::ReverseSpiralDifferenceIterator::ReverseSpiralDifferenceIterator()
+    : BaseIterator(nullptr) {
+  done();
+}
+
+TilingData::ReverseSpiralDifferenceIterator::ReverseSpiralDifferenceIterator(
+    const TilingData* tiling_data,
+    const gfx::Rect& consider_rect,
+    const gfx::Rect& ignore_rect,
+    const gfx::Rect& center_rect)
+    : BaseIterator(tiling_data),
+      consider_left_(-1),
+      consider_top_(-1),
+      consider_right_(-1),
+      consider_bottom_(-1),
+      around_left_(-1),
+      around_top_(-1),
+      around_right_(-1),
+      around_bottom_(-1),
+      ignore_left_(-1),
+      ignore_top_(-1),
+      ignore_right_(-1),
+      ignore_bottom_(-1),
+      direction_(LEFT),
+      delta_x_(-1),
+      delta_y_(0),
+      current_step_(0),
+      horizontal_step_count_(0),
+      vertical_step_count_(0) {
+  if (tiling_data_->num_tiles_x() <= 0 || tiling_data_->num_tiles_y() <= 0) {
+    done();
+    return;
+  }
+
+  gfx::Rect tiling_bounds_rect(tiling_data_->tiling_size());
+  gfx::Rect consider(consider_rect);
+  gfx::Rect ignore(ignore_rect);
+  gfx::Rect center(center_rect);
+  consider.Intersect(tiling_bounds_rect);
+  ignore.Intersect(tiling_bounds_rect);
+  if (consider.IsEmpty()) {
+    done();
+    return;
+  }
+
+  consider_left_ = tiling_data_->TileXIndexFromSrcCoord(consider.x());
+  consider_top_ = tiling_data_->TileYIndexFromSrcCoord(consider.y());
+  consider_right_ = tiling_data_->TileXIndexFromSrcCoord(consider.right() - 1);
+  consider_bottom_ =
+      tiling_data_->TileYIndexFromSrcCoord(consider.bottom() - 1);
+
+  if (!ignore.IsEmpty()) {
+    ignore_left_ = tiling_data_->TileXIndexFromSrcCoord(ignore.x());
+    ignore_top_ = tiling_data_->TileYIndexFromSrcCoord(ignore.y());
+    ignore_right_ = tiling_data_->TileXIndexFromSrcCoord(ignore.right() - 1);
+    ignore_bottom_ = tiling_data_->TileYIndexFromSrcCoord(ignore.bottom() - 1);
+
+    // Clamp ignore indices to consider indices.
+    ignore_left_ = std::max(ignore_left_, consider_left_);
+    ignore_top_ = std::max(ignore_top_, consider_top_);
+    ignore_right_ = std::min(ignore_right_, consider_right_);
+    ignore_bottom_ = std::min(ignore_bottom_, consider_bottom_);
+  }
+
+  if (ignore_left_ == consider_left_ && ignore_right_ == consider_right_ &&
+      ignore_top_ == consider_top_ && ignore_bottom_ == consider_bottom_) {
+    done();
+    return;
+  }
+
+  // Determine around left, such that it is between -1 and num_tiles_x.
+  if (center.x() < 0 || center.IsEmpty())
+    around_left_ = -1;
+  else if (center.x() >= tiling_data->tiling_size().width())
+    around_left_ = tiling_data->num_tiles_x();
+  else
+    around_left_ = tiling_data->TileXIndexFromSrcCoord(center.x());
+
+  // Determine around top, such that it is between -1 and num_tiles_y.
+  if (center.y() < 0 || center.IsEmpty())
+    around_top_ = -1;
+  else if (center.y() >= tiling_data->tiling_size().height())
+    around_top_ = tiling_data->num_tiles_y();
+  else
+    around_top_ = tiling_data->TileYIndexFromSrcCoord(center.y());
+
+  // Determine around right, such that it is between -1 and num_tiles_x.
+  int right_src_coord = center.right() - 1;
+  if (right_src_coord < 0 || center.IsEmpty()) {
+    around_right_ = -1;
+  } else if (right_src_coord >= tiling_data->tiling_size().width()) {
+    around_right_ = tiling_data->num_tiles_x();
+  } else {
+    around_right_ = tiling_data->TileXIndexFromSrcCoord(right_src_coord);
+  }
+
+  // Determine around bottom, such that it is between -1 and num_tiles_y.
+  int bottom_src_coord = center.bottom() - 1;
+  if (bottom_src_coord < 0 || center.IsEmpty()) {
+    around_bottom_ = -1;
+  } else if (bottom_src_coord >= tiling_data->tiling_size().height()) {
+    around_bottom_ = tiling_data->num_tiles_y();
+  } else {
+    around_bottom_ = tiling_data->TileYIndexFromSrcCoord(bottom_src_coord);
+  }
+
+  // Figure out the maximum distance from the around edge to consider edge.
+  int max_distance = 0;
+  max_distance = std::max(max_distance, around_top_ - consider_top_);
+  max_distance = std::max(max_distance, around_left_ - consider_left_);
+  max_distance = std::max(max_distance, consider_bottom_ - around_bottom_);
+  max_distance = std::max(max_distance, consider_right_ - around_right_);
+
+  // The step count is the length of the edge (around_right_ - around_left_ + 1)
+  // plus twice the max distance to pad (to the right and to the left). This way
+  // the initial rect is the size proportional to the center, but big enough
+  // to cover the consider rect.
+  //
+  // C = consider rect
+  // A = around rect
+  // . = area of the padded around rect
+  // md = max distance (note in the picture below, there's md written vertically
+  //      as well).
+  // I = initial starting position
+  //
+  //       |md|  |md|
+  //
+  //     - ..........
+  //     m ..........
+  //     d ..........
+  //     - CCCCCCC...
+  //       CCCCAAC...
+  //       CCCCAAC...
+  //     - ..........
+  //     m ..........
+  //     d ..........
+  //     - ..........I
+  vertical_step_count_ = around_bottom_ - around_top_ + 1 + 2 * max_distance;
+  horizontal_step_count_ = around_right_ - around_left_ + 1 + 2 * max_distance;
+
+  // Start with one to the right of the padded around rect.
+  index_x_ = around_right_ + max_distance + 1;
+  index_y_ = around_bottom_ + max_distance;
+
+  // The current index is outside a valid tile, so advance immediately.
+  ++(*this);
+}
+
+TilingData::ReverseSpiralDifferenceIterator&
+    TilingData::ReverseSpiralDifferenceIterator::
+    operator++() {
+  while (!in_around_rect()) {
+    if (needs_direction_switch())
+      switch_direction();
+
+    index_x_ += delta_x_;
+    index_y_ += delta_y_;
+    ++current_step_;
+
+    if (in_around_rect()) {
+      break;
+    } else if (in_consider_rect()) {
+      // If the tile is in the consider rect but not in ignore rect, then it's a
+      // valid tile to visit.
+      if (!in_ignore_rect())
+        break;
+
+      // Steps needed to reach the very edge of the ignore rect, while remaining
+      // inside it (so that the continue would take us outside).
+      int steps_to_edge = 0;
+      switch (direction_) {
+        case UP:
+          steps_to_edge = index_y_ - ignore_top_;
+          break;
+        case LEFT:
+          steps_to_edge = index_x_ - ignore_left_;
+          break;
+        case DOWN:
+          steps_to_edge = ignore_bottom_ - index_y_;
+          break;
+        case RIGHT:
+          steps_to_edge = ignore_right_ - index_x_;
+          break;
+      }
+
+      // We need to switch directions in |max_steps|.
+      int max_steps = current_step_count() - current_step_;
+
+      int steps_to_take = std::min(steps_to_edge, max_steps);
+      DCHECK_GE(steps_to_take, 0);
+
+      index_x_ += steps_to_take * delta_x_;
+      index_y_ += steps_to_take * delta_y_;
+      current_step_ += steps_to_take;
+    } else {
+      // We're not in the consider rect.
+
+      int max_steps = current_step_count() - current_step_;
+      int steps_to_take = max_steps;
+
+      // We might hit the consider rect before needing to switch directions:
+      // update steps to take.
+      switch (direction_) {
+        case UP:
+          if (valid_column() && consider_bottom_ < index_y_)
+            steps_to_take = index_y_ - consider_bottom_ - 1;
+          break;
+        case LEFT:
+          if (valid_row() && consider_right_ < index_x_)
+            steps_to_take = index_x_ - consider_right_ - 1;
+          break;
+        case DOWN:
+          if (valid_column() && consider_top_ > index_y_)
+            steps_to_take = consider_top_ - index_y_ - 1;
+          break;
+        case RIGHT:
+          if (valid_row() && consider_left_ > index_x_)
+            steps_to_take = consider_left_ - index_x_ - 1;
+          break;
+      }
+      steps_to_take = std::min(steps_to_take, max_steps);
+      DCHECK_GE(steps_to_take, 0);
+
+      index_x_ += steps_to_take * delta_x_;
+      index_y_ += steps_to_take * delta_y_;
+      current_step_ += steps_to_take;
+    }
+  }
+
+  // Once we enter the around rect, we're done.
+  if (in_around_rect())
+    done();
+  return *this;
+}
+
+bool TilingData::ReverseSpiralDifferenceIterator::needs_direction_switch()
+    const {
+  return current_step_ >= current_step_count();
+}
+
+void TilingData::ReverseSpiralDifferenceIterator::switch_direction() {
+  // Note that delta_x_ and delta_y_ always remain between -1 and 1.
+  int new_delta_y_ = delta_x_;
+  delta_x_ = -delta_y_;
+  delta_y_ = new_delta_y_;
+
+  current_step_ = 0;
+  direction_ = static_cast<Direction>((direction_ + 1) % 4);
+
+  if (direction_ == UP || direction_ == DOWN) {
+    --vertical_step_count_;
+    --horizontal_step_count_;
+
+    // We should always end up in an around rect at some point.
+    // Since the direction is now vertical, we have to ensure that we will
+    // advance.
+    DCHECK_GE(horizontal_step_count_, 1);
+    DCHECK_GE(vertical_step_count_, 1);
+  }
+}
+
 }  // namespace cc
diff --git a/cc/base/tiling_data.h b/cc/base/tiling_data.h
index a2e0a13..08d421c 100644
--- a/cc/base/tiling_data.h
+++ b/cc/base/tiling_data.h
@@ -182,6 +182,66 @@
     int vertical_step_count_;
   };
 
+  class CC_EXPORT ReverseSpiralDifferenceIterator : public BaseIterator {
+   public:
+    ReverseSpiralDifferenceIterator();
+    ReverseSpiralDifferenceIterator(const TilingData* tiling_data,
+                                    const gfx::Rect& consider_rect,
+                                    const gfx::Rect& ignore_rect,
+                                    const gfx::Rect& center_rect);
+    ReverseSpiralDifferenceIterator& operator++();
+
+   private:
+    bool in_consider_rect() const {
+      return index_x_ >= consider_left_ && index_x_ <= consider_right_ &&
+             index_y_ >= consider_top_ && index_y_ <= consider_bottom_;
+    }
+    bool in_around_rect() const {
+      return index_x_ >= around_left_ && index_x_ <= around_right_ &&
+             index_y_ >= around_top_ && index_y_ <= around_bottom_;
+    }
+    bool in_ignore_rect() const {
+      return index_x_ >= ignore_left_ && index_x_ <= ignore_right_ &&
+             index_y_ >= ignore_top_ && index_y_ <= ignore_bottom_;
+    }
+    bool valid_column() const {
+      return index_x_ >= consider_left_ && index_x_ <= consider_right_;
+    }
+    bool valid_row() const {
+      return index_y_ >= consider_top_ && index_y_ <= consider_bottom_;
+    }
+
+    int current_step_count() const {
+      return (direction_ == UP || direction_ == DOWN) ? vertical_step_count_
+                                                      : horizontal_step_count_;
+    }
+
+    bool needs_direction_switch() const;
+    void switch_direction();
+
+    int consider_left_;
+    int consider_top_;
+    int consider_right_;
+    int consider_bottom_;
+    int around_left_;
+    int around_top_;
+    int around_right_;
+    int around_bottom_;
+    int ignore_left_;
+    int ignore_top_;
+    int ignore_right_;
+    int ignore_bottom_;
+
+    enum Direction { LEFT, UP, RIGHT, DOWN };
+
+    Direction direction_;
+    int delta_x_;
+    int delta_y_;
+    int current_step_;
+    int horizontal_step_count_;
+    int vertical_step_count_;
+  };
+
  private:
   void AssertTile(int i, int j) const {
     DCHECK_GE(i,  0);
diff --git a/cc/base/tiling_data_unittest.cc b/cc/base/tiling_data_unittest.cc
index 855cd2a..667719b 100644
--- a/cc/base/tiling_data_unittest.cc
+++ b/cc/base/tiling_data_unittest.cc
@@ -1374,20 +1374,42 @@
                        const gfx::Rect& ignore,
                        const gfx::Rect& center,
                        const std::vector<std::pair<int, int>>& expected) {
-  std::vector<std::pair<int, int>> actual;
+  std::vector<std::pair<int, int>> actual_forward;
   for (TilingData::SpiralDifferenceIterator it(
            &tiling_data, consider, ignore, center);
        it;
        ++it) {
-    actual.push_back(it.index());
+    actual_forward.push_back(it.index());
   }
 
-  EXPECT_EQ(expected.size(), actual.size()) << "error from line "
-                                            << source_line_number;
-  for (size_t i = 0; i < std::min(expected.size(), actual.size()); ++i) {
-    EXPECT_EQ(expected[i].first, actual[i].first)
+  EXPECT_EQ(expected.size(), actual_forward.size()) << "error from line "
+                                                    << source_line_number;
+  for (size_t i = 0; i < std::min(expected.size(), actual_forward.size());
+       ++i) {
+    EXPECT_EQ(expected[i].first, actual_forward[i].first)
         << "i: " << i << " error from line: " << source_line_number;
-    EXPECT_EQ(expected[i].second, actual[i].second)
+    EXPECT_EQ(expected[i].second, actual_forward[i].second)
+        << "i: " << i << " error from line: " << source_line_number;
+  }
+
+  std::vector<std::pair<int, int>> actual_reverse;
+  for (TilingData::ReverseSpiralDifferenceIterator it(
+           &tiling_data, consider, ignore, center);
+       it;
+       ++it) {
+    actual_reverse.push_back(it.index());
+  }
+
+  std::vector<std::pair<int, int>> reversed_expected = expected;
+  std::reverse(reversed_expected.begin(), reversed_expected.end());
+  EXPECT_EQ(reversed_expected.size(), actual_reverse.size())
+      << "error from line " << source_line_number;
+  for (size_t i = 0;
+       i < std::min(reversed_expected.size(), actual_reverse.size());
+       ++i) {
+    EXPECT_EQ(reversed_expected[i].first, actual_reverse[i].first)
+        << "i: " << i << " error from line: " << source_line_number;
+    EXPECT_EQ(reversed_expected[i].second, actual_reverse[i].second)
         << "i: " << i << " error from line: " << source_line_number;
   }
 }
diff --git a/cc/resources/picture_layer_tiling.cc b/cc/resources/picture_layer_tiling.cc
index a6c46a1..f47c700 100644
--- a/cc/resources/picture_layer_tiling.cc
+++ b/cc/resources/picture_layer_tiling.cc
@@ -466,6 +466,7 @@
     return false;
   found->second->set_shared(false);
   tiles_.erase(found);
+  eviction_tiles_cache_valid_ = false;
   if (recycled_twin) {
     // Recycled twin does not also have a recycled twin, so pass NULL.
     recycled_twin->RemoveTileAt(i, j, NULL);
diff --git a/cc/resources/picture_layer_tiling_unittest.cc b/cc/resources/picture_layer_tiling_unittest.cc
index 2ff5f8e..c871da4 100644
--- a/cc/resources/picture_layer_tiling_unittest.cc
+++ b/cc/resources/picture_layer_tiling_unittest.cc
@@ -64,8 +64,12 @@
   }
 
   gfx::Rect live_tiles_rect() const { return live_tiles_rect_; }
+  bool eviction_tiles_cache_valid() const {
+    return eviction_tiles_cache_valid_;
+  }
 
   using PictureLayerTiling::ComputeSkewport;
+  using PictureLayerTiling::RemoveTileAt;
 
  protected:
   TestablePictureLayerTiling(float contents_scale,
@@ -1344,6 +1348,10 @@
 
   EXPECT_GT(all_tiles_set.size(), 0u);
   EXPECT_EQ(all_tiles_set, eviction_tiles);
+
+  EXPECT_TRUE(tiling->eviction_tiles_cache_valid());
+  tiling->RemoveTileAt(0, 0, nullptr);
+  EXPECT_FALSE(tiling->eviction_tiles_cache_valid());
 }
 
 TEST_F(PictureLayerTilingIteratorTest, TilesExist) {
diff --git a/cc/resources/scoped_resource.cc b/cc/resources/scoped_resource.cc
index 407de51..c83efb5 100644
--- a/cc/resources/scoped_resource.cc
+++ b/cc/resources/scoped_resource.cc
@@ -59,8 +59,4 @@
   set_id(0);
 }
 
-void ScopedResource::Leak() {
-  set_id(0);
-}
-
 }  // namespace cc
diff --git a/cc/resources/scoped_resource.h b/cc/resources/scoped_resource.h
index f2c1a0d..4241b38 100644
--- a/cc/resources/scoped_resource.h
+++ b/cc/resources/scoped_resource.h
@@ -32,7 +32,6 @@
                        GLenum target,
                        ResourceFormat format);
   void Free();
-  void Leak();
 
  protected:
   explicit ScopedResource(ResourceProvider* provider);
diff --git a/cc/resources/scoped_resource_unittest.cc b/cc/resources/scoped_resource_unittest.cc
index 04d6329..7c7e055 100644
--- a/cc/resources/scoped_resource_unittest.cc
+++ b/cc/resources/scoped_resource_unittest.cc
@@ -112,43 +112,5 @@
   }
 }
 
-TEST(ScopedResourceTest, LeakScopedResource) {
-  FakeOutputSurfaceClient output_surface_client;
-  scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d());
-  CHECK(output_surface->BindToClient(&output_surface_client));
-
-  scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
-      new TestSharedBitmapManager());
-  scoped_ptr<ResourceProvider> resource_provider(
-      ResourceProvider::Create(output_surface.get(),
-                               shared_bitmap_manager.get(),
-                               NULL,
-                               NULL,
-                               0,
-                               false,
-                               1,
-                               false));
-  {
-    scoped_ptr<ScopedResource> texture =
-        ScopedResource::Create(resource_provider.get());
-
-    EXPECT_EQ(0u, resource_provider->num_resources());
-    texture->Allocate(
-        gfx::Size(30, 30), ResourceProvider::TextureHintImmutable, RGBA_8888);
-    EXPECT_LT(0u, texture->id());
-    EXPECT_EQ(1u, resource_provider->num_resources());
-
-    texture->Leak();
-    EXPECT_EQ(0u, texture->id());
-    EXPECT_EQ(1u, resource_provider->num_resources());
-
-    texture->Free();
-    EXPECT_EQ(0u, texture->id());
-    EXPECT_EQ(1u, resource_provider->num_resources());
-  }
-
-  EXPECT_EQ(1u, resource_provider->num_resources());
-}
-
 }  // namespace
 }  // namespace cc
diff --git a/cc/trees/layer_tree_host_unittest_animation.cc b/cc/trees/layer_tree_host_unittest_animation.cc
index f3bbe0a..67fb6f8 100644
--- a/cc/trees/layer_tree_host_unittest_animation.cc
+++ b/cc/trees/layer_tree_host_unittest_animation.cc
@@ -1079,76 +1079,6 @@
 SINGLE_AND_MULTI_THREAD_TEST_F(
     LayerTreeHostAnimationTestScrollOffsetChangesArePropagated);
 
-// Ensure that animation time is correctly updated when animations are frozen
-// because of checkerboarding.
-class LayerTreeHostAnimationTestFrozenAnimationTickTime
-    : public LayerTreeHostAnimationTest {
- public:
-  LayerTreeHostAnimationTestFrozenAnimationTickTime()
-      : started_animating_(false), num_commits_(0), num_draw_attempts_(2) {}
-
-  virtual void InitializeSettings(LayerTreeSettings* settings) override {
-    // Make sure that drawing many times doesn't cause a checkerboarded
-    // animation to start so we avoid flake in this test.
-    settings->timeout_and_draw_when_animation_checkerboards = false;
-  }
-
-  virtual void BeginTest() override {
-    PostAddAnimationToMainThread(layer_tree_host()->root_layer());
-  }
-
-  virtual void BeginMainFrame(const BeginFrameArgs& args) override {
-    last_main_thread_tick_time_ = args.frame_time;
-  }
-
-  virtual void AnimateLayers(LayerTreeHostImpl* host_impl,
-                             base::TimeTicks monotonic_time) override {
-    if (TestEnded())
-      return;
-    if (!started_animating_) {
-      started_animating_ = true;
-      expected_impl_tick_time_ = monotonic_time;
-    } else {
-      EXPECT_EQ(expected_impl_tick_time_, monotonic_time);
-      if (num_commits_ > 2)
-        EndTest();
-    }
-  }
-
-  virtual DrawResult PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
-                                           LayerTreeHostImpl::FrameData* frame,
-                                           DrawResult draw_result) override {
-    if (TestEnded())
-      return draw_result;
-    num_draw_attempts_++;
-    if (num_draw_attempts_ > 2) {
-      num_draw_attempts_ = 0;
-      PostSetNeedsCommitToMainThread();
-    }
-    return DRAW_ABORTED_CHECKERBOARD_ANIMATIONS;
-  }
-
-  virtual void BeginCommitOnThread(LayerTreeHostImpl* host_impl) override {
-    if (!started_animating_)
-      return;
-    expected_impl_tick_time_ =
-        std::max(expected_impl_tick_time_, last_main_thread_tick_time_);
-    num_commits_++;
-  }
-
-  virtual void AfterTest() override {}
-
- private:
-  bool started_animating_;
-  int num_commits_;
-  int num_draw_attempts_;
-  base::TimeTicks last_main_thread_tick_time_;
-  base::TimeTicks expected_impl_tick_time_;
-};
-
-// Only the non-impl-paint multi-threaded compositor freezes animations.
-MULTI_THREAD_NOIMPL_TEST_F(LayerTreeHostAnimationTestFrozenAnimationTickTime);
-
 // When animations are simultaneously added to an existing layer and to a new
 // layer, they should start at the same time, even when there's already a
 // running animation on the existing layer.
diff --git a/cc/trees/thread_proxy.cc b/cc/trees/thread_proxy.cc
index 24286e1..f1ef361 100644
--- a/cc/trees/thread_proxy.cc
+++ b/cc/trees/thread_proxy.cc
@@ -107,7 +107,6 @@
       next_frame_is_newly_committed_frame(false),
       inside_draw(false),
       input_throttled_until_commit(false),
-      animations_frozen_until_next_draw(false),
       did_commit_after_animating(false),
       smoothness_priority_expiration_notifier(
           proxy->ImplThreadTaskRunner(),
@@ -188,8 +187,6 @@
       impl().layer_tree_host_impl->active_tree()->root_layer();
   impl().layer_tree_host_impl->UpdateBackgroundAnimateTicking(
       should_background_tick);
-  if (should_background_tick)
-    impl().animations_frozen_until_next_draw = false;
 }
 
 void ThreadProxy::DidLoseOutputSurface() {
@@ -767,8 +764,6 @@
   layer_tree_host()->BeginMainFrame(begin_main_frame_state->begin_frame_args);
   layer_tree_host()->AnimateLayers(
       begin_main_frame_state->begin_frame_args.frame_time);
-  blocked_main().last_monotonic_frame_begin_time =
-      begin_main_frame_state->begin_frame_args.frame_time;
 
   // Unlink any backings that the impl thread has evicted, so that we know to
   // re-paint them in UpdateLayers.
@@ -939,10 +934,8 @@
   TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionAnimate");
   DCHECK(IsImplThread());
 
-  if (!impl().animations_frozen_until_next_draw) {
-    impl().animation_time =
-        impl().layer_tree_host_impl->CurrentBeginFrameArgs().frame_time;
-  }
+  impl().animation_time =
+      impl().layer_tree_host_impl->CurrentBeginFrameArgs().frame_time;
   impl().layer_tree_host_impl->Animate(impl().animation_time);
   impl().did_commit_after_animating = false;
 }
@@ -958,10 +951,6 @@
   impl().current_resource_update_controller->Finalize();
   impl().current_resource_update_controller = nullptr;
 
-  if (impl().animations_frozen_until_next_draw) {
-    impl().animation_time = std::max(
-        impl().animation_time, blocked_main().last_monotonic_frame_begin_time);
-  }
   impl().did_commit_after_animating = true;
 
   blocked_main().main_thread_inside_commit = true;
@@ -1064,17 +1053,6 @@
     impl().layer_tree_host_impl->DrawLayers(
         &frame, impl().scheduler->LastBeginImplFrameTime());
     result = DRAW_SUCCESS;
-    impl().animations_frozen_until_next_draw = false;
-  } else if (result == DRAW_ABORTED_CHECKERBOARD_ANIMATIONS &&
-             !impl().layer_tree_host_impl->settings().impl_side_painting) {
-    // Without impl-side painting, the animated layer that is checkerboarding
-    // will continue to checkerboard until the next commit. If this layer
-    // continues to move during the commit, it may continue to checkerboard
-    // after the commit since the region rasterized during the commit will not
-    // match the region that is currently visible; eventually this
-    // checkerboarding will be displayed when we force a draw. To avoid this,
-    // we freeze animations until we successfully draw.
-    impl().animations_frozen_until_next_draw = true;
   } else {
     DCHECK_NE(DRAW_SUCCESS, result);
   }
diff --git a/cc/trees/thread_proxy.h b/cc/trees/thread_proxy.h
index 817b36d..c2440e5 100644
--- a/cc/trees/thread_proxy.h
+++ b/cc/trees/thread_proxy.h
@@ -90,8 +90,6 @@
     LayerTreeHost* layer_tree_host;
     bool commit_waits_for_activation;
     bool main_thread_inside_commit;
-
-    base::TimeTicks last_monotonic_frame_begin_time;
   };
 
   struct CompositorThreadOnly {
@@ -129,8 +127,6 @@
 
     bool input_throttled_until_commit;
 
-    // Set when we freeze animations to avoid checkerboarding.
-    bool animations_frozen_until_next_draw;
     base::TimeTicks animation_time;
 
     // Whether a commit has been completed since the last time animations were
diff --git a/mojo/apps/js/main.js b/mojo/apps/js/main.js
index 3a44f04..f8be85c 100644
--- a/mojo/apps/js/main.js
+++ b/mojo/apps/js/main.js
@@ -6,13 +6,13 @@
 // services and then prints a brief summary of the response.
 //
 // To run it using mojo_js_standalone (don't forget the quotes):
-//   mojo_shell 'mojo://mojo_js_standalone THIS_DIR/main.js'
+//   mojo_shell 'mojo://js_standalone THIS_DIR/main.js'
 //
 // To run it using mojo_js_content handler this file must be specified as
 // a URL. For example:
 //   (cd YOUR_DIR/mojo/apps/js; python -m SimpleHTTPServer ) &
 //   mojo_shell \
-//    --content-handlers=application/javascript,mojo://mojo_js_content_handler \
+//    --content-handlers=application/javascript,mojo://js_content_handler \
 //    http://localhost:8000/test.js
 
 define("test", [
@@ -26,7 +26,7 @@
 ], function(mojo, core, connection, support, net, loader, console) {
 
   var networkService = mojo.connectToService(
-      "mojo:mojo_network_service", net.NetworkService);
+      "mojo:network_service", net.NetworkService);
 
   var urlLoaderPipe = core.createMessagePipe();
   networkService.createURLLoader(urlLoaderPipe.handle1);
diff --git a/mojo/aura/surface_binding.cc b/mojo/aura/surface_binding.cc
index 3c9584e..fc1d31a 100644
--- a/mojo/aura/surface_binding.cc
+++ b/mojo/aura/surface_binding.cc
@@ -205,7 +205,7 @@
   DCHECK(!surfaces_service_.get());
 
   ServiceProviderPtr surfaces_service_provider;
-  shell_->ConnectToApplication("mojo:mojo_surfaces_service",
+  shell_->ConnectToApplication("mojo:surfaces_service",
                                GetProxy(&surfaces_service_provider));
   ConnectToService(surfaces_service_provider.get(), &surfaces_service_);
   // base::Unretained is ok here as we block until the call is received.
@@ -221,8 +221,8 @@
   surface_.set_client(surface_client_.get());
 
   ServiceProviderPtr gpu_service_provider;
-  // TODO(jamesr): Should be mojo:mojo_gpu_service
-  shell_->ConnectToApplication("mojo:mojo_native_viewport_service",
+  // TODO(jamesr): Should be mojo:gpu_service
+  shell_->ConnectToApplication("mojo:native_viewport_service",
                                GetProxy(&gpu_service_provider));
   ConnectToService(gpu_service_provider.get(), &gpu_);
 }
diff --git a/mojo/examples/apptest/BUILD.gn b/mojo/examples/apptest/BUILD.gn
index 456f0d4..fd9651e 100644
--- a/mojo/examples/apptest/BUILD.gn
+++ b/mojo/examples/apptest/BUILD.gn
@@ -13,7 +13,6 @@
   ]
 }
 
-# GYP version mojo/mojo_examples.gypi:mojo_example_service
 shared_library("service") {
   output_name = "mojo_example_service"
 
@@ -32,7 +31,6 @@
   ]
 }
 
-# GYP version: mojo/mojo_examples.gypi:mojo_example_apptests
 shared_library("apptests") {
   output_name = "mojo_example_apptests"
 
@@ -55,7 +53,6 @@
    ]
 }
 
-# GYP version: mojo/mojo_examples.gypi:mojo_example_service_bindings
 mojom("bindings") {
   sources = [ "example_service.mojom" ]
 }
diff --git a/mojo/examples/apptest/example_apptest.cc b/mojo/examples/apptest/example_apptest.cc
index dba00e0..2041fde 100644
--- a/mojo/examples/apptest/example_apptest.cc
+++ b/mojo/examples/apptest/example_apptest.cc
@@ -84,7 +84,7 @@
   }
   virtual void SetUp() override {
     Apptest::SetUp();
-    application_impl()->ConnectToService("mojo:mojo_example_service",
+    application_impl()->ConnectToService("mojo:example_service",
                                          &example_service_);
     example_service_.set_client(&example_client_);
   }
@@ -144,7 +144,7 @@
 
     // Construct an ApplicationImpl just for the GTEST commandline arguments.
     // GTEST command line arguments are supported amid application arguments:
-    //   mojo_shell 'mojo:mojo_example_apptest arg1 --gtest_filter=foo arg2'
+    //   mojo_shell 'mojo:example_apptest arg1 --gtest_filter=foo arg2'
     mojo::ApplicationDelegate dummy_application_delegate;
     mojo::ApplicationImpl app(&dummy_application_delegate, shell_handle);
     MOJO_CHECK(app.WaitForInitialize());
diff --git a/mojo/examples/aura_demo/BUILD.gn b/mojo/examples/aura_demo/BUILD.gn
index ecd1843..1c72ece 100644
--- a/mojo/examples/aura_demo/BUILD.gn
+++ b/mojo/examples/aura_demo/BUILD.gn
@@ -6,7 +6,6 @@
 
 assert(use_aura)
 
-# GYP version mojo/mojo_examples.gypi:mojo_aura_demo
 shared_library("mojo_aura_demo") {
   output_name = "mojo_aura_demo"
 
@@ -34,7 +33,6 @@
   datadeps = [ ":init" ]
 }
 
-# GYP version mojo/mojo_examples.gypi:mojo_aura_demo_init
 shared_library("init") {
   output_name = "mojo_aura_demo_init"
 
diff --git a/mojo/examples/aura_demo/view_manager_init.cc b/mojo/examples/aura_demo/view_manager_init.cc
index bd07e6d..5624568 100644
--- a/mojo/examples/aura_demo/view_manager_init.cc
+++ b/mojo/examples/aura_demo/view_manager_init.cc
@@ -23,7 +23,7 @@
 
   virtual void Initialize(mojo::ApplicationImpl* app) override {
     context_.reset(new mojo::ViewManagerContext(app));
-    context_->Embed("mojo:mojo_aura_demo");
+    context_->Embed("mojo:aura_demo");
   }
 
  private:
diff --git a/mojo/examples/bitmap_uploader/BUILD.gn b/mojo/examples/bitmap_uploader/BUILD.gn
index 3606c44..ba8f936 100644
--- a/mojo/examples/bitmap_uploader/BUILD.gn
+++ b/mojo/examples/bitmap_uploader/BUILD.gn
@@ -2,7 +2,6 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-# GYP version: mojo/mojo_examples.gypi:mojo_bitmap_uploader
 source_set("bitmap_uploader") {
   sources = [
     "bitmap_uploader.cc",
diff --git a/mojo/examples/bitmap_uploader/bitmap_uploader.cc b/mojo/examples/bitmap_uploader/bitmap_uploader.cc
index ef19156..dfd7a7d 100644
--- a/mojo/examples/bitmap_uploader/bitmap_uploader.cc
+++ b/mojo/examples/bitmap_uploader/bitmap_uploader.cc
@@ -45,11 +45,11 @@
 
 void BitmapUploader::Init(Shell* shell) {
   ServiceProviderPtr surfaces_service_provider;
-  shell->ConnectToApplication("mojo:mojo_surfaces_service",
+  shell->ConnectToApplication("mojo:surfaces_service",
                               GetProxy(&surfaces_service_provider));
   ConnectToService(surfaces_service_provider.get(), &surfaces_service_);
   ServiceProviderPtr gpu_service_provider;
-  shell->ConnectToApplication("mojo:mojo_native_viewport_service",
+  shell->ConnectToApplication("mojo:native_viewport_service",
                               GetProxy(&gpu_service_provider));
   ConnectToService(gpu_service_provider.get(), &gpu_service_);
 
diff --git a/mojo/examples/browser/BUILD.gn b/mojo/examples/browser/BUILD.gn
index b0b1780..d28a971 100644
--- a/mojo/examples/browser/BUILD.gn
+++ b/mojo/examples/browser/BUILD.gn
@@ -6,7 +6,6 @@
 
 assert(use_aura)
 
-# GYP version: mojo/mojo_examples.gypi:mojo_browser
 shared_library("browser") {
   output_name = "mojo_browser"
 
diff --git a/mojo/examples/browser/browser.cc b/mojo/examples/browser/browser.cc
index 39ddc6b..e5f724e 100644
--- a/mojo/examples/browser/browser.cc
+++ b/mojo/examples/browser/browser.cc
@@ -169,7 +169,7 @@
     view_manager_client_factory_.reset(
         new ViewManagerClientFactory(shell_, this));
     views_init_.reset(new ViewsInit);
-    app->ConnectToService("mojo:mojo_window_manager", &window_manager_);
+    app->ConnectToService("mojo:window_manager", &window_manager_);
  }
 
  virtual bool ConfigureIncomingConnection(
diff --git a/mojo/examples/content_handler_demo/BUILD.gn b/mojo/examples/content_handler_demo/BUILD.gn
index cd8bcbb..d7a036b 100644
--- a/mojo/examples/content_handler_demo/BUILD.gn
+++ b/mojo/examples/content_handler_demo/BUILD.gn
@@ -2,7 +2,6 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-# GYP version: mojo/mojo_examples.gypi:mojo_content_handler_demo
 shared_library("content_handler_demo") {
   output_name = "mojo_content_handler_demo"
 
diff --git a/mojo/examples/demo_launcher/BUILD.gn b/mojo/examples/demo_launcher/BUILD.gn
index 6ecbbfa..5925afb 100644
--- a/mojo/examples/demo_launcher/BUILD.gn
+++ b/mojo/examples/demo_launcher/BUILD.gn
@@ -6,7 +6,6 @@
 
 assert(use_aura)
 
-# GYP version: mojo/mojo_examples.gypi:mojo_demo_launcher
 shared_library("demo_launcher") {
   output_name = "mojo_demo_launcher"
 
diff --git a/mojo/examples/demo_launcher/demo_launcher.cc b/mojo/examples/demo_launcher/demo_launcher.cc
index 2165e2e..820d0ad 100644
--- a/mojo/examples/demo_launcher/demo_launcher.cc
+++ b/mojo/examples/demo_launcher/demo_launcher.cc
@@ -18,7 +18,7 @@
  private:
   virtual void Initialize(mojo::ApplicationImpl* app) override {
     context_.reset(new mojo::ViewManagerContext(app));
-    context_->Embed("mojo:mojo_window_manager");
+    context_->Embed("mojo:window_manager");
   }
 
   scoped_ptr<mojo::ViewManagerContext> context_;
diff --git a/mojo/examples/echo/BUILD.gn b/mojo/examples/echo/BUILD.gn
index 0f518b4..6c390c9 100644
--- a/mojo/examples/echo/BUILD.gn
+++ b/mojo/examples/echo/BUILD.gn
@@ -11,7 +11,6 @@
   ]
 }
 
-# GYP version: mojo/mojo_examples.gypi:mojo_echo_client
 shared_library("client") {
   output_name = "mojo_echo_client"
 
@@ -26,7 +25,6 @@
   sources = [ "echo_client.cc" ]
 }
 
-# GYP version: mojo/mojo_examples.gypi:mojo_echo_service
 shared_library("service") {
   output_name = "mojo_echo_service"
 
@@ -41,7 +39,6 @@
   sources = [ "echo_service.cc" ]
 }
 
-# GYP version: mojo/mojo_examples.gypi:mojo_echo_service_bindings
 mojom("bindings") {
   sources = [ "echo_service.mojom" ]
 }
diff --git a/mojo/examples/echo/echo_client.cc b/mojo/examples/echo/echo_client.cc
index 2eeae0d..1d44d08 100644
--- a/mojo/examples/echo/echo_client.cc
+++ b/mojo/examples/echo/echo_client.cc
@@ -26,7 +26,7 @@
 class EchoClientDelegate : public ApplicationDelegate {
  public:
   virtual void Initialize(ApplicationImpl* app) override {
-    app->ConnectToService("mojo:mojo_echo_service", &echo_service_);
+    app->ConnectToService("mojo:echo_service", &echo_service_);
 
     echo_service_->EchoString("hello world", ResponsePrinter());
   }
diff --git a/mojo/examples/http_server/http_server.cc b/mojo/examples/http_server/http_server.cc
index 389c953..24e4fe7 100644
--- a/mojo/examples/http_server/http_server.cc
+++ b/mojo/examples/http_server/http_server.cc
@@ -100,7 +100,7 @@
 class HttpServerApp : public ApplicationDelegate {
  public:
   virtual void Initialize(ApplicationImpl* app) override {
-    app->ConnectToService("mojo:mojo_network_service", &network_service_);
+    app->ConnectToService("mojo:network_service", &network_service_);
     Start();
   }
 
diff --git a/mojo/examples/keyboard/BUILD.gn b/mojo/examples/keyboard/BUILD.gn
index 2feabcc..0b971b2 100644
--- a/mojo/examples/keyboard/BUILD.gn
+++ b/mojo/examples/keyboard/BUILD.gn
@@ -7,7 +7,6 @@
 
 assert(use_aura)
 
-# GYP version: mojo/mojo_examples.gypi:mojo_keyboard
 shared_library("keyboard") {
   output_name = "mojo_keyboard"
 
@@ -48,7 +47,6 @@
   ]
 }
 
-# GYP version: mojo/mojo_examples.gypi:mojo_keyboard_bindings
 mojom("bindings") {
   sources = [ "keyboard.mojom" ]
 }
diff --git a/mojo/examples/media_viewer/BUILD.gn b/mojo/examples/media_viewer/BUILD.gn
index b251b2d..ae75ec3 100644
--- a/mojo/examples/media_viewer/BUILD.gn
+++ b/mojo/examples/media_viewer/BUILD.gn
@@ -7,7 +7,6 @@
 
 if (use_aura) {
 
-# GYP version: mojo/mojo_examples.gypi:mojo_media_viewer
 shared_library("media_viewer") {
   output_name = "mojo_media_viewer"
 
@@ -34,7 +33,6 @@
 
 }  # use_aura
 
-# GYP version: mojo/mojo_examples.gypi:mojo_media_viewer_bindings
 mojom("bindings") {
   sources = [
     "media_viewer.mojom",
diff --git a/mojo/examples/media_viewer/media_viewer.cc b/mojo/examples/media_viewer/media_viewer.cc
index 533fe36..4d23a8e 100644
--- a/mojo/examples/media_viewer/media_viewer.cc
+++ b/mojo/examples/media_viewer/media_viewer.cc
@@ -203,7 +203,7 @@
         control_view_(NULL),
         content_view_(NULL),
         control_panel_(this) {
-    handler_map_["image/png"] = "mojo:mojo_png_viewer";
+    handler_map_["image/png"] = "mojo:png_viewer";
   }
 
   virtual ~MediaViewer() {
diff --git a/mojo/examples/nesting_app/BUILD.gn b/mojo/examples/nesting_app/BUILD.gn
index 86f611c..0043517 100644
--- a/mojo/examples/nesting_app/BUILD.gn
+++ b/mojo/examples/nesting_app/BUILD.gn
@@ -2,7 +2,6 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-# GYP version: mojo/mojo_examples.gypi:mojo_nesting_app
 shared_library("nesting_app") {
   output_name = "mojo_nesting_app"
 
diff --git a/mojo/examples/nesting_app/nesting_app.cc b/mojo/examples/nesting_app/nesting_app.cc
index e3bcbcd..4473d6f 100644
--- a/mojo/examples/nesting_app/nesting_app.cc
+++ b/mojo/examples/nesting_app/nesting_app.cc
@@ -26,7 +26,7 @@
 namespace examples {
 
 namespace {
-const char kEmbeddedAppURL[] = "mojo:mojo_embedded_app";
+const char kEmbeddedAppURL[] = "mojo:embedded_app";
 }
 
 class NestingApp;
diff --git a/mojo/examples/pepper_container_app/BUILD.gn b/mojo/examples/pepper_container_app/BUILD.gn
index aa9d7af..74b6fd8 100644
--- a/mojo/examples/pepper_container_app/BUILD.gn
+++ b/mojo/examples/pepper_container_app/BUILD.gn
@@ -2,7 +2,6 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-# GYP version: mojo/mojo_examples.gypi:mojo_pepper_container_app
 shared_library("pepper_container_app") {
   output_name = "mojo_pepper_container_app"
 
diff --git a/mojo/examples/pepper_container_app/pepper_container_app.cc b/mojo/examples/pepper_container_app/pepper_container_app.cc
index 82c35f0..d8761ec 100644
--- a/mojo/examples/pepper_container_app/pepper_container_app.cc
+++ b/mojo/examples/pepper_container_app/pepper_container_app.cc
@@ -38,11 +38,11 @@
   virtual ~PepperContainerApp() {}
 
   virtual void Initialize(ApplicationImpl* app) override {
-    app->ConnectToService("mojo:mojo_native_viewport_service", &viewport_);
+    app->ConnectToService("mojo:native_viewport_service", &viewport_);
     viewport_.set_client(this);
 
-    // TODO(jamesr): Should be mojo:mojo_gpu_service
-    app->ConnectToService("mojo:mojo_native_viewport_service", &gpu_service_);
+    // TODO(jamesr): Should be mojo:gpu_service
+    app->ConnectToService("mojo:native_viewport_service", &gpu_service_);
 
     SizePtr size(Size::New());
     size->width = 800;
diff --git a/mojo/examples/png_viewer/BUILD.gn b/mojo/examples/png_viewer/BUILD.gn
index e5265b3..eedc334 100644
--- a/mojo/examples/png_viewer/BUILD.gn
+++ b/mojo/examples/png_viewer/BUILD.gn
@@ -2,7 +2,6 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-# GYP version: mojo/mojo_examples.gypi:mojo_png_viewer
 shared_library("png_viewer") {
   output_name = "mojo_png_viewer"
 
diff --git a/mojo/examples/sample_app/BUILD.gn b/mojo/examples/sample_app/BUILD.gn
index d44e6e4..ffe2aff 100644
--- a/mojo/examples/sample_app/BUILD.gn
+++ b/mojo/examples/sample_app/BUILD.gn
@@ -2,7 +2,6 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-# GYP version: mojo/mojo_examples.gypi:mojo_sample_app
 shared_library("sample_app") {
   output_name = "mojo_sample_app"
 
diff --git a/mojo/examples/sample_app/sample_app.cc b/mojo/examples/sample_app/sample_app.cc
index 96cdac9..faa3c44 100644
--- a/mojo/examples/sample_app/sample_app.cc
+++ b/mojo/examples/sample_app/sample_app.cc
@@ -32,11 +32,11 @@
   }
 
   virtual void Initialize(mojo::ApplicationImpl* app) override {
-    app->ConnectToService("mojo:mojo_native_viewport_service", &viewport_);
+    app->ConnectToService("mojo:native_viewport_service", &viewport_);
     viewport_.set_client(this);
 
-    // TODO(jamesr): Should be mojo:mojo_gpu_service
-    app->ConnectToService("mojo:mojo_native_viewport_service", &gpu_service_);
+    // TODO(jamesr): Should be mojo:gpu_service
+    app->ConnectToService("mojo:native_viewport_service", &gpu_service_);
 
     mojo::SizePtr size(mojo::Size::New());
     size->width = 800;
diff --git a/mojo/examples/surfaces_app/BUILD.gn b/mojo/examples/surfaces_app/BUILD.gn
index 5474752..d722395 100644
--- a/mojo/examples/surfaces_app/BUILD.gn
+++ b/mojo/examples/surfaces_app/BUILD.gn
@@ -12,7 +12,6 @@
   ]
 }
 
-# GYP version: mojo/mojo_examples.gypi:mojo_surfaces_app
 shared_library("parent_app") {
   output_name = "mojo_surfaces_app"
 
@@ -46,7 +45,6 @@
 }
 
 
-# GYP version: mojo/mojo_examples.gypi:mojo_surfaces_child_app
 shared_library("child_app") {
   output_name = "mojo_surfaces_child_app"
 
@@ -78,7 +76,6 @@
   ]
 }
 
-# GYP version: mojo/mojo_examples.gypi:mojo_surfaces_child_gl_app
 shared_library("child_gl_app") {
   output_name = "mojo_surfaces_child_gl_app"
 
@@ -130,7 +127,6 @@
   ]
 }
 
-# GYP version: mojo/mojo_examples.gypi:mojo_surfaces_app_bindings
 mojom("bindings") {
   deps = [
     "//mojo/services/public/interfaces/geometry",
diff --git a/mojo/examples/surfaces_app/child_app.cc b/mojo/examples/surfaces_app/child_app.cc
index 04c1fba..ecd371e 100644
--- a/mojo/examples/surfaces_app/child_app.cc
+++ b/mojo/examples/surfaces_app/child_app.cc
@@ -21,7 +21,7 @@
 
   virtual void Initialize(ApplicationImpl* app) override {
     surfaces_service_connection_ =
-        app->ConnectToApplication("mojo:mojo_surfaces_service");
+        app->ConnectToApplication("mojo:surfaces_service");
   }
 
   // ApplicationDelegate implementation.
diff --git a/mojo/examples/surfaces_app/child_gl_app.cc b/mojo/examples/surfaces_app/child_gl_app.cc
index b84826b..a18b208 100644
--- a/mojo/examples/surfaces_app/child_gl_app.cc
+++ b/mojo/examples/surfaces_app/child_gl_app.cc
@@ -23,9 +23,9 @@
 
   virtual void Initialize(ApplicationImpl* app) override {
     surfaces_service_connection_ =
-        app->ConnectToApplication("mojo:mojo_surfaces_service");
-    // TODO(jamesr): Should be mojo:mojo_gpu_service
-    app->ConnectToService("mojo:mojo_native_viewport_service", &gpu_service_);
+        app->ConnectToApplication("mojo:surfaces_service");
+    // TODO(jamesr): Should be mojo:gpu_service
+    app->ConnectToService("mojo:native_viewport_service", &gpu_service_);
   }
 
   // ApplicationDelegate implementation.
diff --git a/mojo/examples/surfaces_app/surfaces_app.cc b/mojo/examples/surfaces_app/surfaces_app.cc
index 0776e01..307c20c 100644
--- a/mojo/examples/surfaces_app/surfaces_app.cc
+++ b/mojo/examples/surfaces_app/surfaces_app.cc
@@ -36,12 +36,10 @@
   // ApplicationDelegate implementation
   virtual bool ConfigureIncomingConnection(
       ApplicationConnection* connection) override {
-    connection->ConnectToService("mojo:mojo_native_viewport_service",
-                                 &viewport_);
+    connection->ConnectToService("mojo:native_viewport_service", &viewport_);
     viewport_.set_client(this);
 
-    connection->ConnectToService("mojo:mojo_surfaces_service",
-                                 &surfaces_service_);
+    connection->ConnectToService("mojo:surfaces_service", &surfaces_service_);
     surfaces_service_->CreateSurfaceConnection(base::Bind(
         &SurfacesApp::SurfaceConnectionCreated, base::Unretained(this)));
 
@@ -53,9 +51,8 @@
     viewport_->Show();
 
     child_size_ = gfx::Size(size_.width() / 3, size_.height() / 2);
-    connection->ConnectToService("mojo:mojo_surfaces_child_app", &child_one_);
-    connection->ConnectToService("mojo:mojo_surfaces_child_gl_app",
-                                 &child_two_);
+    connection->ConnectToService("mojo:surfaces_child_app", &child_one_);
+    connection->ConnectToService("mojo:surfaces_child_gl_app", &child_two_);
     child_one_->ProduceFrame(Color::From(SK_ColorBLUE),
                              Size::From(child_size_),
                              base::Bind(&SurfacesApp::ChildOneProducedFrame,
diff --git a/mojo/examples/wget/BUILD.gn b/mojo/examples/wget/BUILD.gn
index 448e4ec..e9eaf8b 100644
--- a/mojo/examples/wget/BUILD.gn
+++ b/mojo/examples/wget/BUILD.gn
@@ -2,7 +2,6 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-# GYP version: mojo/mojo_examples.gypi:mojo_wget
 shared_library("wget") {
   output_name = "mojo_wget"
 
diff --git a/mojo/examples/wget/wget.cc b/mojo/examples/wget/wget.cc
index 1efaa2d..5b9e5ca 100644
--- a/mojo/examples/wget/wget.cc
+++ b/mojo/examples/wget/wget.cc
@@ -71,7 +71,7 @@
 class WGetApp : public ApplicationDelegate {
  public:
   virtual void Initialize(ApplicationImpl* app) override {
-    app->ConnectToService("mojo:mojo_network_service", &network_service_);
+    app->ConnectToService("mojo:network_service", &network_service_);
     Start(app->args());
   }
 
diff --git a/mojo/examples/window_manager/BUILD.gn b/mojo/examples/window_manager/BUILD.gn
index 72bdd9d..3f463e5 100644
--- a/mojo/examples/window_manager/BUILD.gn
+++ b/mojo/examples/window_manager/BUILD.gn
@@ -7,7 +7,6 @@
 
 assert(use_aura)
 
-# GYP version: mojo/mojo_examples.gypi:mojo_window_manager
 shared_library("window_manager") {
   output_name = "mojo_window_manager"
 
@@ -46,7 +45,6 @@
   ]
 }
 
-# GYP version: mojo/mojo_examples.gypi:mojo_window_manager_bindings
 mojom("bindings") {
   sources = [
     "window_manager.mojom",
diff --git a/mojo/examples/window_manager/debug_panel.cc b/mojo/examples/window_manager/debug_panel.cc
index 7551fb4..4a75134 100644
--- a/mojo/examples/window_manager/debug_panel.cc
+++ b/mojo/examples/window_manager/debug_panel.cc
@@ -120,7 +120,7 @@
 
 void DebugPanel::ButtonPressed(views::Button* sender, const ui::Event& event) {
   if (sender == colored_square_) {
-    Navigate("mojo://mojo_embedded_app/");
+    Navigate("mojo://embedded_app/");
   } else if (sender == close_last_) {
     delegate_->CloseTopWindow();
   } else if (sender == cross_app_) {
diff --git a/mojo/examples/window_manager/window_manager.cc b/mojo/examples/window_manager/window_manager.cc
index 057ba67..e2bb237 100644
--- a/mojo/examples/window_manager/window_manager.cc
+++ b/mojo/examples/window_manager/window_manager.cc
@@ -160,8 +160,8 @@
     view_ = View::Create(view_manager);
     view_->SetBounds(bounds);
     parent->AddChild(view_);
-    view_->Embed("mojo:mojo_keyboard");
-    application->ConnectToService("mojo:mojo_keyboard", &keyboard_service_);
+    view_->Embed("mojo:keyboard");
+    application->ConnectToService("mojo:keyboard", &keyboard_service_);
     keyboard_service_.set_client(this);
     parent->AddObserver(this);
   }
@@ -490,7 +490,7 @@
     bounds.Inset(kBorderInset, kBorderInset);
     bounds.set_height(kTextfieldHeight);
     launcher_ui_ = CreateWindow(bounds);
-    launcher_ui_->Embed("mojo:mojo_browser");
+    launcher_ui_->Embed("mojo:browser");
     return launcher_ui_->view()->id();
   }
 
diff --git a/mojo/examples/wm_flow/BUILD.gn b/mojo/examples/wm_flow/BUILD.gn
index 9a4c498..5f70abf 100644
--- a/mojo/examples/wm_flow/BUILD.gn
+++ b/mojo/examples/wm_flow/BUILD.gn
@@ -16,7 +16,6 @@
   ]
 }
 
-# GYP version: mojo/mojo_examples.gypi:mojo_wm_flow_wm
 shared_library("wm") {
   output_name = "mojo_wm_flow_wm"
 
@@ -41,7 +40,6 @@
   ]
 }
 
-# GYP version: mojo/mojo_examples.gypi:mojo_wm_flow_init
 shared_library("init") {
   output_name = "mojo_wm_flow_init"
 
@@ -61,7 +59,6 @@
   ]
 }
 
-# GYP version: mojo/mojo_examples.gypi:mojo_wm_flow_app
 shared_library("app") {
   output_name = "mojo_wm_flow_app"
 
@@ -82,7 +79,6 @@
   ]
 }
 
-# GYP version: mojo/mojo_examples.gypi:mojo_wm_flow_embedded
 shared_library("embedded") {
   output_name = "mojo_wm_flow_embedded"
 
@@ -102,14 +98,12 @@
   ]
 }
 
-# GYP version: mojo/mojo_examples.gypi:mojo_wm_flow_embedder_bindings
 mojom("embedder_bindings") {
   sources = [
     "app/embedder.mojom",
   ]
 }
 
-# GYP version: mojo/mojo_examples.gypi:mojo_wm_flow_embeddee_bindings
 mojom("embeddee_bindings") {
   sources = [
     "embedded/embeddee.mojom",
diff --git a/mojo/examples/wm_flow/app/app.cc b/mojo/examples/wm_flow/app/app.cc
index 658433c..d9a8da2 100644
--- a/mojo/examples/wm_flow/app/app.cc
+++ b/mojo/examples/wm_flow/app/app.cc
@@ -102,7 +102,7 @@
     // Expose some services to the embeddee...
     registry->AddService(&embedder_factory_);
     scoped_ptr<mojo::ServiceProvider> imported =
-        embed->Embed("mojo:mojo_wm_flow_embedded", registry.Pass());
+        embed->Embed("mojo:wm_flow_embedded", registry.Pass());
     mojo::ConnectToService(imported.get(), &embeddee_);
     embeddee_->HelloBack(base::Bind(&WMFlowApp::HelloBackAck,
                                     base::Unretained(this)));
@@ -133,9 +133,7 @@
     printf("HelloBack() ack'ed\n");
   }
 
-  void OpenNewWindow() {
-    view_manager_context_->Embed("mojo:mojo_wm_flow_app");
-  }
+  void OpenNewWindow() { view_manager_context_->Embed("mojo:wm_flow_app"); }
 
   mojo::Shell* shell_;
   int embed_count_;
diff --git a/mojo/examples/wm_flow/init/init.cc b/mojo/examples/wm_flow/init/init.cc
index daef4ea..5738edd 100644
--- a/mojo/examples/wm_flow/init/init.cc
+++ b/mojo/examples/wm_flow/init/init.cc
@@ -23,8 +23,8 @@
   // Overridden from Application:
   virtual void Initialize(mojo::ApplicationImpl* app) override {
     context_.reset(new mojo::ViewManagerContext(app));
-    context_->Embed("mojo:mojo_wm_flow_wm");
-    app->ConnectToApplication("mojo:mojo_wm_flow_app");
+    context_->Embed("mojo:wm_flow_wm");
+    app->ConnectToApplication("mojo:wm_flow_app");
   }
 
   scoped_ptr<mojo::ViewManagerContext> context_;
diff --git a/mojo/mojo.gyp b/mojo/mojo.gyp
index e3c769f..6fdddf2 100644
--- a/mojo/mojo.gyp
+++ b/mojo/mojo.gyp
@@ -150,16 +150,18 @@
         'shell/dynamic_application_loader.cc',
         'shell/dynamic_application_loader.h',
         'shell/dynamic_service_runner.h',
+        'shell/external_application_listener.h',
         'shell/external_application_listener_posix.cc',
         'shell/external_application_listener_win.cc',
-        'shell/external_application_listener.h',
         'shell/external_application_registrar.mojom',
+        'shell/filename_util.cc',
+        'shell/filename_util.h',
+        'shell/in_process_dynamic_service_runner.cc',
+        'shell/in_process_dynamic_service_runner.h',
         'shell/incoming_connection_listener_posix.cc',
         'shell/incoming_connection_listener_posix.h',
         'shell/init.cc',
         'shell/init.h',
-        'shell/in_process_dynamic_service_runner.cc',
-        'shell/in_process_dynamic_service_runner.h',
         'shell/mojo_url_resolver.cc',
         'shell/mojo_url_resolver.h',
         'shell/out_of_process_dynamic_service_runner.cc',
diff --git a/mojo/services/clipboard/clipboard_standalone_unittest.cc b/mojo/services/clipboard/clipboard_standalone_unittest.cc
index cdf0087..d0418a9 100644
--- a/mojo/services/clipboard/clipboard_standalone_unittest.cc
+++ b/mojo/services/clipboard/clipboard_standalone_unittest.cc
@@ -52,8 +52,8 @@
   virtual void SetUp() override {
     test_helper_.Init();
 
-    test_helper_.application_manager()->ConnectToService(
-        GURL("mojo:mojo_clipboard"), &clipboard_);
+    test_helper_.application_manager()->ConnectToService(GURL("mojo:clipboard"),
+                                                         &clipboard_);
   }
 
   uint64_t GetSequenceNumber() {
diff --git a/mojo/services/html_viewer/blink_platform_impl.cc b/mojo/services/html_viewer/blink_platform_impl.cc
index 697699a..1981eb2 100644
--- a/mojo/services/html_viewer/blink_platform_impl.cc
+++ b/mojo/services/html_viewer/blink_platform_impl.cc
@@ -56,14 +56,14 @@
       shared_timer_fire_time_was_set_while_suspended_(false),
       shared_timer_suspended_(0),
       current_thread_slot_(&DestroyCurrentThread) {
-  app->ConnectToService("mojo:mojo_network_service", &network_service_);
+  app->ConnectToService("mojo:network_service", &network_service_);
 
   CookieStorePtr cookie_store;
   network_service_->GetCookieStore(GetProxy(&cookie_store));
   cookie_jar_.reset(new WebCookieJarImpl(cookie_store.Pass()));
 
   ClipboardPtr clipboard;
-  app->ConnectToService("mojo:mojo_clipboard", &clipboard);
+  app->ConnectToService("mojo:clipboard", &clipboard);
   clipboard_.reset(new WebClipboardImpl(clipboard.Pass()));
 }
 
diff --git a/mojo/services/html_viewer/html_document_view.cc b/mojo/services/html_viewer/html_document_view.cc
index 400d8ca..0ceb101 100644
--- a/mojo/services/html_viewer/html_document_view.cc
+++ b/mojo/services/html_viewer/html_document_view.cc
@@ -154,14 +154,14 @@
 
 void HTMLDocumentView::initializeLayerTreeView() {
   ServiceProviderPtr surfaces_service_provider;
-  shell_->ConnectToApplication("mojo:mojo_surfaces_service",
+  shell_->ConnectToApplication("mojo:surfaces_service",
                                GetProxy(&surfaces_service_provider));
   SurfacesServicePtr surfaces_service;
   ConnectToService(surfaces_service_provider.get(), &surfaces_service);
 
   ServiceProviderPtr gpu_service_provider;
-  // TODO(jamesr): Should be mojo:mojo_gpu_service
-  shell_->ConnectToApplication("mojo:mojo_native_viewport_service",
+  // TODO(jamesr): Should be mojo:gpu_service
+  shell_->ConnectToApplication("mojo:native_viewport_service",
                                GetProxy(&gpu_service_provider));
   GpuPtr gpu_service;
   ConnectToService(gpu_service_provider.get(), &gpu_service);
diff --git a/mojo/services/native_viewport/native_viewport_impl.cc b/mojo/services/native_viewport/native_viewport_impl.cc
index 5e749ee..810d339 100644
--- a/mojo/services/native_viewport/native_viewport_impl.cc
+++ b/mojo/services/native_viewport/native_viewport_impl.cc
@@ -35,9 +35,9 @@
       widget_id_(0u),
       waiting_for_event_ack_(false),
       weak_factory_(this) {
-  app->ConnectToService("mojo:mojo_surfaces_service", &surfaces_service_);
+  app->ConnectToService("mojo:surfaces_service", &surfaces_service_);
   // TODO(jamesr): Should be mojo_gpu_service
-  app->ConnectToService("mojo:mojo_native_viewport_service", &gpu_service_);
+  app->ConnectToService("mojo:native_viewport_service", &gpu_service_);
 }
 
 NativeViewportImpl::~NativeViewportImpl() {
diff --git a/mojo/services/network/udp_socket_unittest.cc b/mojo/services/network/udp_socket_unittest.cc
index 46c443a..dd38cf1 100644
--- a/mojo/services/network/udp_socket_unittest.cc
+++ b/mojo/services/network/udp_socket_unittest.cc
@@ -212,7 +212,7 @@
     test_helper_.Init();
 
     test_helper_.application_manager()->ConnectToService(
-        GURL("mojo:mojo_network_service"), &network_service_);
+        GURL("mojo:network_service"), &network_service_);
 
     network_service_->CreateUDPSocket(GetProxy(&udp_socket_));
     udp_socket_.set_client(&udp_socket_client_);
diff --git a/mojo/services/public/cpp/view_manager/lib/view_manager_client_impl.cc b/mojo/services/public/cpp/view_manager/lib/view_manager_client_impl.cc
index ac54417..330e07c 100644
--- a/mojo/services/public/cpp/view_manager/lib/view_manager_client_impl.cc
+++ b/mojo/services/public/cpp/view_manager/lib/view_manager_client_impl.cc
@@ -93,7 +93,7 @@
                                              Shell* shell)
     : connected_(false), connection_id_(0), next_id_(1), delegate_(delegate) {
   InterfacePtr<ServiceProvider> sp;
-  shell->ConnectToApplication("mojo:mojo_window_manager", GetProxy(&sp));
+  shell->ConnectToApplication("mojo:window_manager", GetProxy(&sp));
   ConnectToService(sp.get(), &window_manager_);
   window_manager_.set_client(this);
 }
diff --git a/mojo/services/public/cpp/view_manager/lib/view_manager_context.cc b/mojo/services/public/cpp/view_manager/lib/view_manager_context.cc
index 284286e..5d00f3b 100644
--- a/mojo/services/public/cpp/view_manager/lib/view_manager_context.cc
+++ b/mojo/services/public/cpp/view_manager/lib/view_manager_context.cc
@@ -15,8 +15,7 @@
 class ViewManagerContext::InternalState {
  public:
   InternalState(ApplicationImpl* application_impl) {
-    application_impl->ConnectToService("mojo:mojo_view_manager",
-                                       &init_service_);
+    application_impl->ConnectToService("mojo:view_manager", &init_service_);
   }
   ~InternalState() {}
 
diff --git a/mojo/services/public/cpp/view_manager/tests/view_manager_unittest.cc b/mojo/services/public/cpp/view_manager/tests/view_manager_unittest.cc
index 7358fe8..d9609e2 100644
--- a/mojo/services/public/cpp/view_manager/tests/view_manager_unittest.cc
+++ b/mojo/services/public/cpp/view_manager/tests/view_manager_unittest.cc
@@ -316,7 +316,7 @@
         GURL(kEmbeddedApp1URL));
 
     test_helper_.application_manager()->ConnectToService(
-        GURL("mojo:mojo_view_manager"), &view_manager_init_);
+        GURL("mojo:view_manager"), &view_manager_init_);
     ASSERT_TRUE(EmbedRoot(view_manager_init_.get(), kWindowManagerURL));
   }
 
diff --git a/mojo/services/test_service/test_service_impl.cc b/mojo/services/test_service/test_service_impl.cc
index 9e589a5..073ccce 100644
--- a/mojo/services/test_service/test_service_impl.cc
+++ b/mojo/services/test_service/test_service_impl.cc
@@ -57,8 +57,7 @@
 void TestServiceImpl::StartTrackingRequests(
     const mojo::Callback<void()>& callback) {
   TestRequestTrackerPtr tracker;
-  connection_->ConnectToService(
-      "mojo:mojo_test_request_tracker_app", &tracker);
+  connection_->ConnectToService("mojo:test_request_tracker_app", &tracker);
   tracking_.reset(
       new TestRequestTrackerClientImpl(tracker.Pass(), Name_, callback));
 }
diff --git a/mojo/services/test_service/test_time_service_impl.cc b/mojo/services/test_service/test_time_service_impl.cc
index f4adbaa..7201620 100644
--- a/mojo/services/test_service/test_time_service_impl.cc
+++ b/mojo/services/test_service/test_time_service_impl.cc
@@ -21,8 +21,7 @@
 void TestTimeServiceImpl::StartTrackingRequests(
     const mojo::Callback<void()>& callback) {
   TestRequestTrackerPtr tracker;
-  application_->ConnectToService(
-      "mojo:mojo_test_request_tracker_app", &tracker);
+  application_->ConnectToService("mojo:test_request_tracker_app", &tracker);
   tracking_.reset(new TestRequestTrackerClientImpl(
       tracker.Pass(), Name_, callback));
 }
diff --git a/mojo/services/view_manager/display_manager.cc b/mojo/services/view_manager/display_manager.cc
index 06162d1..5488177 100644
--- a/mojo/services/view_manager/display_manager.cc
+++ b/mojo/services/view_manager/display_manager.cc
@@ -77,7 +77,7 @@
       size_(800, 600),
       draw_timer_(false, false),
       weak_factory_(this) {
-  app_connection->ConnectToService("mojo:mojo_native_viewport_service",
+  app_connection->ConnectToService("mojo:native_viewport_service",
                                    &native_viewport_);
   native_viewport_.set_client(this);
   native_viewport_->Create(
@@ -85,8 +85,7 @@
       base::Bind(&DisplayManager::OnCreatedNativeViewport,
                  weak_factory_.GetWeakPtr()));
   native_viewport_->Show();
-  app_connection->ConnectToService("mojo:mojo_surfaces_service",
-                                   &surfaces_service_);
+  app_connection->ConnectToService("mojo:surfaces_service", &surfaces_service_);
   surfaces_service_->CreateSurfaceConnection(base::Bind(
       &DisplayManager::OnSurfaceConnectionCreated, weak_factory_.GetWeakPtr()));
 }
diff --git a/mojo/services/view_manager/view_manager_unittest.cc b/mojo/services/view_manager/view_manager_unittest.cc
index c121659..abf874e 100644
--- a/mojo/services/view_manager/view_manager_unittest.cc
+++ b/mojo/services/view_manager/view_manager_unittest.cc
@@ -509,7 +509,7 @@
     std::vector<std::string> native_viewport_args;
     native_viewport_args.push_back(kUseTestConfig);
     test_helper_.application_manager()->SetArgsForURL(
-        native_viewport_args, GURL("mojo:mojo_native_viewport_service"));
+        native_viewport_args, GURL("mojo:native_viewport_service"));
     printf("Setting args\n");
 
 #if defined(OS_WIN)
@@ -527,7 +527,7 @@
         GURL(kTestServiceURL2));
 
     test_helper_.application_manager()->ConnectToService(
-        GURL("mojo:mojo_view_manager"), &view_manager_init_);
+        GURL("mojo:view_manager"), &view_manager_init_);
     ASSERT_TRUE(InitEmbed(view_manager_init_.get(), kTestServiceURL, 1));
 
     connection_ = ViewManagerProxy::WaitForInstance();
diff --git a/mojo/services/window_manager/window_manager_api_unittest.cc b/mojo/services/window_manager/window_manager_api_unittest.cc
index 690845e..7f89283 100644
--- a/mojo/services/window_manager/window_manager_api_unittest.cc
+++ b/mojo/services/window_manager/window_manager_api_unittest.cc
@@ -203,16 +203,16 @@
             &WindowManagerApiTest::OnRootAdded, base::Unretained(this)))),
         GURL(kTestServiceURL));
     test_helper_.application_manager()->ConnectToService(
-        GURL("mojo:mojo_view_manager"), &view_manager_init_);
-    ASSERT_TRUE(InitEmbed(view_manager_init_.get(),
-                          "mojo:mojo_core_window_manager"));
+        GURL("mojo:view_manager"), &view_manager_init_);
+    ASSERT_TRUE(
+        InitEmbed(view_manager_init_.get(), "mojo:core_window_manager"));
     ConnectToWindowManager();
   }
   virtual void TearDown() override {}
 
   void ConnectToWindowManager() {
     test_helper_.application_manager()->ConnectToService(
-        GURL("mojo:mojo_core_window_manager"), &window_manager_);
+        GURL("mojo:core_window_manager"), &window_manager_);
     base::RunLoop connect_loop;
     window_manager_client_.reset(new TestWindowManagerClient(&connect_loop));
     window_manager_.set_client(window_manager_client());
diff --git a/mojo/shell/BUILD.gn b/mojo/shell/BUILD.gn
index c435a75..ff5f349 100644
--- a/mojo/shell/BUILD.gn
+++ b/mojo/shell/BUILD.gn
@@ -55,15 +55,17 @@
     "dynamic_application_loader.cc",
     "dynamic_application_loader.h",
     "dynamic_service_runner.h",
+    "external_application_listener.h",
     "external_application_listener_posix.cc",
     "external_application_listener_win.cc",
-    "external_application_listener.h",
+    "filename_util.cc",
+    "filename_util.h",
+    "in_process_dynamic_service_runner.cc",
+    "in_process_dynamic_service_runner.h",
     "incoming_connection_listener_posix.cc",
     "incoming_connection_listener_posix.h",
     "init.cc",
     "init.h",
-    "in_process_dynamic_service_runner.cc",
-    "in_process_dynamic_service_runner.h",
     "mojo_url_resolver.cc",
     "mojo_url_resolver.h",
     "out_of_process_dynamic_service_runner.cc",
diff --git a/mojo/shell/context.cc b/mojo/shell/context.cc
index 5d1e135..b268ffb 100644
--- a/mojo/shell/context.cc
+++ b/mojo/shell/context.cc
@@ -46,7 +46,7 @@
 // These mojo: URLs are loaded directly from the local filesystem. They
 // correspond to shared libraries bundled alongside the mojo_shell.
 const char* kLocalMojoURLs[] = {
-  "mojo:mojo_network_service",
+    "mojo:network_service",
 };
 
 // Used to ensure we only init once.
@@ -69,8 +69,8 @@
 void InitContentHandlers(DynamicApplicationLoader* loader,
                          base::CommandLine* command_line) {
   // Default content handlers.
-  loader->RegisterContentHandler("image/png", GURL("mojo://mojo_png_viewer/"));
-  loader->RegisterContentHandler("text/html", GURL("mojo://mojo_html_viewer/"));
+  loader->RegisterContentHandler("image/png", GURL("mojo://png_viewer/"));
+  loader->RegisterContentHandler("text/html", GURL("mojo://html_viewer/"));
 
   // Command-line-specified content handlers.
   std::string handlers_spec = command_line->GetSwitchValueASCII(
@@ -212,7 +212,7 @@
       scoped_ptr<ApplicationLoader>(new UIApplicationLoader(
           scoped_ptr<ApplicationLoader>(new NativeViewportApplicationLoader()),
           this)),
-      GURL("mojo:mojo_native_viewport_service"));
+      GURL("mojo:native_viewport_service"));
 #endif
 
   if (command_line->HasSwitch(switches::kSpy)) {
@@ -234,7 +234,7 @@
             "network_service",
             base::MessageLoop::TYPE_IO));
     application_manager_.SetLoaderForURL(loader.Pass(),
-                                         GURL("mojo:mojo_network_service"));
+                                         GURL("mojo:network_service"));
   }
 #endif
 
diff --git a/mojo/shell/desktop/mojo_main.cc b/mojo/shell/desktop/mojo_main.cc
index 4738e3c..02be823 100644
--- a/mojo/shell/desktop/mojo_main.cc
+++ b/mojo/shell/desktop/mojo_main.cc
@@ -82,11 +82,11 @@
       << " <mojo-app> ...\n\n"
       << "A <mojo-app> is a Mojo URL or a Mojo URL and arguments within "
       << "quotes.\n"
-      << "Example: mojo_shell \"mojo://mojo_js_standalone test.js\".\n"
+      << "Example: mojo_shell \"mojo://js_standalone test.js\".\n"
       << "<url-lib-path> is searched for shared libraries named by mojo URLs.\n"
       << "The value of <handlers> is a comma separated list like:\n"
-      << "text/html,mojo://mojo_html_viewer,"
-      << "application/javascript,mojo://mojo_js_content_handler\n";
+      << "text/html,mojo://html_viewer,"
+      << "application/javascript,mojo://js_content_handler\n";
 }
 
 bool ConfigureURLMappings(const std::string& mappings,
diff --git a/mojo/shell/dynamic_application_loader.cc b/mojo/shell/dynamic_application_loader.cc
index 1f24cf3..eae422d 100644
--- a/mojo/shell/dynamic_application_loader.cc
+++ b/mojo/shell/dynamic_application_loader.cc
@@ -11,12 +11,14 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/weak_ptr.h"
 #include "base/message_loop/message_loop.h"
+#include "base/strings/utf_string_conversions.h"
 #include "mojo/common/common_type_converters.h"
 #include "mojo/common/data_pipe_utils.h"
 #include "mojo/services/public/interfaces/network/url_loader.mojom.h"
 #include "mojo/shell/context.h"
+#include "mojo/shell/filename_util.h"
 #include "mojo/shell/switches.h"
-#include "net/base/filename_util.h"
+#include "url/url_util.h"
 
 namespace mojo {
 namespace shell {
@@ -92,8 +94,17 @@
                load_callbacks,
                loader_complete_callback),
         weak_ptr_factory_(this) {
-    base::FilePath path;
-    net::FileURLToFilePath(url, &path);
+    DCHECK(url.SchemeIsFile());
+    url::RawCanonOutputW<1024> output;
+    url::DecodeURLEscapeSequences(
+        url.path().data(), static_cast<int>(url.path().length()), &output);
+    base::string16 decoded_path =
+        base::string16(output.data(), output.length());
+#if defined(OS_WIN)
+    base::FilePath path(decoded_path);
+#else
+    base::FilePath path(base::UTF16ToUTF8(decoded_path));
+#endif
 
     // Async for consistency with network case.
     base::MessageLoop::current()->PostTask(
@@ -222,7 +233,7 @@
 
   if (!network_service_) {
     context_->application_manager()->ConnectToService(
-        GURL("mojo:mojo_network_service"), &network_service_);
+        GURL("mojo:network_service"), &network_service_);
   }
 
   loaders_.push_back(new NetworkLoader(resolved_url,
diff --git a/mojo/shell/dynamic_application_loader_unittest.cc b/mojo/shell/dynamic_application_loader_unittest.cc
index ea6fb1d..eb2a6ee 100644
--- a/mojo/shell/dynamic_application_loader_unittest.cc
+++ b/mojo/shell/dynamic_application_loader_unittest.cc
@@ -6,7 +6,7 @@
 #include "mojo/shell/context.h"
 #include "mojo/shell/dynamic_application_loader.h"
 #include "mojo/shell/dynamic_service_runner.h"
-#include "net/base/filename_util.h"
+#include "mojo/shell/filename_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace mojo {
@@ -81,7 +81,7 @@
   base::ScopedTempDir temp_dir;
   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
   base::FilePath nonexistent_file(FILE_PATH_LITERAL("nonexistent.txt"));
-  GURL url(net::FilePathToFileURL(temp_dir.path().Append(nonexistent_file)));
+  GURL url(FilePathToFileURL(temp_dir.path().Append(nonexistent_file)));
   MessagePipe pipe;
   scoped_refptr<ApplicationLoader::SimpleLoadCallbacks> callbacks(
       new ApplicationLoader::SimpleLoadCallbacks(pipe.handle0.Pass()));
diff --git a/mojo/shell/filename_util.cc b/mojo/shell/filename_util.cc
new file mode 100644
index 0000000..71c511e
--- /dev/null
+++ b/mojo/shell/filename_util.cc
@@ -0,0 +1,60 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "mojo/shell/filename_util.h"
+
+#include "base/files/file_path.h"
+#include "base/path_service.h"
+#include "base/strings/string_util.h"
+#include "url/gurl.h"
+#include "url/url_canon_internal.h"
+#include "url/url_util.h"
+
+namespace mojo {
+
+// Prefix to prepend to get a file URL.
+static const base::FilePath::CharType kFileURLPrefix[] =
+    FILE_PATH_LITERAL("file://");
+
+GURL FilePathToFileURL(const base::FilePath& path) {
+  // Produce a URL like "file:///C:/foo" for a regular file, or
+  // "file://///server/path" for UNC. The URL canonicalizer will fix up the
+  // latter case to be the canonical UNC form: "file://server/path"
+  base::FilePath::StringType url_string(kFileURLPrefix);
+  if (!path.IsAbsolute()) {
+    base::FilePath current_dir;
+    PathService::Get(base::DIR_CURRENT, &current_dir);
+    url_string.append(current_dir.value());
+    url_string.push_back(base::FilePath::kSeparators[0]);
+  }
+  url_string.append(path.value());
+
+  // Now do replacement of some characters. Since we assume the input is a
+  // literal filename, anything the URL parser might consider special should
+  // be escaped here.
+
+  // This must be the first substitution since others will introduce percents as
+  // the escape character
+  ReplaceSubstringsAfterOffset(
+      &url_string, 0, FILE_PATH_LITERAL("%"), FILE_PATH_LITERAL("%25"));
+
+  // A semicolon is supposed to be some kind of separator according to RFC 2396.
+  ReplaceSubstringsAfterOffset(
+      &url_string, 0, FILE_PATH_LITERAL(";"), FILE_PATH_LITERAL("%3B"));
+
+  ReplaceSubstringsAfterOffset(
+      &url_string, 0, FILE_PATH_LITERAL("#"), FILE_PATH_LITERAL("%23"));
+
+  ReplaceSubstringsAfterOffset(
+      &url_string, 0, FILE_PATH_LITERAL("?"), FILE_PATH_LITERAL("%3F"));
+
+#if defined(OS_POSIX)
+  ReplaceSubstringsAfterOffset(
+      &url_string, 0, FILE_PATH_LITERAL("\\"), FILE_PATH_LITERAL("%5C"));
+#endif
+
+  return GURL(url_string);
+}
+
+}  // namespace mojo
diff --git a/mojo/shell/filename_util.h b/mojo/shell/filename_util.h
new file mode 100644
index 0000000..0fd8b8f
--- /dev/null
+++ b/mojo/shell/filename_util.h
@@ -0,0 +1,22 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_SHELL_FILENAME_UTIL_H_
+#define MOJO_SHELL_FILENAME_UTIL_H_
+
+class GURL;
+
+namespace base {
+class FilePath;
+}
+
+namespace mojo {
+
+// Given the full path to a file name, creates a file: URL. The returned URL
+// may not be valid if the input is malformed.
+GURL FilePathToFileURL(const base::FilePath& path);
+
+}  // namespace mojo
+
+#endif  // MOJO_SHELL_FILENAME_UTIL_H_
diff --git a/mojo/shell/mojo_url_resolver.cc b/mojo/shell/mojo_url_resolver.cc
index 75c625c..8d37237 100644
--- a/mojo/shell/mojo_url_resolver.cc
+++ b/mojo/shell/mojo_url_resolver.cc
@@ -8,14 +8,22 @@
 #include "base/files/file_path.h"
 #include "base/logging.h"
 #include "base/path_service.h"
-#include "net/base/filename_util.h"
+#include "base/strings/string_util.h"
+#include "mojo/shell/filename_util.h"
 #include "url/url_util.h"
 
 namespace mojo {
 namespace shell {
 namespace {
 
-std::string MakeSharedLibraryName(const std::string& host_name) {
+std::string MakeSharedLibraryName(std::string host_name) {
+  // TODO(aa): This should go away soon. In the Chromium repo, all the app
+  // target names start with "mojo_" by convention. But when we have an SDK,
+  // one would assume the libraries would have names that don't have this bit.
+  std::string prefix = "mojo_";
+  if (!StartsWithASCII(host_name, prefix, true))
+    host_name = prefix + host_name;
+
 #if defined(OS_WIN)
   return host_name + ".dll";
 #elif defined(OS_LINUX) || defined(OS_ANDROID)
@@ -47,7 +55,7 @@
   // By default, resolve mojo URLs to files living alongside the shell.
   base::FilePath path;
   PathService::Get(base::DIR_MODULE, &path);
-  default_base_url_ = AddTrailingSlashIfNeeded(net::FilePathToFileURL(path));
+  default_base_url_ = AddTrailingSlashIfNeeded(FilePathToFileURL(path));
 }
 
 MojoURLResolver::~MojoURLResolver() {
diff --git a/mojo/shell/mojo_url_resolver_unittest.cc b/mojo/shell/mojo_url_resolver_unittest.cc
index e4deffa..363071b 100644
--- a/mojo/shell/mojo_url_resolver_unittest.cc
+++ b/mojo/shell/mojo_url_resolver_unittest.cc
@@ -19,11 +19,16 @@
   resolver.AddCustomMapping(GURL("mojo:test"), GURL("mojo:foo"));
   const GURL base_url("file:/base");
   resolver.SetBaseURL(base_url);
-  const std::string resolved(resolver.Resolve(GURL("mojo:test")).spec());
+  std::string resolved(resolver.Resolve(GURL("mojo:test")).spec());
   // Resolved must start with |base_url|.
   EXPECT_EQ(base_url.spec(), resolved.substr(0, base_url.spec().size()));
-  // And must contain foo (which is what test mapped to.
-  EXPECT_NE(std::string::npos, resolved.find("foo"));
+  // And must contain mojo_foo (we got mapped to foo, and all libraries are
+  // prefixed with mojo_).
+  EXPECT_NE(std::string::npos, resolved.find("mojo_foo"));
+
+  // Make sure we don't double-mojo.
+  resolved = resolver.Resolve(GURL("mojo:mojo_test")).spec();
+  EXPECT_EQ(std::string::npos, resolved.find("mojo:mojo_mojo_foo"));
 }
 
 }  // namespace
diff --git a/mojo/shell/shell_test_base.cc b/mojo/shell/shell_test_base.cc
index 296db5e..b9bb7e0 100644
--- a/mojo/shell/shell_test_base.cc
+++ b/mojo/shell/shell_test_base.cc
@@ -10,8 +10,7 @@
 #include "base/logging.h"
 #include "base/path_service.h"
 #include "build/build_config.h"
-#include "net/base/filename_util.h"
-#include "net/test/embedded_test_server/embedded_test_server.h"
+#include "mojo/shell/filename_util.h"
 #include "url/gurl.h"
 
 namespace mojo {
@@ -26,11 +25,8 @@
 
 void ShellTestBase::SetUp() {
   shell_context_.Init();
-  test_server_.reset(new net::test_server::EmbeddedTestServer());
-  ASSERT_TRUE(test_server_->InitializeAndWaitUntilReady());
   base::FilePath service_dir;
   CHECK(PathService::Get(base::DIR_MODULE, &service_dir));
-  test_server_->ServeFilesFromDirectory(service_dir);
 }
 
 ScopedMessagePipeHandle ShellTestBase::ConnectToService(
@@ -43,7 +39,7 @@
   base::FilePath service_dir;
   CHECK(PathService::Get(base::DIR_MODULE, &service_dir));
   shell_context_.mojo_url_resolver()->SetBaseURL(
-      net::FilePathToFileURL(service_dir));
+      FilePathToFileURL(service_dir));
 
   return shell_context_.ConnectToServiceByName(
       application_url, service_name).Pass();
@@ -52,9 +48,6 @@
 ScopedMessagePipeHandle ShellTestBase::ConnectToServiceViaNetwork(
     const GURL& application_url,
     const std::string& service_name) {
-  shell_context_.mojo_url_resolver()->SetBaseURL(
-      test_server_->base_url());
-
   return shell_context_.ConnectToServiceByName(
       application_url, service_name).Pass();
 }
diff --git a/mojo/shell/shell_test_base.h b/mojo/shell/shell_test_base.h
index 4017315..ff5b3e7 100644
--- a/mojo/shell/shell_test_base.h
+++ b/mojo/shell/shell_test_base.h
@@ -15,12 +15,6 @@
 
 class GURL;
 
-namespace net {
-namespace test_server {
-class EmbeddedTestServer;
-}
-}  // namespace net
-
 namespace mojo {
 namespace shell {
 namespace test {
@@ -60,7 +54,6 @@
   Context* shell_context() { return &shell_context_; }
 
  private:
-  scoped_ptr<net::test_server::EmbeddedTestServer> test_server_;
   Context shell_context_;
   base::MessageLoop message_loop_;
 
diff --git a/mojo/shell/shell_test_base_unittest.cc b/mojo/shell/shell_test_base_unittest.cc
index 8a0bdd4..9b1a6c1 100644
--- a/mojo/shell/shell_test_base_unittest.cc
+++ b/mojo/shell/shell_test_base_unittest.cc
@@ -52,13 +52,10 @@
       return base::Bind(&ShellTestBaseTest::SetAndQuitImpl<T>,
           base::Unretained(this), val);
   }
-  static GURL test_app_url() {
-    return GURL("mojo:mojo_test_app");
-  }
+  static GURL test_app_url() { return GURL("mojo:test_app"); }
 
   void GetReport(std::vector<ServiceReport>* report) {
-    ConnectToService(GURL("mojo:mojo_test_request_tracker_app"),
-                     &request_tracking_);
+    ConnectToService(GURL("mojo:test_request_tracker_app"), &request_tracking_);
     request_tracking_->GetReport(base::Bind(&GetReportCallback,
         base::Unretained(message_loop()),
         base::Unretained(report)));
@@ -227,13 +224,13 @@
   int64 time_message;
   TestServicePtr service;
   ConnectToService(test_app_url(), &service);
-  service->ConnectToAppAndGetTime("mojo:mojo_test_request_tracker_app",
+  service->ConnectToAppAndGetTime("mojo:test_request_tracker_app",
                                   SetAndQuit<int64>(&time_message));
   message_loop()->Run();
 
   // Verify by hitting the TimeService in the request tracker app directly.
   TestTimeServicePtr time_service;
-  ConnectToService(GURL("mojo:mojo_test_request_tracker_app"), &time_service);
+  ConnectToService(GURL("mojo:test_request_tracker_app"), &time_service);
   int64 party_time;
   time_service->GetPartyTime(SetAndQuit<int64>(&party_time));
   message_loop()->Run();
@@ -278,7 +275,7 @@
   for (int i = 0; i < 5; i++)
     service->Ping(mojo::Callback<void()>());
   int64 time_result;
-  service->ConnectToAppAndGetTime("mojo:mojo_test_request_tracker_app",
+  service->ConnectToAppAndGetTime("mojo:test_request_tracker_app",
                                   SetAndQuit<int64>(&time_result));
   message_loop()->Run();
 
diff --git a/mojo/shell/shell_test_helper.cc b/mojo/shell/shell_test_helper.cc
index d0f0f7a..6c3490e 100644
--- a/mojo/shell/shell_test_helper.cc
+++ b/mojo/shell/shell_test_helper.cc
@@ -9,8 +9,8 @@
 #include "base/files/file_util.h"
 #include "base/logging.h"
 #include "base/path_service.h"
+#include "mojo/shell/filename_util.h"
 #include "mojo/shell/init.h"
-#include "net/base/filename_util.h"
 
 namespace mojo {
 namespace shell {
@@ -29,8 +29,7 @@
       new ApplicationManager::TestAPI(context_.application_manager()));
   base::FilePath service_dir;
   CHECK(PathService::Get(base::DIR_MODULE, &service_dir));
-  context_.mojo_url_resolver()->SetBaseURL(
-      net::FilePathToFileURL(service_dir));
+  context_.mojo_url_resolver()->SetBaseURL(FilePathToFileURL(service_dir));
 }
 
 void ShellTestHelper::SetLoaderForURL(scoped_ptr<ApplicationLoader> loader,
diff --git a/mojo/shell/switches.cc b/mojo/shell/switches.cc
index ee3ee51..cd863a0 100644
--- a/mojo/shell/switches.cc
+++ b/mojo/shell/switches.cc
@@ -7,7 +7,7 @@
 namespace switches {
 
 // Specify configuration arguments for a Mojo application URL. For example:
-// --args-for='mojo://mojo_wget http://www.google.com'
+// --args-for='mojo://wget http://www.google.com'
 const char kArgsFor[] = "args-for";
 
 // Used to specify the type of child process (switch values from
@@ -15,7 +15,7 @@
 const char kChildProcessType[] = "child-process-type";
 
 // Comma separated list like:
-// text/html,mojo://mojo_html_viewer,application/bravo,https://abarth.com/bravo
+// text/html,mojo://html_viewer,application/bravo,https://abarth.com/bravo
 const char kContentHandlers[] = "content-handlers";
 
 // Force dynamically loaded apps / services to be loaded irrespective of cache
diff --git a/mojo/tools/data/unittests b/mojo/tools/data/unittests
index 0bafba4..ede2115 100644
--- a/mojo/tools/data/unittests
+++ b/mojo/tools/data/unittests
@@ -16,7 +16,8 @@
 mojo_application_manager_unittests
 mojo_common_unittests
 mojo_view_manager_lib_unittests
-mojo_view_manager_unittests
+# These tests currently crash. We should re-enable them when they pass.
+#mojo_view_manager_unittests
 mojo_surfaces_lib_unittests
 
 # JavaScript tests:
diff --git a/mojo/tools/mojob.sh b/mojo/tools/mojob.sh
index 2b82d08..7092c79 100755
--- a/mojo/tools/mojob.sh
+++ b/mojo/tools/mojob.sh
@@ -20,34 +20,37 @@
   test - Run unit tests (does not build).
   perftest - Run perf tests (does not build).
   pytest - Run Python unit tests (does not build).
-  gyp - Run gyp for mojo (does not sync).
-  gypall - Run gyp for all of chromium (does not sync).
-  sync - Sync using gclient (does not run gyp).
+  gn - Run gn for mojo (does not sync).
+  sync - Sync using gclient (does not run gn).
   show-bash-alias - Outputs an appropriate bash alias for mojob. In bash do:
       \$ eval \`mojo/tools/mojob.sh show-bash-alias\`
 
-option (which will only apply to following commands) should be one of:
-  Build/test options (specified before build/test/perftest):
-    --debug - Build/test in Debug mode.
-    --release - Build/test in Release mode.
-    --debug-and-release - Build/test in both Debug and Release modes (default).
-  Compiler options (specified before gyp):
-    --clang - Use clang (default).
-    --gcc - Use gcc.
-  Component options:
-    --shared Build components as shared libraries (default).
-    --static Build components as static libraries.
-  Use goma:
-    --use-goma - Use goma if \$GOMA_DIR is set or \$HOME/goma exists (default).
-    --no-use-goma - Do not use goma.
+option (which will only apply to commands which follow) should be one of:
+  General options (specify before everything):
+    --debug / --release / --debug-and-release - Debug (default) build /
+        Release build / Debug and Release builds.
+  gn options (specify before gn):
+    --clang / --gcc - Use clang (default) / gcc.
+    --use-goma / --no-use-goma - Use goma (if \$GOMA_DIR is set or \$HOME/goma
+        exists; default) / don't use goma.
 
 Note: It will abort on the first failure (if any).
 EOF
 }
 
+get_gn_arg_value() {
+  grep -m 1 "^[[:space:]]*\<$2\>" "$1/args.gn" | \
+      sed -n 's/.* = "\?\([^"]*\)"\?$/\1/p'
+}
+
 do_build() {
   echo "Building in out/$1 ..."
-  if [ "$GOMA" = "auto" -a -v GOMA_DIR ]; then
+  if [ "$(get_gn_arg_value "out/$1" use_goma)" = "true" ]; then
+    # Use the configured goma directory.
+    local goma_dir="$(get_gn_arg_value "out/$1" goma_dir)"
+    echo "Ensuring goma (in ${goma_dir}) started ..."
+    "${goma_dir}/goma_ctl.py" ensure_start
+
     ninja -j 1000 -l 100 -C "out/$1" mojo || exit 1
   else
     ninja -C "out/$1" mojo || exit 1
@@ -68,24 +71,14 @@
 do_pytests() {
   echo "Running python tests in out/$1 ..."
   python mojo/tools/run_mojo_python_tests.py || exit 1
-  # TODO(qsr) Remove this test when the component build is not supported
-  # anymore.
-  if [ -f "out/$1/python/mojo/system.so" ]; then
-    python mojo/tools/run_mojo_python_bindings_tests.py \
-        "--build-dir=out/$1" || exit 1
-  fi
+  python mojo/tools/run_mojo_python_bindings_tests.py "--build-dir=out/$1" || \
+      exit 1
 }
 
-do_gyp() {
-  local gyp_defines="$(make_gyp_defines)"
-  echo "Running gyp for mojo with GYP_DEFINES=$gyp_defines ..."
-  GYP_DEFINES="$gyp_defines" build/gyp_chromium mojo/mojo.gyp || exit 1
-}
-
-do_gypall() {
-  local gyp_defines="$(make_gyp_defines)"
-  echo "Running gyp for everything with GYP_DEFINES=$gyp_defines ..."
-  GYP_DEFINES="$gyp_defines" build/gyp_chromium || exit 1
+do_gn() {
+  local gn_args="$(make_gn_args $1)"
+  echo "Running gn with --args=\"${gn_args}\" ..."
+  gn gen --args="${gn_args}" "out/$1"
 }
 
 do_sync() {
@@ -94,67 +87,43 @@
 }
 
 # Valid values: Debug, Release, or Debug_and_Release.
-BUILD_TEST_TYPE=Debug_and_Release
+BUILD_TYPE=Debug_and_Release
 should_do_Debug() {
-  test "$BUILD_TEST_TYPE" = Debug -o "$BUILD_TEST_TYPE" = Debug_and_Release
+  test "$BUILD_TYPE" = Debug -o "$BUILD_TYPE" = Debug_and_Release
 }
 should_do_Release() {
-  test "$BUILD_TEST_TYPE" = Release -o "$BUILD_TEST_TYPE" = Debug_and_Release
+  test "$BUILD_TYPE" = Release -o "$BUILD_TYPE" = Debug_and_Release
 }
 
 # Valid values: clang or gcc.
 COMPILER=clang
-# Valid values: shared or static.
-COMPONENT=shared
 # Valid values: auto or disabled.
 GOMA=auto
-make_gyp_defines() {
-  local options=()
-  # Always include these options.
-  options+=("use_aura=1")
+make_gn_args() {
+  local args=()
   case "$COMPILER" in
     clang)
-      options+=("clang=1")
+      args+=("is_clang=true")
       ;;
     gcc)
-      options+=("clang=0")
-      ;;
-  esac
-  case "$COMPONENT" in
-    shared)
-      options+=("component=shared_library")
-      ;;
-    static)
-      options+=("component=static_library")
+      args+=("is_clang=false")
       ;;
   esac
   case "$GOMA" in
     auto)
       if [ -v GOMA_DIR ]; then
-        options+=("use_goma=1" "gomadir=\"${GOMA_DIR}\"")
+        args+=("use_goma=true" "goma_dir=\"${GOMA_DIR}\"")
+      elif [ -d "${HOME}/goma" ]; then
+        args+=("use_goma=true" "goma_dir=\"${HOME}/goma\"")
       else
-        options+=("use_goma=0")
+        args+=("use_goma=false")
       fi
       ;;
     disabled)
-      options+=("use_goma=0")
+      args+=("use_goma=false")
       ;;
   esac
-  echo "${options[*]}"
-}
-
-set_goma_dir_if_necessary() {
-  if [ "$GOMA" = "auto" -a ! -v GOMA_DIR ]; then
-    if [ -d "${HOME}/goma" ]; then
-      GOMA_DIR="${HOME}/goma"
-    fi
-  fi
-}
-
-start_goma_if_necessary() {
-  if [ "$GOMA" = "auto" -a -v GOMA_DIR ]; then
-    "${GOMA_DIR}/goma_ctl.py" ensure_start
-  fi
+  echo "${args[*]}"
 }
 
 # We're in src/mojo/tools. We want to get to src.
@@ -173,8 +142,6 @@
       exit 0
       ;;
     build)
-      set_goma_dir_if_necessary
-      start_goma_if_necessary
       should_do_Debug && do_build Debug
       should_do_Release && do_build Release
       ;;
@@ -190,13 +157,9 @@
       should_do_Debug && do_pytests Debug
       should_do_Release && do_pytests Release
       ;;
-    gyp)
-      set_goma_dir_if_necessary
-      do_gyp
-      ;;
-    gypall)
-      set_goma_dir_if_necessary
-      do_gypall
+    gn)
+      should_do_Debug && do_gn Debug
+      should_do_Release && do_gn Release
       ;;
     sync)
       do_sync
@@ -212,13 +175,13 @@
       ;;
     # Options ------------------------------------------------------------------
     --debug)
-      BUILD_TEST_TYPE=Debug
+      BUILD_TYPE=Debug
       ;;
     --release)
-      BUILD_TEST_TYPE=Release
+      BUILD_TYPE=Release
       ;;
     --debug-and-release)
-      BUILD_TEST_TYPE=Debug_and_Release
+      BUILD_TYPE=Debug_and_Release
       ;;
     --clang)
       COMPILER=clang
@@ -226,12 +189,6 @@
     --gcc)
       COMPILER=gcc
       ;;
-    --shared)
-      COMPONENT=shared
-      ;;
-    --static)
-      COMPONENT=static
-      ;;
     --use-goma)
       GOMA=auto
       ;;
diff --git a/mojo/tools/mojosh.sh b/mojo/tools/mojosh.sh
index bb8a2cd..ee2ba63 100755
--- a/mojo/tools/mojosh.sh
+++ b/mojo/tools/mojosh.sh
@@ -15,7 +15,7 @@
 DIRECTORY defaults to $DIRECTORY.
 
 Example:
-  $(basename "$0") mojo:mojo_sample_app
+  $(basename "$0") mojo:sample_app
 EOF
 }
 
diff --git a/mojo/tools/package_manager/package_manager_application.cc b/mojo/tools/package_manager/package_manager_application.cc
index ae4d4a4..4c08de9 100644
--- a/mojo/tools/package_manager/package_manager_application.cc
+++ b/mojo/tools/package_manager/package_manager_application.cc
@@ -34,7 +34,7 @@
 }
 
 void PackageManagerApplication::Initialize(ApplicationImpl* app) {
-  app->ConnectToService("mojo:mojo_network_service", &network_service_);
+  app->ConnectToService("mojo:network_service", &network_service_);
 
   printf("Enter URL> ");
   char buf[1024];
diff --git a/net/base/net_error_list.h b/net/base/net_error_list.h
index ae2ff13..89fbfff 100644
--- a/net/base/net_error_list.h
+++ b/net/base/net_error_list.h
@@ -99,6 +99,10 @@
 // The error can be emitted by code in chrome/browser/policy/policy_helpers.cc.
 NET_ERROR(BLOCKED_ENROLLMENT_CHECK_PENDING, -24)
 
+// The upload failed because the upload stream needed to be re-read, due to a
+// retry or a redirect, but the upload stream doesn't support that operation.
+NET_ERROR(UPLOAD_STREAM_REWIND_NOT_SUPPORTED, -25)
+
 // A connection was closed (corresponding to a TCP FIN).
 NET_ERROR(CONNECTION_CLOSED, -100)
 
diff --git a/net/http/http_server_properties_manager.cc b/net/http/http_server_properties_manager.cc
index 55aa019..08e4f6a 100644
--- a/net/http/http_server_properties_manager.cc
+++ b/net/http/http_server_properties_manager.cc
@@ -27,7 +27,13 @@
 // Time to wait before starting an update the preferences from the
 // http_server_properties_impl_ cache. Scheduling another update during this
 // period will reset the timer.
+// TODO(rtenneti): Remove OS_ANDROID ifdef after testing if flushing of
+// AlternateProtocolHosts to disk in 500ms helps with QUIC's 0RTT or not.
+#if defined(OS_ANDROID)
+const int64 kUpdatePrefsDelayMs = 500;
+#else
 const int64 kUpdatePrefsDelayMs = 5000;
+#endif
 
 // "version" 0 indicates, http_server_properties doesn't have "version"
 // property.
diff --git a/net/http/transport_security_state.cc b/net/http/transport_security_state.cc
index d1091be..d0c0b33 100644
--- a/net/http/transport_security_state.cc
+++ b/net/http/transport_security_state.cc
@@ -552,7 +552,7 @@
           return false;
         }
 
-        if (bit_offset <= jump_delta) {
+        if (bit_offset < jump_delta) {
           return false;
         }
 
@@ -598,8 +598,8 @@
                        PreloadResult* out) {
   bool found;
   if (!DecodeHSTSPreloadRaw(hostname, &found, out)) {
-    LOG(ERROR) << "Internal error in DecodeHSTSPreloadRaw for hostname "
-               << hostname;
+    DCHECK(false) << "Internal error in DecodeHSTSPreloadRaw for hostname "
+                  << hostname;
     return false;
   }
 
diff --git a/net/http/transport_security_state_unittest.cc b/net/http/transport_security_state_unittest.cc
index 67e6f91..8a2ebe8 100644
--- a/net/http/transport_security_state_unittest.cc
+++ b/net/http/transport_security_state_unittest.cc
@@ -10,6 +10,7 @@
 
 #include "base/base64.h"
 #include "base/files/file_path.h"
+#include "base/rand_util.h"
 #include "base/sha1.h"
 #include "base/strings/string_piece.h"
 #include "crypto/sha2.h"
@@ -92,6 +93,28 @@
   EXPECT_TRUE(state.GetDynamicDomainState("yahoo.com", &domain_state));
 }
 
+TEST_F(TransportSecurityStateTest, Fuzz) {
+  TransportSecurityState state;
+  TransportSecurityState::DomainState domain_state;
+
+  EnableStaticPins(&state);
+
+  for (size_t i = 0; i < 128; i++) {
+    std::string hostname;
+
+    for (;;) {
+      if (base::RandInt(0, 16) == 7) {
+        break;
+      }
+      if (i > 0 && base::RandInt(0, 7) == 7) {
+        hostname.append(1, '.');
+      }
+      hostname.append(1, 'a' + base::RandInt(0, 25));
+    }
+    state.GetStaticDomainState(hostname, &domain_state);
+  }
+}
+
 TEST_F(TransportSecurityStateTest, MatchesCase2) {
   TransportSecurityState state;
   TransportSecurityState::DomainState domain_state;
diff --git a/net/proxy/proxy_service.cc b/net/proxy/proxy_service.cc
index 52e9f7f..cb1011c 100644
--- a/net/proxy/proxy_service.cc
+++ b/net/proxy/proxy_service.cc
@@ -979,8 +979,24 @@
                                PacRequest** pac_request,
                                NetworkDelegate* network_delegate,
                                const BoundNetLog& net_log) {
-  DCHECK(CalledOnValidThread());
   DCHECK(!callback.is_null());
+  return ResolveProxyHelper(raw_url,
+                            load_flags,
+                            result,
+                            callback,
+                            pac_request,
+                            network_delegate,
+                            net_log);
+}
+
+int ProxyService::ResolveProxyHelper(const GURL& raw_url,
+                                     int load_flags,
+                                     ProxyInfo* result,
+                                     const net::CompletionCallback& callback,
+                                     PacRequest** pac_request,
+                                     NetworkDelegate* network_delegate,
+                                     const BoundNetLog& net_log) {
+  DCHECK(CalledOnValidThread());
 
   net_log.BeginEvent(NetLog::TYPE_PROXY_SERVICE);
 
@@ -1005,6 +1021,9 @@
     return DidFinishResolvingProxy(url, load_flags, network_delegate,
                                    result, rv, net_log);
 
+  if (callback.is_null())
+    return ERR_IO_PENDING;
+
   scoped_refptr<PacRequest> req(
       new PacRequest(this, url, load_flags, network_delegate,
                      result, callback, net_log));
@@ -1029,6 +1048,22 @@
   return rv;  // ERR_IO_PENDING
 }
 
+bool ProxyService:: TryResolveProxySynchronously(
+    const GURL& raw_url,
+    int load_flags,
+    ProxyInfo* result,
+    NetworkDelegate* network_delegate,
+    const BoundNetLog& net_log) {
+  net::CompletionCallback null_callback;
+  return ResolveProxyHelper(raw_url,
+                            load_flags,
+                            result,
+                            null_callback,
+                            NULL /* pac_request*/,
+                            network_delegate,
+                            net_log) == OK;
+}
+
 int ProxyService::TryToCompleteSynchronously(const GURL& url,
                                              int load_flags,
                                              NetworkDelegate* network_delegate,
diff --git a/net/proxy/proxy_service.h b/net/proxy/proxy_service.h
index 6f32c29..942c6a4 100644
--- a/net/proxy/proxy_service.h
+++ b/net/proxy/proxy_service.h
@@ -130,6 +130,14 @@
                    NetworkDelegate* network_delegate,
                    const BoundNetLog& net_log);
 
+  // Returns true if the proxy information could be determined without spawning
+  // an asynchronous task.  Otherwise, |result| is unmodified.
+  bool TryResolveProxySynchronously(const GURL& raw_url,
+                                    int load_flags,
+                                    ProxyInfo* result,
+                                    NetworkDelegate* network_delegate,
+                                    const BoundNetLog& net_log);
+
   // This method is called after a failure to connect or resolve a host name.
   // It gives the proxy service an opportunity to reconsider the proxy to use.
   // The |results| parameter contains the results returned by an earlier call
@@ -321,6 +329,17 @@
                                  NetworkDelegate* network_delegate,
                                  ProxyInfo* result);
 
+  // Identical to ResolveProxy, except that |callback| is permitted to be null.
+  // if |callback.is_null()|, this function becomes a thin wrapper around
+  // |TryToCompleteSynchronously|.
+  int ResolveProxyHelper(const GURL& url,
+                         int load_flags,
+                         ProxyInfo* results,
+                         const net::CompletionCallback& callback,
+                         PacRequest** pac_request,
+                         NetworkDelegate* network_delegate,
+                         const BoundNetLog& net_log);
+
   // Cancels all of the requests sent to the ProxyResolver. These will be
   // restarted when calling SetReady().
   void SuspendAllPendingRequests();
diff --git a/net/proxy/proxy_service_unittest.cc b/net/proxy/proxy_service_unittest.cc
index 12f9af2..acc015e 100644
--- a/net/proxy/proxy_service_unittest.cc
+++ b/net/proxy/proxy_service_unittest.cc
@@ -3081,4 +3081,56 @@
   EXPECT_TRUE(info3.is_direct());
 }
 
+// Test that the synchronous resolution fails when a PAC script is active.
+TEST_F(ProxyServiceTest, SynchronousWithPAC) {
+  MockProxyConfigService* config_service =
+      new MockProxyConfigService("http://foopy/proxy.pac");
+
+  MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver();
+
+  ProxyService service(config_service, resolver, NULL);
+
+  GURL url("http://www.google.com/");
+
+  ProxyInfo info;
+  info.UseDirect();
+  CapturingBoundNetLog log;
+
+  bool synchronous_success = service.TryResolveProxySynchronously(
+      url, net::LOAD_NORMAL, &info, NULL, log.bound());
+  EXPECT_FALSE(synchronous_success);
+
+  // No request should have been queued.
+  EXPECT_EQ(0u, resolver->pending_requests().size());
+
+  // |info| should not have been modified.
+  EXPECT_TRUE(info.is_direct());
+}
+
+// Test that synchronous results are returned correctly if a fixed proxy
+// configuration is active.
+TEST_F(ProxyServiceTest, SynchronousWithFixedConfiguration) {
+  ProxyConfig config;
+  config.proxy_rules().ParseFromString("foopy1:8080");
+  config.set_auto_detect(false);
+
+  MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver();
+
+  ProxyService service(new MockProxyConfigService(config), resolver, NULL);
+
+  GURL url("http://www.google.com/");
+
+  ProxyInfo info;
+  CapturingBoundNetLog log;
+
+  bool synchronous_success = service.TryResolveProxySynchronously(
+      url, net::LOAD_NORMAL, &info, NULL, log.bound());
+  EXPECT_TRUE(synchronous_success);
+  EXPECT_FALSE(info.is_direct());
+  EXPECT_EQ("foopy1", info.proxy_server().host_port_pair().host());
+
+  // No request should have been queued.
+  EXPECT_EQ(0u, resolver->pending_requests().size());
+}
+
 }  // namespace net
diff --git a/net/quic/quic_client_session.cc b/net/quic/quic_client_session.cc
index 4495765..60bcbb5 100644
--- a/net/quic/quic_client_session.cc
+++ b/net/quic/quic_client_session.cc
@@ -563,7 +563,8 @@
 
 void QuicClientSession::OnCryptoHandshakeEvent(CryptoHandshakeEvent event) {
   if (!callback_.is_null() &&
-      (!require_confirmation_ || event == HANDSHAKE_CONFIRMED)) {
+      (!require_confirmation_ ||
+       event == HANDSHAKE_CONFIRMED || event == ENCRYPTION_REESTABLISHED)) {
     // TODO(rtenneti): Currently for all CryptoHandshakeEvent events, callback_
     // could be called because there are no error events in CryptoHandshakeEvent
     // enum. If error events are added to CryptoHandshakeEvent, then the
diff --git a/net/quic/quic_framer.cc b/net/quic/quic_framer.cc
index 83c44c0..7e914f8 100644
--- a/net/quic/quic_framer.cc
+++ b/net/quic/quic_framer.cc
@@ -1528,8 +1528,7 @@
     return false;
   }
 
-  if (error_code >= QUIC_STREAM_LAST_ERROR ||
-      error_code < QUIC_STREAM_NO_ERROR) {
+  if (error_code >= QUIC_STREAM_LAST_ERROR) {
     set_detailed_error("Invalid rst stream error code.");
     return false;
   }
@@ -1553,8 +1552,7 @@
     return false;
   }
 
-  if (error_code >= QUIC_LAST_ERROR ||
-         error_code < QUIC_NO_ERROR) {
+  if (error_code >= QUIC_LAST_ERROR) {
     set_detailed_error("Invalid error code.");
     return false;
   }
@@ -1579,8 +1577,7 @@
   }
   frame->error_code = static_cast<QuicErrorCode>(error_code);
 
-  if (error_code >= QUIC_LAST_ERROR ||
-      error_code < QUIC_NO_ERROR) {
+  if (error_code >= QUIC_LAST_ERROR) {
     set_detailed_error("Invalid error code.");
     return false;
   }
diff --git a/net/socket/ssl_client_socket_openssl.cc b/net/socket/ssl_client_socket_openssl.cc
index 04be988..953f336 100644
--- a/net/socket/ssl_client_socket_openssl.cc
+++ b/net/socket/ssl_client_socket_openssl.cc
@@ -1363,6 +1363,15 @@
     } else if (*next_result < 0) {
       int err = SSL_get_error(ssl_, *next_result);
       *next_result = MapOpenSSLError(err, err_tracer);
+
+      // Many servers do not reliably send a close_notify alert when shutting
+      // down a connection, and instead terminate the TCP connection. This is
+      // reported as ERR_CONNECTION_CLOSED. Because of this, map the unclean
+      // shutdown to a graceful EOF, instead of treating it as an error as it
+      // should be.
+      if (*next_result == ERR_CONNECTION_CLOSED)
+        *next_result = 0;
+
       if (rv > 0 && *next_result == ERR_IO_PENDING) {
           // If at least some data was read from SSL_read(), do not treat
           // insufficient data as an error to return in the next call to
diff --git a/net/socket/ssl_client_socket_unittest.cc b/net/socket/ssl_client_socket_unittest.cc
index 7e7bf2c..58e43c7 100644
--- a/net/socket/ssl_client_socket_unittest.cc
+++ b/net/socket/ssl_client_socket_unittest.cc
@@ -276,7 +276,7 @@
   // If there is already a pending asynchronous read, the configured error
   // will not be returned until that asynchronous read has completed and Read()
   // is called again.
-  void SetNextReadError(Error error) {
+  void SetNextReadError(int error) {
     DCHECK_GE(0, error);
     have_read_error_ = true;
     pending_read_error_ = error;
@@ -286,7 +286,7 @@
   // If there is already a pending asynchronous write, the configured error
   // will not be returned until that asynchronous write has completed and
   // Write() is called again.
-  void SetNextWriteError(Error error) {
+  void SetNextWriteError(int error) {
     DCHECK_GE(0, error);
     have_write_error_ = true;
     pending_write_error_ = error;
@@ -1813,6 +1813,78 @@
 #endif
 }
 
+// Tests that SSLClientSocket fails the handshake if the underlying
+// transport is cleanly closed.
+TEST_F(SSLClientSocketTest, Connect_WithZeroReturn) {
+  SpawnedTestServer test_server(SpawnedTestServer::TYPE_HTTPS,
+                                SpawnedTestServer::kLocalhost,
+                                base::FilePath());
+  ASSERT_TRUE(test_server.Start());
+
+  AddressList addr;
+  ASSERT_TRUE(test_server.GetAddressList(&addr));
+
+  TestCompletionCallback callback;
+  scoped_ptr<StreamSocket> real_transport(
+      new TCPClientSocket(addr, NULL, NetLog::Source()));
+  scoped_ptr<SynchronousErrorStreamSocket> transport(
+      new SynchronousErrorStreamSocket(real_transport.Pass()));
+  int rv = callback.GetResult(transport->Connect(callback.callback()));
+  EXPECT_EQ(OK, rv);
+
+  SynchronousErrorStreamSocket* raw_transport = transport.get();
+  scoped_ptr<SSLClientSocket> sock(
+      CreateSSLClientSocket(transport.PassAs<StreamSocket>(),
+                            test_server.host_port_pair(),
+                            kDefaultSSLConfig));
+
+  raw_transport->SetNextReadError(0);
+
+  rv = callback.GetResult(sock->Connect(callback.callback()));
+  EXPECT_EQ(ERR_CONNECTION_CLOSED, rv);
+  EXPECT_FALSE(sock->IsConnected());
+}
+
+// Tests that SSLClientSocket cleanly returns a Read of size 0 if the
+// underlying socket is cleanly closed.
+// This is a regression test for https://crbug.com/422246
+TEST_F(SSLClientSocketTest, Read_WithZeroReturn) {
+  SpawnedTestServer test_server(SpawnedTestServer::TYPE_HTTPS,
+                                SpawnedTestServer::kLocalhost,
+                                base::FilePath());
+  ASSERT_TRUE(test_server.Start());
+
+  AddressList addr;
+  ASSERT_TRUE(test_server.GetAddressList(&addr));
+
+  TestCompletionCallback callback;
+  scoped_ptr<StreamSocket> real_transport(
+      new TCPClientSocket(addr, NULL, NetLog::Source()));
+  scoped_ptr<SynchronousErrorStreamSocket> transport(
+      new SynchronousErrorStreamSocket(real_transport.Pass()));
+  int rv = callback.GetResult(transport->Connect(callback.callback()));
+  EXPECT_EQ(OK, rv);
+
+  // Disable TLS False Start to ensure the handshake has completed.
+  SSLConfig ssl_config;
+  ssl_config.false_start_enabled = false;
+
+  SynchronousErrorStreamSocket* raw_transport = transport.get();
+  scoped_ptr<SSLClientSocket> sock(
+      CreateSSLClientSocket(transport.PassAs<StreamSocket>(),
+                            test_server.host_port_pair(),
+                            ssl_config));
+
+  rv = callback.GetResult(sock->Connect(callback.callback()));
+  EXPECT_EQ(OK, rv);
+  EXPECT_TRUE(sock->IsConnected());
+
+  raw_transport->SetNextReadError(0);
+  scoped_refptr<IOBuffer> buf(new IOBuffer(4096));
+  rv = callback.GetResult(sock->Read(buf.get(), 4096, callback.callback()));
+  EXPECT_EQ(0, rv);
+}
+
 TEST_F(SSLClientSocketTest, Read_SmallChunks) {
   SpawnedTestServer test_server(SpawnedTestServer::TYPE_HTTPS,
                                 SpawnedTestServer::kLocalhost,
diff --git a/net/spdy/spdy_framer.cc b/net/spdy/spdy_framer.cc
index fbe3675..6affd7b 100644
--- a/net/spdy/spdy_framer.cc
+++ b/net/spdy/spdy_framer.cc
@@ -2314,7 +2314,7 @@
     }
     builder.WriteBytes(data_ir.data().data(), data_ir.data().length());
     if (data_ir.padding_payload_len() > 0) {
-      string padding = string(data_ir.padding_payload_len(), '0');
+      string padding(data_ir.padding_payload_len(), 0);
       builder.WriteBytes(padding.data(), padding.length());
     }
     DCHECK_EQ(size_with_padding, builder.length());
diff --git a/net/spdy/spdy_framer_test.cc b/net/spdy/spdy_framer_test.cc
index 07b23ac..982e75c 100644
--- a/net/spdy/spdy_framer_test.cc
+++ b/net/spdy/spdy_framer_test.cc
@@ -1638,26 +1638,28 @@
       0x01, 0xf7,                  // Pad length field.
       'h',  'e',  'l',  'l',       // Data
       'o',
-      // Padding of 247 zeros.
-      '0',  '0',  '0',  '0',  '0',  '0',  '0',  '0', '0',  '0',  '0',  '0', '0',
-      '0',  '0',  '0',  '0',  '0',  '0',  '0',  '0', '0',  '0',  '0',  '0', '0',
-      '0',  '0',  '0',  '0',  '0',  '0',  '0',  '0', '0',  '0',  '0',  '0', '0',
-      '0',  '0',  '0',  '0',  '0',  '0',  '0',  '0', '0',  '0',  '0',  '0', '0',
-      '0',  '0',  '0',  '0',  '0',  '0',  '0',  '0', '0',  '0',  '0',  '0', '0',
-      '0',  '0',  '0',  '0',  '0',  '0',  '0',  '0', '0',  '0',  '0',  '0', '0',
-      '0',  '0',  '0',  '0',  '0',  '0',  '0',  '0', '0',  '0',  '0',  '0', '0',
-      '0',  '0',  '0',  '0',  '0',  '0',  '0',  '0', '0',  '0',  '0',  '0', '0',
-      '0',  '0',  '0',  '0',  '0',  '0',  '0',  '0', '0',  '0',  '0',  '0', '0',
-      '0',  '0',  '0',  '0',  '0',  '0',  '0',  '0', '0',  '0',  '0',  '0', '0',
-      '0',  '0',  '0',  '0',  '0',  '0',  '0',  '0', '0',  '0',  '0',  '0', '0',
-      '0',  '0',  '0',  '0',  '0',  '0',  '0',  '0', '0',  '0',  '0',  '0', '0',
-      '0',  '0',  '0',  '0',  '0',  '0',  '0',  '0', '0',  '0',  '0',  '0', '0',
-      '0',  '0',  '0',  '0',  '0',  '0',  '0',  '0', '0',  '0',  '0',  '0', '0',
-      '0',  '0',  '0',  '0',  '0',  '0',  '0',  '0', '0',  '0',  '0',  '0', '0',
-      '0',  '0',  '0',  '0',  '0',  '0',  '0',  '0', '0',  '0',  '0',  '0', '0',
-      '0',  '0',  '0',  '0',  '0',  '0',  '0',  '0', '0',  '0',  '0',  '0', '0',
-      '0',  '0',  '0',  '0',  '0',  '0',  '0',  '0', '0',  '0',  '0',  '0', '0',
-      '0',  '0',  '0',  '0',  '0',  '0',  '0',  '0', '0',  '0',  '0',  '0', '0',
+      // Padding of 247 0x00(s).
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     };
     const char bytes[] = "hello";
 
@@ -1698,8 +1700,8 @@
       0x01, 0x07,                  // Pad length field.
       'h',  'e',  'l',  'l',       // Data
       'o',
-      '0',  '0',  '0',  '0',       // Padding
-      '0',  '0',  '0'
+      0x00,  0x00,  0x00,  0x00,   // Padding
+      0x00,  0x00,  0x00
     };
     const char bytes[] = "hello";
 
diff --git a/net/test/embedded_test_server/http_request.cc b/net/test/embedded_test_server/http_request.cc
index ca9d070..3acb550 100644
--- a/net/test/embedded_test_server/http_request.cc
+++ b/net/test/embedded_test_server/http_request.cc
@@ -89,6 +89,7 @@
     base::SplitString(header_line, ' ', &header_line_tokens);
     DCHECK_EQ(3u, header_line_tokens.size());
     // Method.
+    http_request_->method_string = header_line_tokens[0];
     http_request_->method = GetMethodType(base::StringToLowerASCII(
         header_line_tokens[0]));
     // Address.
diff --git a/net/test/embedded_test_server/http_request.h b/net/test/embedded_test_server/http_request.h
index 1e849d8..cb9144b 100644
--- a/net/test/embedded_test_server/http_request.h
+++ b/net/test/embedded_test_server/http_request.h
@@ -35,6 +35,7 @@
 
   std::string relative_url;  // Starts with '/'. Example: "/test?query=foo"
   HttpMethod method;
+  std::string method_string;
   std::map<std::string, std::string> headers;
   std::string content;
   bool has_content;
diff --git a/net/test/embedded_test_server/http_request_unittest.cc b/net/test/embedded_test_server/http_request_unittest.cc
index b45742c..1006e4e 100644
--- a/net/test/embedded_test_server/http_request_unittest.cc
+++ b/net/test/embedded_test_server/http_request_unittest.cc
@@ -35,6 +35,7 @@
   {
     scoped_ptr<HttpRequest> request = parser.GetRequest();
     EXPECT_EQ("/foobar.html", request->relative_url);
+    EXPECT_EQ("POST", request->method_string);
     EXPECT_EQ(METHOD_POST, request->method);
     EXPECT_EQ("1234567890", request->content);
     ASSERT_EQ(3u, request->headers.size());
@@ -78,5 +79,19 @@
   EXPECT_FALSE(request->has_content);
 }
 
+TEST(HttpRequestTest, ParseGet) {
+  HttpRequestParser parser;
+
+  parser.ProcessChunk("GET /foobar.html HTTP/1.1\r\n\r\n");
+  ASSERT_EQ(HttpRequestParser::ACCEPTED, parser.ParseRequest());
+
+  scoped_ptr<HttpRequest> request = parser.GetRequest();
+  EXPECT_EQ("/foobar.html", request->relative_url);
+  EXPECT_EQ("GET", request->method_string);
+  EXPECT_EQ(METHOD_GET, request->method);
+  EXPECT_EQ("", request->content);
+  EXPECT_FALSE(request->has_content);
+}
+
 }  // namespace test_server
 }  // namespace net
diff --git a/testing/android/java/src/org/chromium/native_test/ChromeNativeTestActivity.java b/testing/android/java/src/org/chromium/native_test/ChromeNativeTestActivity.java
index 7482af8..9b241d1 100644
--- a/testing/android/java/src/org/chromium/native_test/ChromeNativeTestActivity.java
+++ b/testing/android/java/src/org/chromium/native_test/ChromeNativeTestActivity.java
@@ -10,6 +10,7 @@
 import android.os.Handler;
 import android.util.Log;
 
+import org.chromium.base.CommandLine;
 import org.chromium.base.PathUtils;
 import org.chromium.base.PowerMonitor;
 import org.chromium.base.ResourceExtractor;
@@ -29,6 +30,8 @@
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
+        CommandLine.init(new String[]{});
+
         // Needed by path_utils_unittest.cc
         PathUtils.setPrivateDataDirectorySuffix("chrome");
 
diff --git a/testing/chromoting/chromoting_integration_tests.isolate b/testing/chromoting/chromoting_integration_tests.isolate
index 135836b..b0c2d00 100644
--- a/testing/chromoting/chromoting_integration_tests.isolate
+++ b/testing/chromoting/chromoting_integration_tests.isolate
@@ -52,7 +52,7 @@
     ['OS=="mac" or OS=="win"', {
       'variables': {
         'command': [
-          '../testing/test_env.py',
+          '../test_env.py',
           '<(PRODUCT_DIR)/browser_tests<(EXECUTABLE_SUFFIX)',
           '--gtest_filter=RemoteDesktopBrowserTest.MANUAL_Launch',
           '--run-manual',
diff --git a/testing/test_env.py b/testing/test_env.py
index 574aaed..4c19427 100755
--- a/testing/test_env.py
+++ b/testing/test_env.py
@@ -114,6 +114,8 @@
     # Important note: when running ASan with leak detection enabled, we must use
     # the LSan symbolization options above.
     symbolization_options = ['symbolize=0']
+    # Set the path to llvm-symbolizer to be used by asan_symbolize.py
+    extra_env['LLVM_SYMBOLIZER_PATH'] = symbolizer_path
 
   asan_options.extend(symbolization_options)
 
@@ -172,10 +174,11 @@
       p1 = subprocess.Popen(cmd, env=env, stdout=subprocess.PIPE,
                             stderr=sys.stdout)
       p2 = subprocess.Popen(["../tools/valgrind/asan/asan_symbolize.py"],
-                            stdin=p1.stdout)
+                            env=env, stdin=p1.stdout)
       p1.stdout.close()  # Allow p1 to receive a SIGPIPE if p2 exits.
+      p1.wait()
       p2.wait()
-      return p2.returncode
+      return p1.returncode
     else:
       return subprocess.call(cmd, env=env)
   except OSError:
diff --git a/tools/android/checkstyle/OWNERS b/tools/android/checkstyle/OWNERS
new file mode 100644
index 0000000..577bf98
--- /dev/null
+++ b/tools/android/checkstyle/OWNERS
@@ -0,0 +1,2 @@
+aurimas@chromium.org
+newt@chromium.org
diff --git a/tools/android/checkstyle/checkstyle.py b/tools/android/checkstyle/checkstyle.py
index 6b54c77..c8ad04f 100644
--- a/tools/android/checkstyle/checkstyle.py
+++ b/tools/android/checkstyle/checkstyle.py
@@ -13,7 +13,7 @@
     os.path.join(os.path.dirname(__file__),
                  os.pardir, os.pardir, os.pardir))
 CHECKSTYLE_ROOT = os.path.join(CHROMIUM_SRC, 'third_party', 'checkstyle',
-                               'checkstyle-5.8-all.jar')
+                               'checkstyle-5.9-all.jar')
 
 
 def RunCheckstyle(input_api, output_api, style_file):
diff --git a/tools/android/checkstyle/chromium-style-5.0.xml b/tools/android/checkstyle/chromium-style-5.0.xml
index 7f6b7ee..17b44b4 100644
--- a/tools/android/checkstyle/chromium-style-5.0.xml
+++ b/tools/android/checkstyle/chromium-style-5.0.xml
@@ -158,11 +158,11 @@
       <property name="option" value="top"/>
       <property name="separated" value="true"/>
     </module>
-    <!-- TODO(aurimas): make indentation an error once https://github.com/checkstyle/checkstyle/issues/255 is fixed. -->
     <module name="Indentation">
-      <property name="severity" value="info"/>
+      <property name="severity" value="error"/>
       <property name="basicOffset" value="4"/>
       <property name="throwsIndent" value="8"/>
+      <property name="lineWrappingIndentation" value="8"/>
     </module>
   </module>
   <module name="FileTabCharacter">
diff --git a/tools/clang/blink_gc_plugin/BlinkGCPlugin.cpp b/tools/clang/blink_gc_plugin/BlinkGCPlugin.cpp
index 59cd417..d24d67a 100644
--- a/tools/clang/blink_gc_plugin/BlinkGCPlugin.cpp
+++ b/tools/clang/blink_gc_plugin/BlinkGCPlugin.cpp
@@ -572,6 +572,7 @@
 class CheckGCRootsVisitor : public RecursiveEdgeVisitor {
  public:
   typedef std::vector<FieldPoint*> RootPath;
+  typedef std::set<RecordInfo*> VisitingSet;
   typedef std::vector<RootPath> Errors;
 
   CheckGCRootsVisitor() {}
@@ -594,6 +595,11 @@
     if (edge->value()->record()->isUnion())
       return;
 
+    // Prevent infinite regress for cyclic part objects.
+    if (visiting_set_.find(edge->value()) != visiting_set_.end())
+      return;
+
+    visiting_set_.insert(edge->value());
     // If the value is a part object, then continue checking for roots.
     for (Context::iterator it = context().begin();
          it != context().end();
@@ -602,6 +608,7 @@
         return;
     }
     ContainsGCRoots(edge->value());
+    visiting_set_.erase(edge->value());
   }
 
   void VisitPersistent(Persistent* edge) override {
@@ -615,6 +622,7 @@
 
  protected:
   RootPath current_;
+  VisitingSet visiting_set_;
   Errors gc_roots_;
 };
 
diff --git a/tools/clang/blink_gc_plugin/tests/crash_on_invalid.txt b/tools/clang/blink_gc_plugin/tests/crash_on_invalid.txt
index 8b13789..cf19ff5 100644
--- a/tools/clang/blink_gc_plugin/tests/crash_on_invalid.txt
+++ b/tools/clang/blink_gc_plugin/tests/crash_on_invalid.txt
@@ -1 +1,8 @@
-
+In file included from crash_on_invalid.cpp:5:
+./crash_on_invalid.h:16:30: error: unknown template name 'GarbageCollectedFinalized'
+class Gamepad final : public GarbageCollectedFinalized<Gamepad>,
+                             ^
+./crash_on_invalid.h:20:19: error: unknown type name 'WrapperTypeInfo'
+    virtual const WrapperTypeInfo *wrapperTypeInfo() const {}
+                  ^
+2 errors generated.
diff --git a/tools/clang/blink_gc_plugin/tests/fields_require_tracing.cpp b/tools/clang/blink_gc_plugin/tests/fields_require_tracing.cpp
index 9779510..880ce1e 100644
--- a/tools/clang/blink_gc_plugin/tests/fields_require_tracing.cpp
+++ b/tools/clang/blink_gc_plugin/tests/fields_require_tracing.cpp
@@ -10,6 +10,12 @@
     m_obj1->trace(visitor); // Don't allow direct tracing.
     visitor->trace(m_obj2);
     // Missing visitor->trace(m_obj3);
+    visitor->trace(m_parts);
+}
+
+void PartBObject::trace(Visitor* visitor) {
+  // Missing visitor->trace(m_set);
+  visitor->trace(m_vector);
 }
 
 void HeapObject::trace(Visitor* visitor) {
diff --git a/tools/clang/blink_gc_plugin/tests/fields_require_tracing.h b/tools/clang/blink_gc_plugin/tests/fields_require_tracing.h
index fe5b8d9..60caa68 100644
--- a/tools/clang/blink_gc_plugin/tests/fields_require_tracing.h
+++ b/tools/clang/blink_gc_plugin/tests/fields_require_tracing.h
@@ -10,6 +10,16 @@
 namespace blink {
 
 class HeapObject;
+class PartObject;
+
+class PartBObject {
+    DISALLOW_ALLOCATION();
+public:
+    void trace(Visitor*);
+private:
+    HeapHashSet<PartBObject> m_set;
+    HeapVector<PartBObject> m_vector;
+};
 
 class PartObject {
     DISALLOW_ALLOCATION();
@@ -19,6 +29,8 @@
     Member<HeapObject> m_obj1;
     Member<HeapObject> m_obj2;
     Member<HeapObject> m_obj3;
+
+    HeapVector<PartBObject> m_parts;
 };
 
 class HeapObject : public GarbageCollected<HeapObject> {
diff --git a/tools/clang/blink_gc_plugin/tests/fields_require_tracing.txt b/tools/clang/blink_gc_plugin/tests/fields_require_tracing.txt
index cafa32f..39d49f3 100644
--- a/tools/clang/blink_gc_plugin/tests/fields_require_tracing.txt
+++ b/tools/clang/blink_gc_plugin/tests/fields_require_tracing.txt
@@ -1,16 +1,22 @@
 fields_require_tracing.cpp:9:1: warning: [blink-gc] Class 'PartObject' has untraced fields that require tracing.
 void PartObject::trace(Visitor* visitor) {
 ^
-./fields_require_tracing.h:19:5: note: [blink-gc] Untraced field 'm_obj1' declared here:
+./fields_require_tracing.h:29:5: note: [blink-gc] Untraced field 'm_obj1' declared here:
     Member<HeapObject> m_obj1;
     ^
-./fields_require_tracing.h:21:5: note: [blink-gc] Untraced field 'm_obj3' declared here:
+./fields_require_tracing.h:31:5: note: [blink-gc] Untraced field 'm_obj3' declared here:
     Member<HeapObject> m_obj3;
     ^
-fields_require_tracing.cpp:15:1: warning: [blink-gc] Class 'HeapObject' has untraced fields that require tracing.
+fields_require_tracing.cpp:16:1: warning: [blink-gc] Class 'PartBObject' has untraced fields that require tracing.
+void PartBObject::trace(Visitor* visitor) {
+^
+./fields_require_tracing.h:20:5: note: [blink-gc] Untraced field 'm_set' declared here:
+    HeapHashSet<PartBObject> m_set;
+    ^
+fields_require_tracing.cpp:21:1: warning: [blink-gc] Class 'HeapObject' has untraced fields that require tracing.
 void HeapObject::trace(Visitor* visitor) {
 ^
-./fields_require_tracing.h:28:5: note: [blink-gc] Untraced field 'm_part' declared here:
+./fields_require_tracing.h:40:5: note: [blink-gc] Untraced field 'm_part' declared here:
     PartObject m_part;
     ^
-2 warnings generated.
+3 warnings generated.
diff --git a/tools/gritsettings/resource_ids b/tools/gritsettings/resource_ids
index c4a6337..7fa7d9f 100644
--- a/tools/gritsettings/resource_ids
+++ b/tools/gritsettings/resource_ids
@@ -185,6 +185,9 @@
   "extensions/extensions_strings.grd": {
     "messages": [27000],
   },
+  "extensions/shell/app_shell_resources.grd": {
+    "includes": [27400],
+  },
   "chrome/browser/resources/memory_internals_resources.grd": {
     "includes": [27500],
   },
diff --git a/tools/idl_parser/idl_lexer.py b/tools/idl_parser/idl_lexer.py
index 9c320d6..5ba1d4e 100755
--- a/tools/idl_parser/idl_lexer.py
+++ b/tools/idl_parser/idl_lexer.py
@@ -93,7 +93,8 @@
     'octet' : 'OCTET',
     'optional' : 'OPTIONAL',
     'or' : 'OR',
-    'partial'  : 'PARTIAL',
+    'partial' : 'PARTIAL',
+    'Promise' : 'PROMISE',
     'readonly' : 'READONLY',
     'RegExp' : 'REGEXP',
     'sequence' : 'SEQUENCE',
diff --git a/tools/idl_parser/idl_parser.py b/tools/idl_parser/idl_parser.py
index a19785b..9b63f94 100755
--- a/tools/idl_parser/idl_parser.py
+++ b/tools/idl_parser/idl_parser.py
@@ -265,6 +265,14 @@
                        | AttributeOrOperationOrIterator"""
     p[0] = p[1]
 
+  # [10.1] Removed unsupported: Serializer
+  def p_AttributeOrOperationOrIterator(self, p):
+    """AttributeOrOperationOrIterator : Stringifier
+                                      | StaticMember
+                                      | ReadWriteAttribute
+                                      | OperationOrIterator"""
+    p[0] = p[1]
+
   # [11]
   def p_Dictionary(self, p):
     """Dictionary : DICTIONARY identifier Inheritance '{' DictionaryMembers '}' ';'"""
@@ -288,25 +296,27 @@
     """DictionaryMember : Type identifier Default ';'"""
     p[0] = self.BuildNamed('Key', p, 2, ListFromConcat(p[1], p[3]))
 
-  # [14]
+  # [14] NOT IMPLEMENTED (Required)
+
+  # [15]
   def p_PartialDictionary(self, p):
     """PartialDictionary : DICTIONARY identifier '{' DictionaryMembers '}' ';'"""
     partial = self.BuildTrue('Partial')
     p[0] = self.BuildNamed('Dictionary', p, 2, ListFromConcat(p[4], partial))
 
-  # [14.1] Error recovery for Partial Dictionary
+  # [15.1] Error recovery for Partial Dictionary
   def p_PartialDictionaryError(self, p):
     """PartialDictionary : DICTIONARY error ';'"""
     p[0] = self.BuildError(p, 'PartialDictionary')
 
-  # [15]
+  # [16]
   def p_Default(self, p):
     """Default : '=' DefaultValue
                |"""
     if len(p) > 1:
       p[0] = self.BuildProduction('Default', p, 2, p[2])
 
-  # [16]
+  # [17]
   def p_DefaultValue(self, p):
     """DefaultValue : ConstValue
                     | string"""
@@ -316,12 +326,12 @@
     else:
       p[0] = p[1]
 
-  # [17]
+  # [] - Not specified
   def p_Exception(self, p):
     """Exception : EXCEPTION identifier Inheritance '{' ExceptionMembers '}' ';'"""
     p[0] = self.BuildNamed('Exception', p, 2, ListFromConcat(p[3], p[5]))
 
-  # [18]
+  # [] - Not specified
   def p_ExceptionMembers(self, p):
     """ExceptionMembers : ExtendedAttributeList ExceptionMember ExceptionMembers
                         |"""
@@ -329,42 +339,42 @@
       p[2].AddChildren(p[1])
       p[0] = ListFromConcat(p[2], p[3])
 
-  # [18.1] Error recovery for ExceptionMembers
+  # [.1] Error recovery for ExceptionMembers - Not specified
   def p_ExceptionMembersError(self, p):
     """ExceptionMembers : error"""
     p[0] = self.BuildError(p, 'ExceptionMembers')
 
-  # [19]
+  # [18]
   def p_Inheritance(self, p):
     """Inheritance : ':' identifier
                    |"""
     if len(p) > 1:
       p[0] = self.BuildNamed('Inherit', p, 2)
 
-  # [20]
+  # [19]
   def p_Enum(self, p):
     """Enum : ENUM identifier '{' EnumValueList '}' ';'"""
     p[0] = self.BuildNamed('Enum', p, 2, p[4])
 
-  # [20.1] Error recovery for Enums
+  # [19.1] Error recovery for Enums
   def p_EnumError(self, p):
     """Enum : ENUM error ';'"""
     p[0] = self.BuildError(p, 'Enum')
 
-  # [21]
+  # [20]
   def p_EnumValueList(self, p):
     """EnumValueList : ExtendedAttributeList string EnumValueListComma"""
     enum = self.BuildNamed('EnumItem', p, 2, p[1])
     p[0] = ListFromConcat(enum, p[3])
 
-  # [22]
+  # [21]
   def p_EnumValueListComma(self, p):
     """EnumValueListComma : ',' EnumValueListString
                           |"""
     if len(p) > 1:
       p[0] = p[2]
 
-  # [23]
+  # [22]
   def p_EnumValueListString(self, p):
     """EnumValueListString : ExtendedAttributeList string EnumValueListComma
                            |"""
@@ -372,35 +382,35 @@
       enum = self.BuildNamed('EnumItem', p, 2, p[1])
       p[0] = ListFromConcat(enum, p[3])
 
-  # [24]
+  # [23]
   def p_CallbackRest(self, p):
     """CallbackRest : identifier '=' ReturnType '(' ArgumentList ')' ';'"""
     arguments = self.BuildProduction('Arguments', p, 4, p[5])
     p[0] = self.BuildNamed('Callback', p, 1, ListFromConcat(p[3], arguments))
 
-  # [25]
+  # [24]
   def p_Typedef(self, p):
     """Typedef : TYPEDEF ExtendedAttributeListNoComments Type identifier ';'"""
     p[0] = self.BuildNamed('Typedef', p, 4, ListFromConcat(p[2], p[3]))
 
-  # [25.1] Error recovery for Typedefs
+  # [24.1] Error recovery for Typedefs
   def p_TypedefError(self, p):
     """Typedef : TYPEDEF error ';'"""
     p[0] = self.BuildError(p, 'Typedef')
 
-  # [26]
+  # [25]
   def p_ImplementsStatement(self, p):
     """ImplementsStatement : identifier IMPLEMENTS identifier ';'"""
     name = self.BuildAttribute('REFERENCE', p[3])
     p[0] = self.BuildNamed('Implements', p, 1, name)
 
-  # [27]
+  # [26]
   def p_Const(self,  p):
     """Const : CONST ConstType identifier '=' ConstValue ';'"""
     value = self.BuildProduction('Value', p, 5, p[5])
     p[0] = self.BuildNamed('Const', p, 3, ListFromConcat(p[2], value))
 
-  # [28]
+  # [27]
   def p_ConstValue(self, p):
     """ConstValue : BooleanLiteral
                   | FloatLiteral
@@ -412,20 +422,20 @@
     else:
       p[0] = p[1]
 
-  # [28.1] Add definition for NULL
+  # [27.1] Add definition for NULL
   def p_null(self, p):
     """null : NULL"""
     p[0] = ListFromConcat(self.BuildAttribute('TYPE', 'NULL'),
                           self.BuildAttribute('NAME', 'NULL'))
 
-  # [29]
+  # [28]
   def p_BooleanLiteral(self, p):
     """BooleanLiteral : TRUE
                       | FALSE"""
     value = self.BuildAttribute('VALUE', Boolean(p[1] == 'true'))
     p[0] = ListFromConcat(self.BuildAttribute('TYPE', 'boolean'), value)
 
-  # [30]
+  # [29]
   def p_FloatLiteral(self, p):
     """FloatLiteral : float
                     | '-' INFINITY
@@ -438,22 +448,14 @@
     p[0] = ListFromConcat(self.BuildAttribute('TYPE', 'float'),
                           self.BuildAttribute('VALUE', val))
 
-  # [31] Removed unsupported: Serializer
-  def p_AttributeOrOperationOrIterator(self, p):
-    """AttributeOrOperationOrIterator : Stringifier
-                                      | StaticMember
-                                      | Attribute
-                                      | OperationOrIterator"""
-    p[0] = p[1]
+  # [30-34] NOT IMPLEMENTED (Serializer)
 
-  # [32-37] NOT IMPLEMENTED (Serializer)
-
-  # [38]
+  # [35]
   def p_Stringifier(self, p):
     """Stringifier : STRINGIFIER StringifierRest"""
     p[0] = self.BuildProduction('Stringifier', p, 1, p[2])
 
-  # [39]
+  # [36]
   def p_StringifierRest(self, p):
     """StringifierRest : AttributeRest
                        | ReturnType OperationRest
@@ -464,13 +466,13 @@
     elif p[1] != ';':
       p[0] = p[1]
 
-  # [40]
+  # [37]
   def p_StaticMember(self, p):
     """StaticMember : STATIC StaticMemberRest"""
     p[2].AddChildren(self.BuildTrue('STATIC'))
     p[0] = p[2]
 
-  # [41]
+  # [38]
   def p_StaticMemberRest(self, p):
     """StaticMemberRest : AttributeRest
                         | ReturnType OperationRest"""
@@ -480,33 +482,44 @@
       p[2].AddChildren(p[1])
       p[0] = p[2]
 
-  # [42]
-  def p_Attribute(self, p):
-    """Attribute : Inherit AttributeRest"""
+  # [39] NOT IMPLEMENTED (ReadOnlyMember)
+  # [40] NOT IMPLEMENTED (ReadOnlyMemberReset)
+
+  # [41]
+  def p_ReadWriteAttribute(self, p):
+    """ReadWriteAttribute : Inherit AttributeRest"""
     p[2].AddChildren(ListFromConcat(p[1]))
     p[0] = p[2]
 
-  # [43]
+  # [41] Deprecated - Remove this entry after blink stops using it.
+  def p_Attribute(self, p):
+    """Attribute : ReadWriteAttribute"""
+    p[0] = p[1]
+
+  # [42]
   def p_AttributeRest(self, p):
     """AttributeRest : ReadOnly ATTRIBUTE Type identifier ';'"""
     p[0] = self.BuildNamed('Attribute', p, 4,
                            ListFromConcat(p[1], p[3]))
 
-  # [44]
+  # [43] NOT IMPLEMENTED (AttributeName)
+  # [44] NOT IMPLEMENTED (AttributeNameKeyword)
+
+  # [45]
   def p_Inherit(self, p):
     """Inherit : INHERIT
                |"""
     if len(p) > 1:
       p[0] = self.BuildTrue('INHERIT')
 
-  # [45]
+  # [46]
   def p_ReadOnly(self, p):
     """ReadOnly : READONLY
                 |"""
     if len(p) > 1:
       p[0] = self.BuildTrue('READONLY')
 
-  # [46]
+  # [47]
   def p_OperationOrIterator(self, p):
     """OperationOrIterator : ReturnType OperationOrIteratorRest
                            | SpecialOperation"""
@@ -516,20 +529,20 @@
     else:
       p[0] = p[1]
 
-  # [47]
+  # [48]
   def p_SpecialOperation(self, p):
     """SpecialOperation : Special Specials ReturnType OperationRest"""
     p[4].AddChildren(ListFromConcat(p[1], p[2], p[3]))
     p[0] = p[4]
 
-  # [48]
+  # [49]
   def p_Specials(self, p):
     """Specials : Special Specials
                 | """
     if len(p) > 1:
       p[0] = ListFromConcat(p[1], p[2])
 
-  # [49]
+  # [50]
   def p_Special(self, p):
     """Special : GETTER
                | SETTER
@@ -538,20 +551,18 @@
                | LEGACYCALLER"""
     p[0] = self.BuildTrue(p[1].upper())
 
-  # [50] Removed unsupported: IteratorRest
+  # [51]
   def p_OperationOrIteratorRest(self, p):
     """OperationOrIteratorRest : OperationRest"""
     p[0] = p[1]
 
-  # [51-53] NOT IMPLEMENTED (IteratorRest)
-
-  # [54]
+  # [51]
   def p_OperationRest(self, p):
     """OperationRest : OptionalIdentifier '(' ArgumentList ')' ';'"""
     arguments = self.BuildProduction('Arguments', p, 2, p[3])
     p[0] = self.BuildNamed('Operation', p, 1, arguments)
 
-  # [55]
+  # [52]
   def p_OptionalIdentifier(self, p):
     """OptionalIdentifier : identifier
                           |"""
@@ -560,32 +571,32 @@
     else:
       p[0] = '_unnamed_'
 
-  # [56]
+  # [53]
   def p_ArgumentList(self, p):
     """ArgumentList : Argument Arguments
                     |"""
     if len(p) > 1:
       p[0] = ListFromConcat(p[1], p[2])
 
-  # [56.1] ArgumentList error recovery
+  # [53.1] ArgumentList error recovery
   def p_ArgumentListError(self, p):
     """ArgumentList : error """
     p[0] = self.BuildError(p, 'ArgumentList')
 
-  # [57]
+  # [54]
   def p_Arguments(self, p):
     """Arguments : ',' Argument Arguments
                  |"""
     if len(p) > 1:
       p[0] = ListFromConcat(p[2], p[3])
 
-  # [58]
+  # [55]
   def p_Argument(self, p):
     """Argument : ExtendedAttributeList OptionalOrRequiredArgument"""
     p[2].AddChildren(p[1])
     p[0] = p[2]
 
-  # [59]
+  # [56]
   def p_OptionalOrRequiredArgument(self, p):
     """OptionalOrRequiredArgument : OPTIONAL Type ArgumentName Default
                                   | Type Ellipsis ArgumentName"""
@@ -596,13 +607,13 @@
       arg = self.BuildNamed('Argument', p, 3, ListFromConcat(p[1], p[2]))
     p[0] = arg
 
-  # [60]
+  # [57]
   def p_ArgumentName(self, p):
     """ArgumentName : ArgumentNameKeyword
                     | identifier"""
     p[0] = p[1]
 
-  # [61]
+  # [58]
   def p_Ellipsis(self, p):
     """Ellipsis : ELLIPSIS
                 |"""
@@ -610,23 +621,30 @@
       p[0] = self.BuildNamed('Argument', p, 1)
       p[0].AddChildren(self.BuildTrue('ELLIPSIS'))
 
-  # [62]
+  # [] Unspecified
   def p_ExceptionMember(self, p):
     """ExceptionMember : Const
                        | ExceptionField"""
     p[0] = p[1]
 
-  # [63]
+  # [] Unspecified
   def p_ExceptionField(self, p):
     """ExceptionField : Type identifier ';'"""
     p[0] = self.BuildNamed('ExceptionField', p, 2, p[1])
 
-  # [63.1] Error recovery for ExceptionMembers
+  # [] Error recovery for ExceptionMembers - Unspecified
   def p_ExceptionFieldError(self, p):
     """ExceptionField : error"""
     p[0] = self.BuildError(p, 'ExceptionField')
 
-  # [64] No comment version for mid statement attributes.
+  # [59] NOT IMPLEMENTED (Iterable)
+  # [60] NOT IMPLEMENTED (OptionalType)
+  # [61] NOT IMPLEMENTED (ReadWriteMaplike)
+  # [62] NOT IMPLEMENTED (ReadWriteSetlike)
+  # [63] NOT IMPLEMENTED (MaplikeRest)
+  # [64] NOT IMPLEMENTED (SetlikeRest)
+
+  # [65] No comment version for mid statement attributes.
   def p_ExtendedAttributeListNoComments(self, p):
     """ExtendedAttributeListNoComments : '[' ExtendedAttribute ExtendedAttributes ']'
                                        | """
@@ -634,7 +652,7 @@
       items = ListFromConcat(p[2], p[3])
       p[0] = self.BuildProduction('ExtAttributes', p, 1, items)
 
-  # [64.1] Add optional comment field for start of statements.
+  # [65.1] Add optional comment field for start of statements.
   def p_ExtendedAttributeList(self, p):
     """ExtendedAttributeList : Comments '[' ExtendedAttribute ExtendedAttributes ']'
                              | Comments """
@@ -645,7 +663,7 @@
     else:
       p[0] = p[1]
 
-  # [65]
+  # [66]
   def p_ExtendedAttributes(self, p):
     """ExtendedAttributes : ',' ExtendedAttribute ExtendedAttributes
                           |"""
@@ -668,7 +686,7 @@
                          | ExtendedAttributeNamedArgList"""
     p[0] = p[1]
 
-  # [70]
+  # [71]
   def p_ArgumentNameKeyword(self, p):
     """ArgumentNameKeyword : ATTRIBUTE
                            | CALLBACK
@@ -691,7 +709,9 @@
                            | UNRESTRICTED"""
     p[0] = p[1]
 
-  # [72]
+  # [72] NOT IMPLEMENTED (OtherOrComma)
+
+  # [73]
   def p_Type(self, p):
     """Type : SingleType
             | UnionType TypeSuffix"""
@@ -700,7 +720,7 @@
     else:
       p[0] = self.BuildProduction('Type', p, 1, ListFromConcat(p[1], p[2]))
 
-  # [73]
+  # [74]
   def p_SingleType(self, p):
     """SingleType : NonAnyType
                   | ANY TypeSuffixStartingWithArray"""
@@ -709,26 +729,27 @@
     else:
       p[0] = ListFromConcat(self.BuildProduction('Any', p, 1), p[2])
 
-  # [74]
+  # [75]
   def p_UnionType(self, p):
     """UnionType : '(' UnionMemberType OR UnionMemberType UnionMemberTypes ')'"""
 
-  # [75]
+  # [76]
   def p_UnionMemberType(self, p):
     """UnionMemberType : NonAnyType
                        | UnionType TypeSuffix
                        | ANY '[' ']' TypeSuffix"""
-  # [76]
+  # [77]
   def p_UnionMemberTypes(self, p):
     """UnionMemberTypes : OR UnionMemberType UnionMemberTypes
                         |"""
 
-  # [77] Moved BYTESTRING, DOMSTRING, OBJECT, DATE, REGEXP to PrimitiveType
+  # [78] Moved BYTESTRING, DOMSTRING, OBJECT, DATE, REGEXP to PrimitiveType
   # Moving all built-in types into PrimitiveType makes it easier to
   # differentiate between them and 'identifier', since p[1] would be a string in
   # both cases.
   def p_NonAnyType(self, p):
     """NonAnyType : PrimitiveType TypeSuffix
+                  | PromiseType Null
                   | identifier TypeSuffix
                   | SEQUENCE '<' Type '>' Null"""
     if len(p) == 3:
@@ -741,8 +762,9 @@
     if len(p) == 6:
       p[0] = self.BuildProduction('Sequence', p, 1, ListFromConcat(p[3], p[5]))
 
+  # [79] NOT IMPLEMENTED (BufferRelatedType)
 
-  # [78]
+  # [80]
   def p_ConstType(self,  p):
     """ConstType : PrimitiveType Null
                  | identifier Null"""
@@ -753,7 +775,7 @@
       p[0] = p[1]
 
 
-  # [79] Added BYTESTRING, DOMSTRING, OBJECT, DATE, REGEXP
+  # [81] Added BYTESTRING, DOMSTRING, OBJECT, DATE, REGEXP
   def p_PrimitiveType(self, p):
     """PrimitiveType : UnsignedIntegerType
                      | UnrestrictedFloatType
@@ -771,7 +793,7 @@
       p[0] = p[1]
 
 
-  # [80]
+  # [82]
   def p_UnrestrictedFloatType(self, p):
     """UnrestrictedFloatType : UNRESTRICTED FloatType
                              | FloatType"""
@@ -783,13 +805,13 @@
     p[0] = typeref
 
 
-  # [81]
+  # [83]
   def p_FloatType(self, p):
     """FloatType : FLOAT
                  | DOUBLE"""
     p[0] = p[1]
 
-  # [82]
+  # [84]
   def p_UnsignedIntegerType(self, p):
     """UnsignedIntegerType : UNSIGNED IntegerType
                            | IntegerType"""
@@ -798,7 +820,7 @@
     else:
       p[0] = 'unsigned ' + p[2]
 
-  # [83]
+  # [85]
   def p_IntegerType(self, p):
     """IntegerType : SHORT
                    | LONG OptionalLong"""
@@ -807,7 +829,7 @@
     else:
       p[0] = p[1] + p[2]
 
-  # [84]
+  # [86]
   def p_OptionalLong(self, p):
     """OptionalLong : LONG
                     | """
@@ -816,8 +838,21 @@
     else:
       p[0] = ''
 
+  # [87] Add unqualified Promise
+  def p_PromiseType(self, p):
+    """PromiseType : PROMISE '<' ReturnType '>'
+                   | PROMISE"""
+    if len(p) == 2:
+      # Promise without resolution type is not specified in the Web IDL spec.
+      # As it is used in some specs and in the blink implementation,
+      # we allow that here.
+      resolution_type = self.BuildProduction('Type', p, 1,
+                                             self.BuildProduction('Any', p, 1))
+      p[0] = self.BuildNamed('Promise', p, 1, resolution_type)
+    else:
+      p[0] = self.BuildNamed('Promise', p, 1, p[3])
 
-  # [85] Add support for sized array
+  # [88] Add support for sized array
   def p_TypeSuffix(self, p):
     """TypeSuffix : '[' integer ']' TypeSuffix
                   | '[' ']' TypeSuffix
@@ -833,21 +868,21 @@
       p[0] = ListFromConcat(self.BuildTrue('NULLABLE'), p[2])
 
 
-  # [86]
+  # [89]
   def p_TypeSuffixStartingWithArray(self, p):
     """TypeSuffixStartingWithArray : '[' ']' TypeSuffix
                                    | """
     if len(p) > 1:
       p[0] = self.BuildProduction('Array', p, 0, p[3])
 
-  # [87]
+  # [90]
   def p_Null(self, p):
     """Null : '?'
             |"""
     if len(p) > 1:
       p[0] = self.BuildTrue('NULLABLE')
 
-  # [88]
+  # [91]
   def p_ReturnType(self, p):
     """ReturnType : Type
                   | VOID"""
@@ -857,50 +892,48 @@
     else:
       p[0] = p[1]
 
-  # [89]
+  # [92]
   def p_IdentifierList(self, p):
     """IdentifierList : identifier Identifiers"""
     p[0] = ListFromConcat(p[1], p[2])
 
-  # [90]
+  # [93]
   def p_Identifiers(self, p):
     """Identifiers : ',' identifier Identifiers
                    |"""
     if len(p) > 1:
       p[0] = ListFromConcat(p[2], p[3])
 
-  # [91]
+  # [94]
   def p_ExtendedAttributeNoArgs(self, p):
     """ExtendedAttributeNoArgs : identifier"""
     p[0] = self.BuildNamed('ExtAttribute', p, 1)
 
-  # [92]
+  # [95]
   def p_ExtendedAttributeArgList(self, p):
     """ExtendedAttributeArgList : identifier '(' ArgumentList ')'"""
     arguments = self.BuildProduction('Arguments', p, 2, p[3])
     p[0] = self.BuildNamed('ExtAttribute', p, 1, arguments)
 
-  # [93]
+  # [96]
   def p_ExtendedAttributeIdent(self, p):
     """ExtendedAttributeIdent : identifier '=' identifier"""
     value = self.BuildAttribute('VALUE', p[3])
     p[0] = self.BuildNamed('ExtAttribute', p, 1, value)
 
-  # [94]
+  # [97]
   def p_ExtendedAttributeIdentList(self, p):
     """ExtendedAttributeIdentList : identifier '=' '(' IdentifierList ')'"""
     value = self.BuildAttribute('VALUE', p[4])
     p[0] = self.BuildNamed('ExtAttribute', p, 1, value)
 
-  # [95]
+  # [98]
   def p_ExtendedAttributeNamedArgList(self, p):
     """ExtendedAttributeNamedArgList : identifier '=' identifier '(' ArgumentList ')'"""
     args = self.BuildProduction('Arguments', p, 4, p[5])
     value = self.BuildNamed('Call', p, 3, args)
     p[0] = self.BuildNamed('ExtAttribute', p, 1, value)
 
-  # [96] NOT IMPLEMENTED (ExtendedAttributeTypePair)
-
 #
 # Parser Errors
 #
diff --git a/tools/idl_parser/idl_ppapi_lexer.py b/tools/idl_parser/idl_ppapi_lexer.py
index 3d5d39e..ac6f42c 100755
--- a/tools/idl_parser/idl_ppapi_lexer.py
+++ b/tools/idl_parser/idl_ppapi_lexer.py
@@ -59,8 +59,8 @@
 
     # Remove JS types
     self._DelKeywords(['boolean', 'byte', 'ByteString', 'Date', 'DOMString',
-                       'double', 'float', 'long', 'object', 'octet', 'RegExp',
-                       'short', 'unsigned'])
+                       'double', 'float', 'long', 'object', 'octet', 'Promise',
+                       'RegExp', 'short', 'unsigned'])
 
 
 # If run by itself, attempt to build the lexer
diff --git a/tools/idl_parser/idl_ppapi_parser.py b/tools/idl_parser/idl_ppapi_parser.py
index 07963ea..094df72 100755
--- a/tools/idl_parser/idl_ppapi_parser.py
+++ b/tools/idl_parser/idl_ppapi_parser.py
@@ -124,18 +124,15 @@
     """StructMember : ExtendedAttributeList Type identifier ';'"""
     p[0] = self.BuildNamed('Member', p, 3, ListFromConcat(p[1], p[2]))
 
-  # [24]
   def p_Typedef(self, p):
     """Typedef : TYPEDEF ExtendedAttributeListNoComments Type identifier ';'"""
     p[0] = self.BuildNamed('Typedef', p, 4, ListFromConcat(p[2], p[3]))
 
-  # [24.1]
   def p_TypedefFunc(self, p):
     """Typedef : TYPEDEF ExtendedAttributeListNoComments ReturnType identifier '(' ArgumentList ')' ';'"""
     args = self.BuildProduction('Arguments', p, 5, p[6])
     p[0] = self.BuildNamed('Callback', p, 4, ListFromConcat(p[2], p[3], args))
 
-  # [27]
   def p_ConstValue(self, p):
     """ConstValue : integer
                   | integer LSHIFT integer
@@ -157,12 +154,10 @@
                   | BooleanLiteral """
     p[0] = p[1]
 
-  # [21]
   def p_EnumValueList(self, p):
     """EnumValueList : EnumValue EnumValues"""
     p[0] = ListFromConcat(p[1], p[2])
 
-  # [22]
   def p_EnumValues(self, p):
     """EnumValues : ',' EnumValue EnumValues
                   |"""
@@ -176,6 +171,13 @@
     if len(p) > 3:
       p[0].AddChildren(p[4])
 
+  # Omit PromiseType, as it is a JS type.
+  def p_NonAnyType(self, p):
+    """NonAnyType : PrimitiveType TypeSuffix
+                  | identifier TypeSuffix
+                  | SEQUENCE '<' Type '>' Null"""
+    IDLParser.p_NonAnyType(self, p)
+
   def p_PrimitiveType(self, p):
     """PrimitiveType : IntegerType
                      | UnsignedIntegerType
@@ -200,13 +202,11 @@
                   | PP_FILEHANDLE"""
     p[0] = p[1]
 
-  # [66]
   def p_FloatType(self, p):
     """FloatType : FLOAT_T
                  | DOUBLE_T"""
     p[0] = p[1]
 
-  # [67]
   def p_UnsignedIntegerType(self, p):
     """UnsignedIntegerType : UINT8_T
                            | UINT16_T
@@ -215,7 +215,6 @@
     p[0] = p[1]
 
 
-  # [68]
   def p_IntegerType(self, p):
     """IntegerType : CHAR
                    | INT8_T
@@ -237,6 +236,10 @@
     """ """
     pass
 
+  def p_PromiseType(self, p):
+    """ """
+    pass
+
   # We only support:
   #    [ identifier ]
   #    [ identifier ( ArgumentList )]
@@ -272,7 +275,6 @@
     if len(p) > 1:
       p[0] = p[1]
 
-  # [76]
   def p_ExtendedAttributeIdentConst(self, p):
     """ExtendedAttributeIdentConst : identifier '=' ConstValue"""
     p[0] = self.BuildNamed('ExtAttribute', p, 1, p[3])
diff --git a/tools/idl_parser/test_parser/interface_web.idl b/tools/idl_parser/test_parser/interface_web.idl
index 8d41e91..09a2902 100644
--- a/tools/idl_parser/test_parser/interface_web.idl
+++ b/tools/idl_parser/test_parser/interface_web.idl
@@ -181,3 +181,37 @@
 interface MyExtendedAttributeInterface {
   [Attr, MethodIdentList=(Foo, Bar)] void method();
 };
+
+/* TREE
+ *Interface(MyIfacePromise)
+ *  Operation(method1)
+ *    Arguments()
+ *    Type()
+ *      Promise(Promise)
+ *        Type()
+ *          PrimitiveType(void)
+ *  Operation(method2)
+ *    Arguments()
+ *    Type()
+ *      Promise(Promise)
+ *        Type()
+ *          PrimitiveType(long)
+ *  Operation(method3)
+ *    Arguments()
+ *    Type()
+ *      Promise(Promise)
+ *        Type()
+ *          Any()
+ *  Operation(method4)
+ *    Arguments()
+ *    Type()
+ *      Promise(Promise)
+ *        Type()
+ *          Any()
+ */
+interface MyIfacePromise {
+  Promise<void> method1();
+  Promise<long> method2();
+  Promise<any> method3();
+  Promise method4();
+};
diff --git a/tools/idl_parser/test_parser/struct_ppapi.idl b/tools/idl_parser/test_parser/struct_ppapi.idl
index dd017ac..59bc7eb 100644
--- a/tools/idl_parser/test_parser/struct_ppapi.idl
+++ b/tools/idl_parser/test_parser/struct_ppapi.idl
@@ -42,6 +42,9 @@
  *      ExtAttribute(fake_attribute)
  *    Type()
  *      PrimitiveType(str_t)
+ *  Member(z)
+ *    Type()
+ *      Typeref(Promise)
  *  ExtAttributes()
  *    ExtAttribute(union)
  */
@@ -49,4 +52,5 @@
   uint32_t x;
   uint64_t y;
   [fake_attribute] str_t string;
+  Promise z;
 };
diff --git a/tools/valgrind/drmemory/suppressions_full.txt b/tools/valgrind/drmemory/suppressions_full.txt
index 544e5a6..ebe6a15 100644
--- a/tools/valgrind/drmemory/suppressions_full.txt
+++ b/tools/valgrind/drmemory/suppressions_full.txt
@@ -1860,3 +1860,7 @@
 ppapi_proxy.dll!ppapi::CallWhileUnlocked<>
 ppapi_proxy.dll!ppapi::proxy::PPP_InputEvent_Proxy::OnMsgHandleFilteredInputEvent
 
+UNADDRESSABLE ACCESS
+name=bug_425097
+...
+*!ash::test::ShelfViewTest_CheckDragAndDropFromOverflowBubbleToShelf_Test::TestBody
diff --git a/ui/android/java/src/org/chromium/ui/base/LocalizationUtils.java b/ui/android/java/src/org/chromium/ui/base/LocalizationUtils.java
index becf1f4..8deeb47 100644
--- a/ui/android/java/src/org/chromium/ui/base/LocalizationUtils.java
+++ b/ui/android/java/src/org/chromium/ui/base/LocalizationUtils.java
@@ -11,7 +11,6 @@
 import org.chromium.base.ApplicationStatus;
 import org.chromium.base.CalledByNative;
 import org.chromium.base.JNINamespace;
-import org.chromium.base.LocaleUtils;
 
 import java.util.Locale;
 
@@ -30,16 +29,6 @@
 
     private LocalizationUtils() { /* cannot be instantiated */ }
 
-    /**
-     * @return the default locale, translating Android deprecated
-     * language codes into the modern ones used by Chromium.
-     */
-    @CalledByNative
-    public static String getDefaultLocale() {
-        // TODO(vivekg): Native callers should use LocaleUtils directly instead of the redirection.
-        return LocaleUtils.getDefaultLocale();
-    }
-
     @CalledByNative
     private static Locale getJavaLocale(String language, String country, String variant) {
         return new Locale(language, country, variant);
diff --git a/ui/app_list/app_list_switches.cc b/ui/app_list/app_list_switches.cc
index ec2ea1c..ea10c7c 100644
--- a/ui/app_list/app_list_switches.cc
+++ b/ui/app_list/app_list_switches.cc
@@ -16,6 +16,11 @@
 // If set, the app info context menu item is not available in the app list UI.
 const char kDisableAppInfo[] = "disable-app-list-app-info";
 
+// If set, the app list will not be dismissed when it loses focus. This is
+// useful when testing the app list or a custom launcher page. It can still be
+// dismissed via the other methods (like the Esc key).
+const char kDisableAppListDismissOnBlur[] = "disable-app-list-dismiss-on-blur";
+
 // If set, Drive apps will not be shown side-by-side with Chrome apps.
 const char kDisableDriveAppsInAppList[] = "disable-drive-apps-in-app-list";
 
@@ -76,6 +81,11 @@
          IsExperimentalAppListEnabled();
 }
 
+bool ShouldNotDismissOnBlur() {
+  return CommandLine::ForCurrentProcess()->HasSwitch(
+      kDisableAppListDismissOnBlur);
+}
+
 bool IsDriveAppsInAppListEnabled() {
 #if defined(OS_CHROMEOS)
   return !CommandLine::ForCurrentProcess()->HasSwitch(
diff --git a/ui/app_list/app_list_switches.h b/ui/app_list/app_list_switches.h
index c5c95f4..094040c 100644
--- a/ui/app_list/app_list_switches.h
+++ b/ui/app_list/app_list_switches.h
@@ -13,6 +13,7 @@
 // Please keep these flags sorted.
 APP_LIST_EXPORT extern const char kCustomLauncherPage[];
 APP_LIST_EXPORT extern const char kDisableAppInfo[];
+APP_LIST_EXPORT extern const char kDisableAppListDismissOnBlur[];
 APP_LIST_EXPORT extern const char kDisableDriveAppsInAppList[];
 APP_LIST_EXPORT extern const char kDisableSyncAppList[];
 APP_LIST_EXPORT extern const char kEnableCenteredAppList[];
@@ -36,6 +37,9 @@
 // the conditions that trigger the position.
 bool APP_LIST_EXPORT IsCenteredAppListEnabled();
 
+// Determines whether the app list should not be dismissed on focus loss.
+bool APP_LIST_EXPORT ShouldNotDismissOnBlur();
+
 bool APP_LIST_EXPORT IsDriveAppsInAppListEnabled();
 
 }  // namespace switches
diff --git a/ui/app_list/test/run_all_unittests.cc b/ui/app_list/test/run_all_unittests.cc
index 19f0a0c..bd03d4f 100644
--- a/ui/app_list/test/run_all_unittests.cc
+++ b/ui/app_list/test/run_all_unittests.cc
@@ -12,7 +12,9 @@
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/base/ui_base_paths.h"
 
-#if !defined(OS_MACOSX)
+#if defined(OS_MACOSX)
+#include "base/test/mock_chrome_application_mac.h"
+#else
 #include "ui/gl/gl_surface.h"
 #endif
 
@@ -24,7 +26,9 @@
 
  protected:
   virtual void Initialize() override {
-#if !defined(OS_MACOSX)
+#if defined(OS_MACOSX)
+    mock_cr_app::RegisterMockCrApp();
+#else
     gfx::GLSurface::InitializeOneOffForTests();
 #endif
     base::TestSuite::Initialize();
diff --git a/ui/app_list/views/apps_grid_view.cc b/ui/app_list/views/apps_grid_view.cc
index 474b6ef..2c277a5 100644
--- a/ui/app_list/views/apps_grid_view.cc
+++ b/ui/app_list/views/apps_grid_view.cc
@@ -1178,6 +1178,11 @@
 }
 
 void AppsGridView::CalculateIdealBounds() {
+  // TODO(calamity): This fixes http://crbug.com/422604 on ChromeOS but it's
+  // unclear why. This should be investigated to fix the issue on Linux Ash.
+  if (GetContentsBounds().IsEmpty())
+    return;
+
   gfx::Size grid_size = GetTileGridSize();
 
   // Page size including padding pixels. A tile.x + page_width means the same
diff --git a/ui/base/l10n/l10n_util.cc b/ui/base/l10n/l10n_util.cc
index 9db2206..bcc070a 100644
--- a/ui/base/l10n/l10n_util.cc
+++ b/ui/base/l10n/l10n_util.cc
@@ -33,6 +33,7 @@
 #include "ui/base/ui_base_paths.h"
 
 #if defined(OS_ANDROID)
+#include "base/android/locale_utils.h"
 #include "ui/base/l10n/l10n_util_android.h"
 #endif
 
@@ -447,7 +448,7 @@
 #elif defined(OS_ANDROID)
 
   // On Android, query java.util.Locale for the default locale.
-  candidates.push_back(GetDefaultLocale());
+  candidates.push_back(base::android::GetDefaultLocale());
 
 #elif defined(USE_GLIB) && !defined(OS_CHROMEOS)
 
diff --git a/ui/base/l10n/l10n_util_android.cc b/ui/base/l10n/l10n_util_android.cc
index 154b675..8530fcd 100644
--- a/ui/base/l10n/l10n_util_android.cc
+++ b/ui/base/l10n/l10n_util_android.cc
@@ -23,13 +23,6 @@
       base::android::ConvertJavaStringToUTF16(env, string));
 }
 
-std::string GetDefaultLocale() {
-  JNIEnv* env = base::android::AttachCurrentThread();
-  ScopedJavaLocalRef<jstring> locale = Java_LocalizationUtils_getDefaultLocale(
-      env);
-  return ConvertJavaStringToUTF8(locale);
-}
-
 bool IsLayoutRtl() {
   static bool is_layout_rtl_cached = false;
   static bool layout_rtl_cache;
diff --git a/ui/base/l10n/l10n_util_android.h b/ui/base/l10n/l10n_util_android.h
index c8cf4bb..3745ed6 100644
--- a/ui/base/l10n/l10n_util_android.h
+++ b/ui/base/l10n/l10n_util_android.h
@@ -14,9 +14,6 @@
 
 namespace l10n_util {
 
-// Return the current default locale of the device.
-UI_BASE_EXPORT std::string GetDefaultLocale();
-
 UI_BASE_EXPORT base::string16 GetDisplayNameForLocale(
     const std::string& locale,
     const std::string& display_locale);
diff --git a/ui/base/test/run_all_unittests.cc b/ui/base/test/run_all_unittests.cc
index 1254d97..7e14b52 100644
--- a/ui/base/test/run_all_unittests.cc
+++ b/ui/base/test/run_all_unittests.cc
@@ -19,6 +19,7 @@
 
 #if defined(OS_MACOSX) && !defined(OS_IOS)
 #include "base/mac/bundle_locations.h"
+#include "base/test/mock_chrome_application_mac.h"
 #endif
 
 #if defined(OS_WIN)
@@ -62,6 +63,8 @@
   PathService::Get(base::DIR_EXE, &exe_path);
 
 #if defined(OS_MACOSX) && !defined(OS_IOS)
+  mock_cr_app::RegisterMockCrApp();
+
   // On Mac, a test Framework bundle is created that links locale.pak and
   // chrome_100_percent.pak at the appropriate places to ui_test.pak.
   base::mac::SetOverrideFrameworkBundlePath(
diff --git a/ui/base/test/ui_controls.h b/ui/base/test/ui_controls.h
index 971e8f8..e54f936 100644
--- a/ui/base/test/ui_controls.h
+++ b/ui/base/test/ui_controls.h
@@ -97,6 +97,13 @@
 void InstallUIControlsAura(UIControlsAura* instance);
 #endif
 
+#if defined(OS_MACOSX)
+// Returns true when tests need to use extra Tab and Shift-Tab key events
+// to traverse to the desired item; because the application is configured to
+// traverse more elements for accessibility reasons.
+bool IsFullKeyboardAccessEnabled();
+#endif
+
 }  // namespace ui_controls
 
 #endif  // UI_BASE_TEST_UI_CONTROLS_H_
diff --git a/ui/base/test/ui_controls_mac.mm b/ui/base/test/ui_controls_mac.mm
index f608f21..cf2c239 100644
--- a/ui/base/test/ui_controls_mac.mm
+++ b/ui/base/test/ui_controls_mac.mm
@@ -389,4 +389,8 @@
       FROM_HERE, base::Bind(&EventQueueWatcher, closure));
 }
 
+bool IsFullKeyboardAccessEnabled() {
+  return [NSApp isFullKeyboardAccessEnabled];
+}
+
 }  // namespace ui_controls
diff --git a/ui/events/ozone/evdev/event_factory_evdev.cc b/ui/events/ozone/evdev/event_factory_evdev.cc
index 5499339..e87acbf 100644
--- a/ui/events/ozone/evdev/event_factory_evdev.cc
+++ b/ui/events/ozone/evdev/event_factory_evdev.cc
@@ -48,6 +48,7 @@
 
   // State shared between devices. Must not be dereferenced on worker thread.
   EventModifiersEvdev* modifiers;
+  KeyboardEvdev* keyboard;
   CursorDelegateEvdev* cursor;
 };
 
@@ -71,11 +72,13 @@
   // Touchpad or mouse: use gestures library.
   // EventReaderLibevdevCros -> GestureInterpreterLibevdevCros -> DispatchEvent
   if (UseGesturesLibraryForDevice(devinfo)) {
-    scoped_ptr<GestureInterpreterLibevdevCros> gesture_interp =
-        make_scoped_ptr(new GestureInterpreterLibevdevCros(
-            params.modifiers, params.cursor, params.dispatch_callback));
+    scoped_ptr<GestureInterpreterLibevdevCros> gesture_interp = make_scoped_ptr(
+        new GestureInterpreterLibevdevCros(params.modifiers,
+                                           params.cursor,
+                                           params.keyboard,
+                                           params.dispatch_callback));
     return make_scoped_ptr(new EventReaderLibevdevCros(
-        fd, params.path, params.id, gesture_interp.Pass()));
+          fd, params.path, params.id, gesture_interp.Pass()));
   }
 #endif
 
@@ -86,8 +89,8 @@
         fd, params.path, params.id, devinfo, params.dispatch_callback));
 
   // Everything else: use KeyEventConverterEvdev.
-  return make_scoped_ptr<EventConverterEvdev>(new KeyEventConverterEvdev(
-      fd, params.path, params.id, params.modifiers, params.dispatch_callback));
+  return make_scoped_ptr<EventConverterEvdev>(
+      new KeyEventConverterEvdev(fd, params.path, params.id, params.keyboard));
 }
 
 // Open an input device. Opening may put the calling thread to sleep, and
@@ -146,10 +149,11 @@
                                      DeviceManager* device_manager)
     : last_device_id_(0),
       device_manager_(device_manager),
-      cursor_(cursor),
       dispatch_callback_(
           base::Bind(base::IgnoreResult(&EventFactoryEvdev::DispatchUiEvent),
                      base::Unretained(this))),
+      keyboard_(&modifiers_, dispatch_callback_),
+      cursor_(cursor),
       weak_ptr_factory_(this) {
   DCHECK(device_manager_);
 }
@@ -193,6 +197,7 @@
       params->path = event.path();
       params->dispatch_callback = dispatch_callback_;
       params->modifiers = &modifiers_;
+      params->keyboard = &keyboard_;
       params->cursor = cursor_;
 
       OpenInputDeviceReplyCallback reply_callback =
diff --git a/ui/events/ozone/evdev/event_factory_evdev.h b/ui/events/ozone/evdev/event_factory_evdev.h
index 806ec29..c1998a6 100644
--- a/ui/events/ozone/evdev/event_factory_evdev.h
+++ b/ui/events/ozone/evdev/event_factory_evdev.h
@@ -14,6 +14,7 @@
 #include "ui/events/ozone/evdev/event_converter_evdev.h"
 #include "ui/events/ozone/evdev/event_modifiers_evdev.h"
 #include "ui/events/ozone/evdev/events_ozone_evdev_export.h"
+#include "ui/events/ozone/evdev/keyboard_evdev.h"
 #include "ui/events/platform/platform_event_source.h"
 #include "ui/gfx/native_widget_types.h"
 
@@ -70,15 +71,18 @@
   // Task runner for event dispatch.
   scoped_refptr<base::TaskRunner> ui_task_runner_;
 
+  // Dispatch callback for events.
+  EventDispatchCallback dispatch_callback_;
+
   // Modifier key state (shift, ctrl, etc).
   EventModifiersEvdev modifiers_;
 
+  // Keyboard state.
+  KeyboardEvdev keyboard_;
+
   // Cursor movement.
   CursorDelegateEvdev* cursor_;
 
-  // Dispatch callback for events.
-  EventDispatchCallback dispatch_callback_;
-
   // Support weak pointers for attach & detach callbacks.
   base::WeakPtrFactory<EventFactoryEvdev> weak_ptr_factory_;
 
diff --git a/ui/events/ozone/evdev/key_event_converter_evdev.cc b/ui/events/ozone/evdev/key_event_converter_evdev.cc
index 195b514..1f07eb2 100644
--- a/ui/events/ozone/evdev/key_event_converter_evdev.cc
+++ b/ui/events/ozone/evdev/key_event_converter_evdev.cc
@@ -17,188 +17,13 @@
 
 namespace {
 
-const int kXkbKeycodeOffset = 8;
-
-ui::KeyboardCode KeyboardCodeFromButton(unsigned int code) {
-  static const ui::KeyboardCode kLinuxBaseKeyMap[] = {
-      ui::VKEY_UNKNOWN,            // KEY_RESERVED
-      ui::VKEY_ESCAPE,             // KEY_ESC
-      ui::VKEY_1,                  // KEY_1
-      ui::VKEY_2,                  // KEY_2
-      ui::VKEY_3,                  // KEY_3
-      ui::VKEY_4,                  // KEY_4
-      ui::VKEY_5,                  // KEY_5
-      ui::VKEY_6,                  // KEY_6
-      ui::VKEY_7,                  // KEY_7
-      ui::VKEY_8,                  // KEY_8
-      ui::VKEY_9,                  // KEY_9
-      ui::VKEY_0,                  // KEY_0
-      ui::VKEY_OEM_MINUS,          // KEY_MINUS
-      ui::VKEY_OEM_PLUS,           // KEY_EQUAL
-      ui::VKEY_BACK,               // KEY_BACKSPACE
-      ui::VKEY_TAB,                // KEY_TAB
-      ui::VKEY_Q,                  // KEY_Q
-      ui::VKEY_W,                  // KEY_W
-      ui::VKEY_E,                  // KEY_E
-      ui::VKEY_R,                  // KEY_R
-      ui::VKEY_T,                  // KEY_T
-      ui::VKEY_Y,                  // KEY_Y
-      ui::VKEY_U,                  // KEY_U
-      ui::VKEY_I,                  // KEY_I
-      ui::VKEY_O,                  // KEY_O
-      ui::VKEY_P,                  // KEY_P
-      ui::VKEY_OEM_4,              // KEY_LEFTBRACE
-      ui::VKEY_OEM_6,              // KEY_RIGHTBRACE
-      ui::VKEY_RETURN,             // KEY_ENTER
-      ui::VKEY_CONTROL,            // KEY_LEFTCTRL
-      ui::VKEY_A,                  // KEY_A
-      ui::VKEY_S,                  // KEY_S
-      ui::VKEY_D,                  // KEY_D
-      ui::VKEY_F,                  // KEY_F
-      ui::VKEY_G,                  // KEY_G
-      ui::VKEY_H,                  // KEY_H
-      ui::VKEY_J,                  // KEY_J
-      ui::VKEY_K,                  // KEY_K
-      ui::VKEY_L,                  // KEY_L
-      ui::VKEY_OEM_1,              // KEY_SEMICOLON
-      ui::VKEY_OEM_7,              // KEY_APOSTROPHE
-      ui::VKEY_OEM_3,              // KEY_GRAVE
-      ui::VKEY_SHIFT,              // KEY_LEFTSHIFT
-      ui::VKEY_OEM_5,              // KEY_BACKSLASH
-      ui::VKEY_Z,                  // KEY_Z
-      ui::VKEY_X,                  // KEY_X
-      ui::VKEY_C,                  // KEY_C
-      ui::VKEY_V,                  // KEY_V
-      ui::VKEY_B,                  // KEY_B
-      ui::VKEY_N,                  // KEY_N
-      ui::VKEY_M,                  // KEY_M
-      ui::VKEY_OEM_COMMA,          // KEY_COMMA
-      ui::VKEY_OEM_PERIOD,         // KEY_DOT
-      ui::VKEY_OEM_2,              // KEY_SLASH
-      ui::VKEY_SHIFT,              // KEY_RIGHTSHIFT
-      ui::VKEY_MULTIPLY,           // KEY_KPASTERISK
-      ui::VKEY_MENU,               // KEY_LEFTALT
-      ui::VKEY_SPACE,              // KEY_SPACE
-      ui::VKEY_CAPITAL,            // KEY_CAPSLOCK
-      ui::VKEY_F1,                 // KEY_F1
-      ui::VKEY_F2,                 // KEY_F2
-      ui::VKEY_F3,                 // KEY_F3
-      ui::VKEY_F4,                 // KEY_F4
-      ui::VKEY_F5,                 // KEY_F5
-      ui::VKEY_F6,                 // KEY_F6
-      ui::VKEY_F7,                 // KEY_F7
-      ui::VKEY_F8,                 // KEY_F8
-      ui::VKEY_F9,                 // KEY_F9
-      ui::VKEY_F10,                // KEY_F10
-      ui::VKEY_NUMLOCK,            // KEY_NUMLOCK
-      ui::VKEY_SCROLL,             // KEY_SCROLLLOCK
-      ui::VKEY_NUMPAD7,            // KEY_KP7
-      ui::VKEY_NUMPAD8,            // KEY_KP8
-      ui::VKEY_NUMPAD9,            // KEY_KP9
-      ui::VKEY_SUBTRACT,           // KEY_KPMINUS
-      ui::VKEY_NUMPAD4,            // KEY_KP4
-      ui::VKEY_NUMPAD5,            // KEY_KP5
-      ui::VKEY_NUMPAD6,            // KEY_KP6
-      ui::VKEY_ADD,                // KEY_KPPLUS
-      ui::VKEY_NUMPAD1,            // KEY_KP1
-      ui::VKEY_NUMPAD2,            // KEY_KP2
-      ui::VKEY_NUMPAD3,            // KEY_KP3
-      ui::VKEY_NUMPAD0,            // KEY_KP0
-      ui::VKEY_DECIMAL,            // KEY_KPDOT
-      ui::VKEY_UNKNOWN,            // (unassigned)
-      ui::VKEY_DBE_DBCSCHAR,       // KEY_ZENKAKUHANKAKU
-      ui::VKEY_OEM_102,            // KEY_102ND
-      ui::VKEY_F11,                // KEY_F11
-      ui::VKEY_F12,                // KEY_F12
-      ui::VKEY_UNKNOWN,            // KEY_RO
-      ui::VKEY_UNKNOWN,            // KEY_KATAKANA
-      ui::VKEY_UNKNOWN,            // KEY_HIRAGANA
-      ui::VKEY_CONVERT,            // KEY_HENKAN
-      ui::VKEY_UNKNOWN,            // KEY_KATAKANAHIRAGANA
-      ui::VKEY_NONCONVERT,         // KEY_MUHENKAN
-      ui::VKEY_UNKNOWN,            // KEY_KPJPCOMMA
-      ui::VKEY_RETURN,             // KEY_KPENTER
-      ui::VKEY_CONTROL,            // KEY_RIGHTCTRL
-      ui::VKEY_DIVIDE,             // KEY_KPSLASH
-      ui::VKEY_PRINT,              // KEY_SYSRQ
-      ui::VKEY_MENU,               // KEY_RIGHTALT
-      ui::VKEY_RETURN,             // KEY_LINEFEED
-      ui::VKEY_HOME,               // KEY_HOME
-      ui::VKEY_UP,                 // KEY_UP
-      ui::VKEY_PRIOR,              // KEY_PAGEUP
-      ui::VKEY_LEFT,               // KEY_LEFT
-      ui::VKEY_RIGHT,              // KEY_RIGHT
-      ui::VKEY_END,                // KEY_END
-      ui::VKEY_DOWN,               // KEY_DOWN
-      ui::VKEY_NEXT,               // KEY_PAGEDOWN
-      ui::VKEY_INSERT,             // KEY_INSERT
-      ui::VKEY_DELETE,             // KEY_DELETE
-      ui::VKEY_UNKNOWN,            // KEY_MACRO
-      ui::VKEY_VOLUME_MUTE,        // KEY_MUTE
-      ui::VKEY_VOLUME_DOWN,        // KEY_VOLUMEDOWN
-      ui::VKEY_VOLUME_UP,          // KEY_VOLUMEUP
-      ui::VKEY_POWER,              // KEY_POWER
-      ui::VKEY_OEM_PLUS,           // KEY_KPEQUAL
-      ui::VKEY_UNKNOWN,            // KEY_KPPLUSMINUS
-      ui::VKEY_PAUSE,              // KEY_PAUSE
-      ui::VKEY_MEDIA_LAUNCH_APP1,  // KEY_SCALE
-      ui::VKEY_DECIMAL,            // KEY_KPCOMMA
-      ui::VKEY_HANGUL,             // KEY_HANGEUL
-      ui::VKEY_HANJA,              // KEY_HANJA
-      ui::VKEY_UNKNOWN,            // KEY_YEN
-      ui::VKEY_LWIN,               // KEY_LEFTMETA
-      ui::VKEY_RWIN,               // KEY_RIGHTMETA
-      ui::VKEY_APPS,               // KEY_COMPOSE
-  };
-
-  if (code < arraysize(kLinuxBaseKeyMap))
-    return kLinuxBaseKeyMap[code];
-
-  LOG(ERROR) << "Unknown key code: " << code;
-  return ui::VKEY_UNKNOWN;
-}
-
-int ModifierFromButton(unsigned int code) {
-  switch (code) {
-    case KEY_CAPSLOCK:
-      return EVDEV_MODIFIER_CAPS_LOCK;
-    case KEY_LEFTSHIFT:
-    case KEY_RIGHTSHIFT:
-      return EVDEV_MODIFIER_SHIFT;
-    case KEY_LEFTCTRL:
-    case KEY_RIGHTCTRL:
-      return EVDEV_MODIFIER_CONTROL;
-    case KEY_LEFTALT:
-    case KEY_RIGHTALT:
-      return EVDEV_MODIFIER_ALT;
-    case BTN_LEFT:
-      return EVDEV_MODIFIER_LEFT_MOUSE_BUTTON;
-    case BTN_MIDDLE:
-      return EVDEV_MODIFIER_MIDDLE_MOUSE_BUTTON;
-    case BTN_RIGHT:
-      return EVDEV_MODIFIER_RIGHT_MOUSE_BUTTON;
-    case KEY_LEFTMETA:
-    case KEY_RIGHTMETA:
-      return EVDEV_MODIFIER_COMMAND;
-    default:
-      return EVDEV_MODIFIER_NONE;
-  }
-}
-
-bool IsLockButton(unsigned int code) { return code == KEY_CAPSLOCK; }
-
 }  // namespace
 
-KeyEventConverterEvdev::KeyEventConverterEvdev(
-    int fd,
-    base::FilePath path,
-    int id,
-    EventModifiersEvdev* modifiers,
-    const EventDispatchCallback& callback)
-    : EventConverterEvdev(fd, path, id),
-      callback_(callback),
-      modifiers_(modifiers) {
-  // TODO(spang): Initialize modifiers using EVIOCGKEY.
+KeyEventConverterEvdev::KeyEventConverterEvdev(int fd,
+                                               base::FilePath path,
+                                               int id,
+                                               KeyboardEvdev* keyboard)
+    : EventConverterEvdev(fd, path, id), keyboard_(keyboard) {
 }
 
 KeyEventConverterEvdev::~KeyEventConverterEvdev() {
@@ -227,37 +52,11 @@
   for (int i = 0; i < count; ++i) {
     const input_event& input = inputs[i];
     if (input.type == EV_KEY) {
-      ConvertKeyEvent(input.code, input.value);
+      keyboard_->OnKeyChange(input.code, input.value != 0);
     } else if (input.type == EV_SYN) {
       // TODO(sadrul): Handle this case appropriately.
     }
   }
 }
 
-void KeyEventConverterEvdev::ConvertKeyEvent(int key, int value) {
-  int down = (value != 0);
-  int repeat = (value == 2);
-  int modifier = ModifierFromButton(key);
-  ui::KeyboardCode code = KeyboardCodeFromButton(key);
-
-  if (!repeat && (modifier != EVDEV_MODIFIER_NONE)) {
-    if (IsLockButton(key)) {
-      // Locking modifier keys: CapsLock.
-      modifiers_->UpdateModifierLock(modifier, down);
-    } else {
-      // Regular modifier keys: Shift, Ctrl, Alt, etc.
-      modifiers_->UpdateModifier(modifier, down);
-    }
-  }
-
-  int flags = modifiers_->GetModifierFlags();
-
-  KeyEvent key_event(
-      down ? ET_KEY_PRESSED : ET_KEY_RELEASED,
-      code,
-      KeycodeConverter::NativeKeycodeToCode(key + kXkbKeycodeOffset),
-      flags);
-  callback_.Run(&key_event);
-}
-
 }  // namespace ui
diff --git a/ui/events/ozone/evdev/key_event_converter_evdev.h b/ui/events/ozone/evdev/key_event_converter_evdev.h
index 9a2f771..f1044fa 100644
--- a/ui/events/ozone/evdev/key_event_converter_evdev.h
+++ b/ui/events/ozone/evdev/key_event_converter_evdev.h
@@ -11,6 +11,7 @@
 #include "ui/events/ozone/evdev/event_converter_evdev.h"
 #include "ui/events/ozone/evdev/event_modifiers_evdev.h"
 #include "ui/events/ozone/evdev/events_ozone_evdev_export.h"
+#include "ui/events/ozone/evdev/keyboard_evdev.h"
 
 struct input_event;
 
@@ -22,8 +23,7 @@
   KeyEventConverterEvdev(int fd,
                          base::FilePath path,
                          int id,
-                         EventModifiersEvdev* modifiers,
-                         const EventDispatchCallback& dispatch);
+                         KeyboardEvdev* keyboard);
   virtual ~KeyEventConverterEvdev();
 
   // EventConverterEvdev:
@@ -32,16 +32,11 @@
   void ProcessEvents(const struct input_event* inputs, int count);
 
  private:
-  // Callback for dispatching events.
-  EventDispatchCallback callback_;
-
-  // Shared modifier state.
-  EventModifiersEvdev* modifiers_;
-
   // Controller for watching the input fd.
   base::MessagePumpLibevent::FileDescriptorWatcher controller_;
 
-  void ConvertKeyEvent(int key, int value);
+  // Shared keyboard state.
+  KeyboardEvdev* keyboard_;
 
   DISALLOW_COPY_AND_ASSIGN(KeyEventConverterEvdev);
 };
diff --git a/ui/events/ozone/evdev/key_event_converter_evdev_unittest.cc b/ui/events/ozone/evdev/key_event_converter_evdev_unittest.cc
index a144bce..fb5a90a 100644
--- a/ui/events/ozone/evdev/key_event_converter_evdev_unittest.cc
+++ b/ui/events/ozone/evdev/key_event_converter_evdev_unittest.cc
@@ -12,6 +12,7 @@
 #include "ui/events/event.h"
 #include "ui/events/keycodes/keyboard_codes.h"
 #include "ui/events/ozone/evdev/key_event_converter_evdev.h"
+#include "ui/events/ozone/evdev/keyboard_evdev.h"
 
 namespace ui {
 
@@ -19,36 +20,19 @@
 
 class MockKeyEventConverterEvdev : public KeyEventConverterEvdev {
  public:
-  MockKeyEventConverterEvdev(int fd, EventModifiersEvdev* modifiers)
-      : KeyEventConverterEvdev(
-            fd,
-            base::FilePath(kTestDevicePath),
-            1,
-            modifiers,
-            base::Bind(&MockKeyEventConverterEvdev::DispatchEventForTest,
-                       base::Unretained(this))) {
+  MockKeyEventConverterEvdev(int fd, KeyboardEvdev* keyboard)
+      : KeyEventConverterEvdev(fd,
+                               base::FilePath(kTestDevicePath),
+                               1,
+                               keyboard) {
     Start();
   }
   virtual ~MockKeyEventConverterEvdev() {};
 
-  unsigned size() { return dispatched_events_.size(); }
-  KeyEvent* event(unsigned index) {
-    DCHECK_GT(dispatched_events_.size(), index);
-    return dispatched_events_[index];
-  }
-
-  void DispatchEventForTest(Event* event);
-
  private:
-  ScopedVector<KeyEvent> dispatched_events_;
-
   DISALLOW_COPY_AND_ASSIGN(MockKeyEventConverterEvdev);
 };
 
-void MockKeyEventConverterEvdev::DispatchEventForTest(Event* event) {
-  dispatched_events_.push_back(new KeyEvent(*static_cast<KeyEvent*>(event)));
-}
-
 }  // namespace ui
 
 // Test fixture.
@@ -66,24 +50,44 @@
     events_in_ = evdev_io[0];
     events_out_ = evdev_io[1];
 
-    modifiers_ = new ui::EventModifiersEvdev();
-    device_ = new ui::MockKeyEventConverterEvdev(events_in_, modifiers_);
+    modifiers_.reset(new ui::EventModifiersEvdev());
+    keyboard_.reset(new ui::KeyboardEvdev(
+        modifiers_.get(),
+        base::Bind(&KeyEventConverterEvdevTest::DispatchEventForTest,
+                   base::Unretained(this))));
+    device_.reset(
+        new ui::MockKeyEventConverterEvdev(events_in_, keyboard_.get()));
   }
   virtual void TearDown() override {
-    delete device_;
-    delete modifiers_;
+    device_.reset();
+    keyboard_.reset();
+    modifiers_.reset();
     close(events_in_);
     close(events_out_);
   }
 
-  ui::MockKeyEventConverterEvdev* device() { return device_; }
-  ui::EventModifiersEvdev* modifiers() { return modifiers_; }
+  ui::MockKeyEventConverterEvdev* device() { return device_.get(); }
+  ui::EventModifiersEvdev* modifiers() { return modifiers_.get(); }
+
+  unsigned size() { return dispatched_events_.size(); }
+  ui::KeyEvent* dispatched_event(unsigned index) {
+    DCHECK_GT(dispatched_events_.size(), index);
+    return dispatched_events_[index];
+  }
 
  private:
+  void DispatchEventForTest(ui::Event* event) {
+    dispatched_events_.push_back(
+        new ui::KeyEvent(*static_cast<ui::KeyEvent*>(event)));
+  }
+
   base::MessageLoopForUI ui_loop_;
 
-  ui::EventModifiersEvdev* modifiers_;
-  ui::MockKeyEventConverterEvdev* device_;
+  scoped_ptr<ui::EventModifiersEvdev> modifiers_;
+  scoped_ptr<ui::KeyboardEvdev> keyboard_;
+  scoped_ptr<ui::MockKeyEventConverterEvdev> device_;
+
+  ScopedVector<ui::KeyEvent> dispatched_events_;
 
   int events_out_;
   int events_in_;
@@ -105,16 +109,16 @@
   };
 
   dev->ProcessEvents(mock_kernel_queue, arraysize(mock_kernel_queue));
-  EXPECT_EQ(2u, dev->size());
+  EXPECT_EQ(2u, size());
 
   ui::KeyEvent* event;
 
-  event = dev->event(0);
+  event = dispatched_event(0);
   EXPECT_EQ(ui::ET_KEY_PRESSED, event->type());
   EXPECT_EQ(ui::VKEY_BACK, event->key_code());
   EXPECT_EQ(0, event->flags());
 
-  event = dev->event(1);
+  event = dispatched_event(1);
   EXPECT_EQ(ui::ET_KEY_RELEASED, event->type());
   EXPECT_EQ(ui::VKEY_BACK, event->key_code());
   EXPECT_EQ(0, event->flags());
@@ -142,26 +146,26 @@
   };
 
   dev->ProcessEvents(mock_kernel_queue, arraysize(mock_kernel_queue));
-  EXPECT_EQ(4u, dev->size());
+  EXPECT_EQ(4u, size());
 
   ui::KeyEvent* event;
 
-  event = dev->event(0);
+  event = dispatched_event(0);
   EXPECT_EQ(ui::ET_KEY_PRESSED, event->type());
   EXPECT_EQ(ui::VKEY_BACK, event->key_code());
   EXPECT_EQ(0, event->flags());
 
-  event = dev->event(1);
+  event = dispatched_event(1);
   EXPECT_EQ(ui::ET_KEY_PRESSED, event->type());
   EXPECT_EQ(ui::VKEY_BACK, event->key_code());
   EXPECT_EQ(0, event->flags());
 
-  event = dev->event(2);
+  event = dispatched_event(2);
   EXPECT_EQ(ui::ET_KEY_PRESSED, event->type());
   EXPECT_EQ(ui::VKEY_BACK, event->key_code());
   EXPECT_EQ(0, event->flags());
 
-  event = dev->event(3);
+  event = dispatched_event(3);
   EXPECT_EQ(ui::ET_KEY_RELEASED, event->type());
   EXPECT_EQ(ui::VKEY_BACK, event->key_code());
   EXPECT_EQ(0, event->flags());
@@ -170,7 +174,7 @@
 TEST_F(KeyEventConverterEvdevTest, NoEvents) {
   ui::MockKeyEventConverterEvdev* dev = device();
   dev->ProcessEvents(NULL, 0);
-  EXPECT_EQ(0u, dev->size());
+  EXPECT_EQ(0u, size());
 }
 
 TEST_F(KeyEventConverterEvdevTest, KeyWithModifier) {
@@ -195,26 +199,26 @@
   };
 
   dev->ProcessEvents(mock_kernel_queue, arraysize(mock_kernel_queue));
-  EXPECT_EQ(4u, dev->size());
+  EXPECT_EQ(4u, size());
 
   ui::KeyEvent* event;
 
-  event = dev->event(0);
+  event = dispatched_event(0);
   EXPECT_EQ(ui::ET_KEY_PRESSED, event->type());
   EXPECT_EQ(ui::VKEY_SHIFT, event->key_code());
   EXPECT_EQ(ui::EF_SHIFT_DOWN, event->flags());
 
-  event = dev->event(1);
+  event = dispatched_event(1);
   EXPECT_EQ(ui::ET_KEY_PRESSED, event->type());
   EXPECT_EQ(ui::VKEY_A, event->key_code());
   EXPECT_EQ(ui::EF_SHIFT_DOWN, event->flags());
 
-  event = dev->event(2);
+  event = dispatched_event(2);
   EXPECT_EQ(ui::ET_KEY_RELEASED, event->type());
   EXPECT_EQ(ui::VKEY_A, event->key_code());
   EXPECT_EQ(ui::EF_SHIFT_DOWN, event->flags());
 
-  event = dev->event(3);
+  event = dispatched_event(3);
   EXPECT_EQ(ui::ET_KEY_RELEASED, event->type());
   EXPECT_EQ(ui::VKEY_SHIFT, event->key_code());
   EXPECT_EQ(0, event->flags());
@@ -250,36 +254,36 @@
   };
 
   dev->ProcessEvents(mock_kernel_queue, arraysize(mock_kernel_queue));
-  EXPECT_EQ(6u, dev->size());
+  EXPECT_EQ(6u, size());
 
   ui::KeyEvent* event;
 
-  event = dev->event(0);
+  event = dispatched_event(0);
   EXPECT_EQ(ui::ET_KEY_PRESSED, event->type());
   EXPECT_EQ(ui::VKEY_CONTROL, event->key_code());
   EXPECT_EQ(ui::EF_CONTROL_DOWN, event->flags());
 
-  event = dev->event(1);
+  event = dispatched_event(1);
   EXPECT_EQ(ui::ET_KEY_PRESSED, event->type());
   EXPECT_EQ(ui::VKEY_CONTROL, event->key_code());
   EXPECT_EQ(ui::EF_CONTROL_DOWN, event->flags());
 
-  event = dev->event(2);
+  event = dispatched_event(2);
   EXPECT_EQ(ui::ET_KEY_PRESSED, event->type());
   EXPECT_EQ(ui::VKEY_Z, event->key_code());
   EXPECT_EQ(ui::EF_CONTROL_DOWN, event->flags());
 
-  event = dev->event(3);
+  event = dispatched_event(3);
   EXPECT_EQ(ui::ET_KEY_RELEASED, event->type());
   EXPECT_EQ(ui::VKEY_Z, event->key_code());
   EXPECT_EQ(ui::EF_CONTROL_DOWN, event->flags());
 
-  event = dev->event(4);
+  event = dispatched_event(4);
   EXPECT_EQ(ui::ET_KEY_RELEASED, event->type());
   EXPECT_EQ(ui::VKEY_CONTROL, event->key_code());
   EXPECT_EQ(ui::EF_CONTROL_DOWN, event->flags());
 
-  event = dev->event(5);
+  event = dispatched_event(5);
   EXPECT_EQ(ui::ET_KEY_RELEASED, event->type());
   EXPECT_EQ(ui::VKEY_CONTROL, event->key_code());
   EXPECT_EQ(0, event->flags());
@@ -315,36 +319,36 @@
   };
 
   dev->ProcessEvents(mock_kernel_queue, arraysize(mock_kernel_queue));
-  EXPECT_EQ(6u, dev->size());
+  EXPECT_EQ(6u, size());
 
   ui::KeyEvent* event;
 
-  event = dev->event(0);
+  event = dispatched_event(0);
   EXPECT_EQ(ui::ET_KEY_PRESSED, event->type());
   EXPECT_EQ(ui::VKEY_CAPITAL, event->key_code());
   EXPECT_EQ(ui::EF_CAPS_LOCK_DOWN, event->flags());
 
-  event = dev->event(1);
+  event = dispatched_event(1);
   EXPECT_EQ(ui::ET_KEY_RELEASED, event->type());
   EXPECT_EQ(ui::VKEY_CAPITAL, event->key_code());
   EXPECT_EQ(ui::EF_CAPS_LOCK_DOWN, event->flags());
 
-  event = dev->event(2);
+  event = dispatched_event(2);
   EXPECT_EQ(ui::ET_KEY_PRESSED, event->type());
   EXPECT_EQ(ui::VKEY_Q, event->key_code());
   EXPECT_EQ(ui::EF_CAPS_LOCK_DOWN, event->flags());
 
-  event = dev->event(3);
+  event = dispatched_event(3);
   EXPECT_EQ(ui::ET_KEY_RELEASED, event->type());
   EXPECT_EQ(ui::VKEY_Q, event->key_code());
   EXPECT_EQ(ui::EF_CAPS_LOCK_DOWN, event->flags());
 
-  event = dev->event(4);
+  event = dispatched_event(4);
   EXPECT_EQ(ui::ET_KEY_PRESSED, event->type());
   EXPECT_EQ(ui::VKEY_CAPITAL, event->key_code());
   EXPECT_EQ(0, event->flags());
 
-  event = dev->event(5);
+  event = dispatched_event(5);
   EXPECT_EQ(ui::ET_KEY_RELEASED, event->type());
   EXPECT_EQ(ui::VKEY_CAPITAL, event->key_code());
   EXPECT_EQ(0, event->flags());
diff --git a/ui/events/ozone/evdev/keyboard_evdev.cc b/ui/events/ozone/evdev/keyboard_evdev.cc
new file mode 100644
index 0000000..6e5266f
--- /dev/null
+++ b/ui/events/ozone/evdev/keyboard_evdev.cc
@@ -0,0 +1,239 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/events/ozone/evdev/keyboard_evdev.h"
+
+#include "ui/events/event.h"
+#include "ui/events/keycodes/dom4/keycode_converter.h"
+#include "ui/events/ozone/evdev/event_modifiers_evdev.h"
+
+namespace ui {
+
+namespace {
+
+const int kXkbKeycodeOffset = 8;
+
+ui::KeyboardCode KeyboardCodeFromEvdevKey(unsigned int code) {
+  static const ui::KeyboardCode kLinuxBaseKeyMap[] = {
+      ui::VKEY_UNKNOWN,            // KEY_RESERVED
+      ui::VKEY_ESCAPE,             // KEY_ESC
+      ui::VKEY_1,                  // KEY_1
+      ui::VKEY_2,                  // KEY_2
+      ui::VKEY_3,                  // KEY_3
+      ui::VKEY_4,                  // KEY_4
+      ui::VKEY_5,                  // KEY_5
+      ui::VKEY_6,                  // KEY_6
+      ui::VKEY_7,                  // KEY_7
+      ui::VKEY_8,                  // KEY_8
+      ui::VKEY_9,                  // KEY_9
+      ui::VKEY_0,                  // KEY_0
+      ui::VKEY_OEM_MINUS,          // KEY_MINUS
+      ui::VKEY_OEM_PLUS,           // KEY_EQUAL
+      ui::VKEY_BACK,               // KEY_BACKSPACE
+      ui::VKEY_TAB,                // KEY_TAB
+      ui::VKEY_Q,                  // KEY_Q
+      ui::VKEY_W,                  // KEY_W
+      ui::VKEY_E,                  // KEY_E
+      ui::VKEY_R,                  // KEY_R
+      ui::VKEY_T,                  // KEY_T
+      ui::VKEY_Y,                  // KEY_Y
+      ui::VKEY_U,                  // KEY_U
+      ui::VKEY_I,                  // KEY_I
+      ui::VKEY_O,                  // KEY_O
+      ui::VKEY_P,                  // KEY_P
+      ui::VKEY_OEM_4,              // KEY_LEFTBRACE
+      ui::VKEY_OEM_6,              // KEY_RIGHTBRACE
+      ui::VKEY_RETURN,             // KEY_ENTER
+      ui::VKEY_CONTROL,            // KEY_LEFTCTRL
+      ui::VKEY_A,                  // KEY_A
+      ui::VKEY_S,                  // KEY_S
+      ui::VKEY_D,                  // KEY_D
+      ui::VKEY_F,                  // KEY_F
+      ui::VKEY_G,                  // KEY_G
+      ui::VKEY_H,                  // KEY_H
+      ui::VKEY_J,                  // KEY_J
+      ui::VKEY_K,                  // KEY_K
+      ui::VKEY_L,                  // KEY_L
+      ui::VKEY_OEM_1,              // KEY_SEMICOLON
+      ui::VKEY_OEM_7,              // KEY_APOSTROPHE
+      ui::VKEY_OEM_3,              // KEY_GRAVE
+      ui::VKEY_SHIFT,              // KEY_LEFTSHIFT
+      ui::VKEY_OEM_5,              // KEY_BACKSLASH
+      ui::VKEY_Z,                  // KEY_Z
+      ui::VKEY_X,                  // KEY_X
+      ui::VKEY_C,                  // KEY_C
+      ui::VKEY_V,                  // KEY_V
+      ui::VKEY_B,                  // KEY_B
+      ui::VKEY_N,                  // KEY_N
+      ui::VKEY_M,                  // KEY_M
+      ui::VKEY_OEM_COMMA,          // KEY_COMMA
+      ui::VKEY_OEM_PERIOD,         // KEY_DOT
+      ui::VKEY_OEM_2,              // KEY_SLASH
+      ui::VKEY_SHIFT,              // KEY_RIGHTSHIFT
+      ui::VKEY_MULTIPLY,           // KEY_KPASTERISK
+      ui::VKEY_MENU,               // KEY_LEFTALT
+      ui::VKEY_SPACE,              // KEY_SPACE
+      ui::VKEY_CAPITAL,            // KEY_CAPSLOCK
+      ui::VKEY_F1,                 // KEY_F1
+      ui::VKEY_F2,                 // KEY_F2
+      ui::VKEY_F3,                 // KEY_F3
+      ui::VKEY_F4,                 // KEY_F4
+      ui::VKEY_F5,                 // KEY_F5
+      ui::VKEY_F6,                 // KEY_F6
+      ui::VKEY_F7,                 // KEY_F7
+      ui::VKEY_F8,                 // KEY_F8
+      ui::VKEY_F9,                 // KEY_F9
+      ui::VKEY_F10,                // KEY_F10
+      ui::VKEY_NUMLOCK,            // KEY_NUMLOCK
+      ui::VKEY_SCROLL,             // KEY_SCROLLLOCK
+      ui::VKEY_NUMPAD7,            // KEY_KP7
+      ui::VKEY_NUMPAD8,            // KEY_KP8
+      ui::VKEY_NUMPAD9,            // KEY_KP9
+      ui::VKEY_SUBTRACT,           // KEY_KPMINUS
+      ui::VKEY_NUMPAD4,            // KEY_KP4
+      ui::VKEY_NUMPAD5,            // KEY_KP5
+      ui::VKEY_NUMPAD6,            // KEY_KP6
+      ui::VKEY_ADD,                // KEY_KPPLUS
+      ui::VKEY_NUMPAD1,            // KEY_KP1
+      ui::VKEY_NUMPAD2,            // KEY_KP2
+      ui::VKEY_NUMPAD3,            // KEY_KP3
+      ui::VKEY_NUMPAD0,            // KEY_KP0
+      ui::VKEY_DECIMAL,            // KEY_KPDOT
+      ui::VKEY_UNKNOWN,            // (unassigned)
+      ui::VKEY_DBE_DBCSCHAR,       // KEY_ZENKAKUHANKAKU
+      ui::VKEY_OEM_102,            // KEY_102ND
+      ui::VKEY_F11,                // KEY_F11
+      ui::VKEY_F12,                // KEY_F12
+      ui::VKEY_UNKNOWN,            // KEY_RO
+      ui::VKEY_UNKNOWN,            // KEY_KATAKANA
+      ui::VKEY_UNKNOWN,            // KEY_HIRAGANA
+      ui::VKEY_CONVERT,            // KEY_HENKAN
+      ui::VKEY_UNKNOWN,            // KEY_KATAKANAHIRAGANA
+      ui::VKEY_NONCONVERT,         // KEY_MUHENKAN
+      ui::VKEY_UNKNOWN,            // KEY_KPJPCOMMA
+      ui::VKEY_RETURN,             // KEY_KPENTER
+      ui::VKEY_CONTROL,            // KEY_RIGHTCTRL
+      ui::VKEY_DIVIDE,             // KEY_KPSLASH
+      ui::VKEY_PRINT,              // KEY_SYSRQ
+      ui::VKEY_MENU,               // KEY_RIGHTALT
+      ui::VKEY_RETURN,             // KEY_LINEFEED
+      ui::VKEY_HOME,               // KEY_HOME
+      ui::VKEY_UP,                 // KEY_UP
+      ui::VKEY_PRIOR,              // KEY_PAGEUP
+      ui::VKEY_LEFT,               // KEY_LEFT
+      ui::VKEY_RIGHT,              // KEY_RIGHT
+      ui::VKEY_END,                // KEY_END
+      ui::VKEY_DOWN,               // KEY_DOWN
+      ui::VKEY_NEXT,               // KEY_PAGEDOWN
+      ui::VKEY_INSERT,             // KEY_INSERT
+      ui::VKEY_DELETE,             // KEY_DELETE
+      ui::VKEY_UNKNOWN,            // KEY_MACRO
+      ui::VKEY_VOLUME_MUTE,        // KEY_MUTE
+      ui::VKEY_VOLUME_DOWN,        // KEY_VOLUMEDOWN
+      ui::VKEY_VOLUME_UP,          // KEY_VOLUMEUP
+      ui::VKEY_POWER,              // KEY_POWER
+      ui::VKEY_OEM_PLUS,           // KEY_KPEQUAL
+      ui::VKEY_UNKNOWN,            // KEY_KPPLUSMINUS
+      ui::VKEY_PAUSE,              // KEY_PAUSE
+      ui::VKEY_MEDIA_LAUNCH_APP1,  // KEY_SCALE
+      ui::VKEY_DECIMAL,            // KEY_KPCOMMA
+      ui::VKEY_HANGUL,             // KEY_HANGEUL
+      ui::VKEY_HANJA,              // KEY_HANJA
+      ui::VKEY_UNKNOWN,            // KEY_YEN
+      ui::VKEY_LWIN,               // KEY_LEFTMETA
+      ui::VKEY_RWIN,               // KEY_RIGHTMETA
+      ui::VKEY_APPS,               // KEY_COMPOSE
+  };
+
+  if (code < arraysize(kLinuxBaseKeyMap))
+    return kLinuxBaseKeyMap[code];
+
+  LOG(ERROR) << "Unknown key code: " << code;
+  return ui::VKEY_UNKNOWN;
+}
+
+int ModifierFromEvdevKey(unsigned int code) {
+  switch (code) {
+    case KEY_CAPSLOCK:
+      return EVDEV_MODIFIER_CAPS_LOCK;
+    case KEY_LEFTSHIFT:
+    case KEY_RIGHTSHIFT:
+      return EVDEV_MODIFIER_SHIFT;
+    case KEY_LEFTCTRL:
+    case KEY_RIGHTCTRL:
+      return EVDEV_MODIFIER_CONTROL;
+    case KEY_LEFTALT:
+    case KEY_RIGHTALT:
+      return EVDEV_MODIFIER_ALT;
+    case BTN_LEFT:
+      return EVDEV_MODIFIER_LEFT_MOUSE_BUTTON;
+    case BTN_MIDDLE:
+      return EVDEV_MODIFIER_MIDDLE_MOUSE_BUTTON;
+    case BTN_RIGHT:
+      return EVDEV_MODIFIER_RIGHT_MOUSE_BUTTON;
+    case KEY_LEFTMETA:
+    case KEY_RIGHTMETA:
+      return EVDEV_MODIFIER_COMMAND;
+    default:
+      return EVDEV_MODIFIER_NONE;
+  }
+}
+
+bool IsModifierLockKeyFromEvdevKey(unsigned int code) {
+  return code == KEY_CAPSLOCK;
+}
+
+}  // namespace
+
+KeyboardEvdev::KeyboardEvdev(EventModifiersEvdev* modifiers,
+                             const EventDispatchCallback& callback)
+    : callback_(callback), modifiers_(modifiers) {
+}
+
+KeyboardEvdev::~KeyboardEvdev() {
+}
+
+void KeyboardEvdev::OnKeyChange(unsigned int key, bool down) {
+  if (key > KEY_MAX)
+    return;
+
+  if (down != key_state_.test(key)) {
+    // State transition: !(down) -> (down)
+    if (down)
+      key_state_.set(key);
+    else
+      key_state_.reset(key);
+
+    UpdateModifier(key, down);
+  }
+
+  DispatchKey(key, down);
+}
+
+void KeyboardEvdev::UpdateModifier(unsigned int key, bool down) {
+  int modifier = ModifierFromEvdevKey(key);
+  int locking = IsModifierLockKeyFromEvdevKey(key);
+
+  if (modifier == EVDEV_MODIFIER_NONE)
+    return;
+
+  if (locking)
+    modifiers_->UpdateModifierLock(modifier, down);
+  else
+    modifiers_->UpdateModifier(modifier, down);
+}
+
+void KeyboardEvdev::DispatchKey(unsigned int key, bool down) {
+  ui::KeyboardCode code = KeyboardCodeFromEvdevKey(key);
+  int flags = modifiers_->GetModifierFlags();
+
+  KeyEvent key_event(
+      down ? ET_KEY_PRESSED : ET_KEY_RELEASED,
+      code,
+      KeycodeConverter::NativeKeycodeToCode(key + kXkbKeycodeOffset),
+      flags);
+  callback_.Run(&key_event);
+}
+
+}  // namespace ui
diff --git a/ui/events/ozone/evdev/keyboard_evdev.h b/ui/events/ozone/evdev/keyboard_evdev.h
new file mode 100644
index 0000000..913d006
--- /dev/null
+++ b/ui/events/ozone/evdev/keyboard_evdev.h
@@ -0,0 +1,60 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_EVENTS_OZONE_EVDEV_KEYBOARD_EVDEV_H_
+#define UI_EVENTS_OZONE_EVDEV_KEYBOARD_EVDEV_H_
+
+#include <bitset>
+#include <linux/input.h>
+
+#include "ui/events/ozone/evdev/event_device_util.h"
+#include "ui/events/ozone/evdev/event_dispatch_callback.h"
+#include "ui/events/ozone/evdev/events_ozone_evdev_export.h"
+
+namespace ui {
+
+class EventModifiersEvdev;
+
+// Keyboard for evdev.
+//
+// This object is responsible for combining all attached keyboards into
+// one logical keyboard, applying modifiers & implementing key repeat.
+//
+// It also currently also applies the layout (hardcoded as US).
+//
+// TODO(spang): Implement key repeat & turn off kernel repeat.
+class EVENTS_OZONE_EVDEV_EXPORT KeyboardEvdev {
+ public:
+  KeyboardEvdev(EventModifiersEvdev* modifiers,
+                const EventDispatchCallback& callback);
+  ~KeyboardEvdev();
+
+  // Handlers for raw key presses & releases.
+  void OnKeyChange(unsigned int code, bool down);
+
+ private:
+  void UpdateModifier(unsigned int key, bool down);
+  void DispatchKey(unsigned int key, bool down);
+
+  // Aggregated key state. There is only one bit of state per key; we do not
+  // attempt to count presses of the same key on multiple keyboards.
+  //
+  // A key is down iff the most recent event pertaining to that key was a key
+  // down event rather than a key up event. Therefore, a particular key position
+  // can be considered released even if it is being depresssed on one or more
+  // keyboards.
+  std::bitset<KEY_CNT> key_state_;
+
+  // Callback for dispatching events.
+  EventDispatchCallback callback_;
+
+  // Shared modifier state.
+  EventModifiersEvdev* modifiers_;
+
+  DISALLOW_COPY_AND_ASSIGN(KeyboardEvdev);
+};
+
+}  // namespace ui
+
+#endif  // UI_EVENTS_OZONE_EVDEV_KEYBOARD_EVDEV_H_
diff --git a/ui/events/ozone/evdev/libgestures_glue/gesture_interpreter_libevdev_cros.cc b/ui/events/ozone/evdev/libgestures_glue/gesture_interpreter_libevdev_cros.cc
index 59d8735..073514d 100644
--- a/ui/events/ozone/evdev/libgestures_glue/gesture_interpreter_libevdev_cros.cc
+++ b/ui/events/ozone/evdev/libgestures_glue/gesture_interpreter_libevdev_cros.cc
@@ -11,7 +11,9 @@
 #include "base/timer/timer.h"
 #include "ui/events/event.h"
 #include "ui/events/ozone/evdev/cursor_delegate_evdev.h"
+#include "ui/events/ozone/evdev/event_device_util.h"
 #include "ui/events/ozone/evdev/event_modifiers_evdev.h"
+#include "ui/events/ozone/evdev/keyboard_evdev.h"
 #include "ui/events/ozone/evdev/libgestures_glue/gesture_timer_provider.h"
 #include "ui/gfx/geometry/point_f.h"
 
@@ -81,11 +83,15 @@
 GestureInterpreterLibevdevCros::GestureInterpreterLibevdevCros(
     EventModifiersEvdev* modifiers,
     CursorDelegateEvdev* cursor,
+    KeyboardEvdev* keyboard,
     const EventDispatchCallback& callback)
     : modifiers_(modifiers),
       cursor_(cursor),
+      keyboard_(keyboard),
       dispatch_callback_(callback),
-      interpreter_(NULL) {}
+      interpreter_(NULL) {
+  memset(&prev_key_state_, 0, sizeof(prev_key_state_));
+}
 
 GestureInterpreterLibevdevCros::~GestureInterpreterLibevdevCros() {
   if (interpreter_) {
@@ -118,6 +124,9 @@
 void GestureInterpreterLibevdevCros::OnLibEvdevCrosEvent(Evdev* evdev,
                                                          EventStateRec* evstate,
                                                          const timeval& time) {
+  // If the device has keys no it, dispatch any presses/release.
+  DispatchChangedKeys(evdev, time);
+
   HardwareState hwstate;
   memset(&hwstate, 0, sizeof(hwstate));
   hwstate.timestamp = StimeFromTimeval(&time);
@@ -395,4 +404,25 @@
   Dispatch(&event);
 }
 
+void GestureInterpreterLibevdevCros::DispatchChangedKeys(Evdev* evdev,
+                                                         const timeval& time) {
+  unsigned long key_state_diff[EVDEV_BITS_TO_LONGS(KEY_CNT)];
+
+  // Find changed keys.
+  for (unsigned long i = 0; i < arraysize(key_state_diff); ++i)
+    key_state_diff[i] = evdev->key_state_bitmask[i] ^ prev_key_state_[i];
+
+  // Dispatch events for changed keys.
+  for (unsigned long i = 0; i < KEY_CNT; ++i) {
+    if (EvdevBitIsSet(key_state_diff, i)) {
+      bool value = EvdevBitIsSet(evdev->key_state_bitmask, i);
+      keyboard_->OnKeyChange(i, value);
+    }
+  }
+
+  // Update internal key state.
+  for (unsigned long i = 0; i < EVDEV_BITS_TO_LONGS(KEY_CNT); ++i)
+    prev_key_state_[i] = evdev->key_state_bitmask[i];
+}
+
 }  // namespace ui
diff --git a/ui/events/ozone/evdev/libgestures_glue/gesture_interpreter_libevdev_cros.h b/ui/events/ozone/evdev/libgestures_glue/gesture_interpreter_libevdev_cros.h
index f097fb4..a0863bf 100644
--- a/ui/events/ozone/evdev/libgestures_glue/gesture_interpreter_libevdev_cros.h
+++ b/ui/events/ozone/evdev/libgestures_glue/gesture_interpreter_libevdev_cros.h
@@ -11,6 +11,7 @@
 #include "base/callback.h"
 #include "base/memory/scoped_ptr.h"
 #include "ui/events/ozone/evdev/cursor_delegate_evdev.h"
+#include "ui/events/ozone/evdev/event_device_util.h"
 #include "ui/events/ozone/evdev/event_dispatch_callback.h"
 #include "ui/events/ozone/evdev/events_ozone_evdev_export.h"
 #include "ui/events/ozone/evdev/libgestures_glue/event_reader_libevdev_cros.h"
@@ -20,6 +21,7 @@
 class EventDeviceInfo;
 class EventModifiersEvdev;
 class CursorDelegateEvdev;
+class KeyboardEvdev;
 
 // Convert libevdev-cros events to ui::Events using libgestures.
 //
@@ -39,6 +41,7 @@
  public:
   GestureInterpreterLibevdevCros(EventModifiersEvdev* modifiers,
                                  CursorDelegateEvdev* cursor,
+                                 KeyboardEvdev* keyboard,
                                  const EventDispatchCallback& callback);
   virtual ~GestureInterpreterLibevdevCros();
 
@@ -67,6 +70,7 @@
 
   void Dispatch(Event* event);
   void DispatchMouseButton(unsigned int modifier, bool down);
+  void DispatchChangedKeys(Evdev* evdev, const timeval& time);
 
   // Shared modifier state.
   EventModifiersEvdev* modifiers_;
@@ -74,12 +78,18 @@
   // Shared cursor state.
   CursorDelegateEvdev* cursor_;
 
+  // Shared keyboard state.
+  KeyboardEvdev* keyboard_;
+
   // Callback for dispatching events.
   EventDispatchCallback dispatch_callback_;
 
   // Gestures interpretation state.
   gestures::GestureInterpreter* interpreter_;
 
+  // Last key state from libevdev.
+  unsigned long prev_key_state_[EVDEV_BITS_TO_LONGS(KEY_CNT)];
+
   DISALLOW_COPY_AND_ASSIGN(GestureInterpreterLibevdevCros);
 };
 
diff --git a/ui/events/ozone/events_ozone.gyp b/ui/events/ozone/events_ozone.gyp
index 1c88263..905e0fd 100644
--- a/ui/events/ozone/events_ozone.gyp
+++ b/ui/events/ozone/events_ozone.gyp
@@ -73,6 +73,8 @@
       'evdev/events_ozone_evdev_export.h',
       'evdev/key_event_converter_evdev.cc',
       'evdev/key_event_converter_evdev.h',
+      'evdev/keyboard_evdev.cc',
+      'evdev/keyboard_evdev.h',
       'evdev/touch_event_converter_evdev.cc',
       'evdev/touch_event_converter_evdev.h',
     ],
diff --git a/ui/file_manager/video_player/js/media_controls.js b/ui/file_manager/video_player/js/media_controls.js
index 238c763..a565cc4 100644
--- a/ui/file_manager/video_player/js/media_controls.js
+++ b/ui/file_manager/video_player/js/media_controls.js
@@ -361,6 +361,10 @@
   this.media_.addEventListener('timeupdate', this.onMediaProgressBound_);
   this.media_.addEventListener('error', this.onMediaError_);
 
+  // If the text banner is being displayed, hide it immediately, since it is
+  // related to the previous media.
+  this.textBanner_.removeAttribute('visible');
+
   // Reflect the media state in the UI.
   this.onMediaDuration_();
   this.onMediaPlay_(this.isPlaying());
diff --git a/ui/gfx/font_render_params_android.cc b/ui/gfx/font_render_params_android.cc
index a74efb8..729de41 100644
--- a/ui/gfx/font_render_params_android.cc
+++ b/ui/gfx/font_render_params_android.cc
@@ -32,9 +32,9 @@
 
 FontRenderParams GetFontRenderParams(const FontRenderParamsQuery& query,
                                      std::string* family_out) {
-  // Customized font rendering settings are not supported, only defaults.
-  if (!query.is_empty() || family_out)
+  if (family_out)
     NOTIMPLEMENTED();
+  // Customized font rendering settings are not supported, only defaults.
   CR_DEFINE_STATIC_LOCAL(const gfx::FontRenderParams, params, (LoadDefaults()));
   return params;
 }
diff --git a/ui/gfx/font_render_params_mac.cc b/ui/gfx/font_render_params_mac.cc
index 0062f3b..83fd341 100644
--- a/ui/gfx/font_render_params_mac.cc
+++ b/ui/gfx/font_render_params_mac.cc
@@ -28,9 +28,9 @@
 
 FontRenderParams GetFontRenderParams(const FontRenderParamsQuery& query,
                                      std::string* family_out) {
-  // TODO: Query the OS for font render settings instead of returning defaults.
-  if (!query.is_empty() || family_out)
+  if (family_out)
     NOTIMPLEMENTED();
+  // TODO: Query the OS for font render settings instead of returning defaults.
   CR_DEFINE_STATIC_LOCAL(const gfx::FontRenderParams, params, (LoadDefaults()));
   return params;
 }
diff --git a/ui/gfx/font_render_params_win.cc b/ui/gfx/font_render_params_win.cc
index 372435d..70b19d2 100644
--- a/ui/gfx/font_render_params_win.cc
+++ b/ui/gfx/font_render_params_win.cc
@@ -75,9 +75,9 @@
 
 FontRenderParams GetFontRenderParams(const FontRenderParamsQuery& query,
                                      std::string* family_out) {
-  // Customized font rendering settings are not supported, only defaults.
-  if (!query.is_empty() || family_out)
+  if (family_out)
     NOTIMPLEMENTED();
+  // Customized font rendering settings are not supported, only defaults.
   return CachedFontRenderParams::GetInstance()->GetParams(
       query.for_web_contents);
 }
diff --git a/ui/gfx/geometry/BUILD.gn b/ui/gfx/geometry/BUILD.gn
index 48b26fe..0863330 100644
--- a/ui/gfx/geometry/BUILD.gn
+++ b/ui/gfx/geometry/BUILD.gn
@@ -20,7 +20,6 @@
     "point.h",
     "point3_f.cc",
     "point3_f.h",
-    "point_base.h",
     "point_conversions.cc",
     "point_conversions.h",
     "point_f.cc",
@@ -41,7 +40,6 @@
     "scroll_offset.h",
     "size.cc",
     "size.h",
-    "size_base.h",
     "size_conversions.cc",
     "size_conversions.h",
     "size_f.cc",
diff --git a/ui/gfx/geometry/point.cc b/ui/gfx/geometry/point.cc
index 5a68ba6..2248a4d 100644
--- a/ui/gfx/geometry/point.cc
+++ b/ui/gfx/geometry/point.cc
@@ -12,22 +12,19 @@
 
 namespace gfx {
 
-template class PointBase<Point, int, Vector2d>;
-
 #if defined(OS_WIN)
-Point::Point(DWORD point) : PointBase<Point, int, Vector2d>(0, 0){
+Point::Point(DWORD point) {
   POINTS points = MAKEPOINTS(point);
-  set_x(points.x);
-  set_y(points.y);
+  x_ = points.x;
+  y_ = points.y;
 }
 
-Point::Point(const POINT& point)
-    : PointBase<Point, int, Vector2d>(point.x, point.y) {
+Point::Point(const POINT& point) : x_(point.x), y_(point.y) {
 }
 
 Point& Point::operator=(const POINT& point) {
-  set_x(point.x);
-  set_y(point.y);
+  x_ = point.x;
+  y_ = point.y;
   return *this;
 }
 
@@ -37,15 +34,17 @@
   p.y = y();
   return p;
 }
-#elif defined(OS_MACOSX)
-Point::Point(const CGPoint& point)
-    : PointBase<Point, int, Vector2d>(point.x, point.y) {
+#endif
+
+void Point::SetToMin(const Point& other) {
+  x_ = x_ <= other.x_ ? x_ : other.x_;
+  y_ = y_ <= other.y_ ? y_ : other.y_;
 }
 
-CGPoint Point::ToCGPoint() const {
-  return CGPointMake(x(), y());
+void Point::SetToMax(const Point& other) {
+  x_ = x_ >= other.x_ ? x_ : other.x_;
+  y_ = y_ >= other.y_ ? y_ : other.y_;
 }
-#endif
 
 std::string Point::ToString() const {
   return base::StringPrintf("%d,%d", x(), y());
diff --git a/ui/gfx/geometry/point.h b/ui/gfx/geometry/point.h
index c7ac4ff..63ee922 100644
--- a/ui/gfx/geometry/point.h
+++ b/ui/gfx/geometry/point.h
@@ -8,7 +8,6 @@
 #include <iosfwd>
 #include <string>
 
-#include "ui/gfx/geometry/point_base.h"
 #include "ui/gfx/geometry/point_f.h"
 #include "ui/gfx/geometry/vector2d.h"
 #include "ui/gfx/gfx_export.h"
@@ -25,10 +24,10 @@
 namespace gfx {
 
 // A point has an x and y coordinate.
-class GFX_EXPORT Point : public PointBase<Point, int, Vector2d> {
+class GFX_EXPORT Point {
  public:
-  Point() : PointBase<Point, int, Vector2d>(0, 0) {}
-  Point(int x, int y) : PointBase<Point, int, Vector2d>(x, y) {}
+  Point() : x_(0), y_(0) {}
+  Point(int x, int y) : x_(x), y_(y) {}
 #if defined(OS_WIN)
   // |point| is a DWORD value that contains a coordinate.  The x-coordinate is
   // the low-order short and the y-coordinate is the high-order short.  This
@@ -37,7 +36,7 @@
   explicit Point(const POINT& point);
   Point& operator=(const POINT& point);
 #elif defined(OS_MACOSX)
-  explicit Point(const CGPoint& point);
+  explicit Point(const CGPoint& point) : x_(point.x), y_(point.y) {}
 #endif
 
   ~Point() {}
@@ -45,15 +44,61 @@
 #if defined(OS_WIN)
   POINT ToPOINT() const;
 #elif defined(OS_MACOSX)
-  CGPoint ToCGPoint() const;
+  CGPoint ToCGPoint() const { return CGPointMake(x(), y()); }
 #endif
 
+  int x() const { return x_; }
+  int y() const { return y_; }
+  void set_x(int x) { x_ = x; }
+  void set_y(int y) { y_ = y; }
+
+  void SetPoint(int x, int y) {
+    x_ = x;
+    y_ = y;
+  }
+
+  void Offset(int delta_x, int delta_y) {
+    x_ += delta_x;
+    y_ += delta_y;
+  }
+
+  void operator+=(const Vector2d& vector) {
+    x_ += vector.x();
+    y_ += vector.y();
+  }
+
+  void operator-=(const Vector2d& vector) {
+    x_ -= vector.x();
+    y_ -= vector.y();
+  }
+
+  void SetToMin(const Point& other);
+  void SetToMax(const Point& other);
+
+  bool IsOrigin() const { return x_ == 0 && y_ == 0; }
+
+  Vector2d OffsetFromOrigin() const { return Vector2d(x_, y_); }
+
+  // A point is less than another point if its y-value is closer
+  // to the origin. If the y-values are the same, then point with
+  // the x-value closer to the origin is considered less than the
+  // other.
+  // This comparison is required to use Point in sets, or sorted
+  // vectors.
+  bool operator<(const Point& rhs) const {
+    return (y_ == rhs.y_) ? (x_ < rhs.x_) : (y_ < rhs.y_);
+  }
+
   operator PointF() const {
     return PointF(x(), y());
   }
 
   // Returns a string representation of point.
   std::string ToString() const;
+
+ private:
+  int x_;
+  int y_;
 };
 
 inline bool operator==(const Point& lhs, const Point& rhs) {
@@ -84,10 +129,6 @@
   return Point(offset_from_origin.x(), offset_from_origin.y());
 }
 
-#if !defined(COMPILER_MSVC) && !defined(__native_client__)
-extern template class PointBase<Point, int, Vector2d>;
-#endif
-
 // This is declared here for use in gtest-based unit tests but is defined in
 // the gfx_test_support target. Depend on that to use this in your unit test.
 // This should not be used in production code - call ToString() instead.
diff --git a/ui/gfx/geometry/point_base.h b/ui/gfx/geometry/point_base.h
deleted file mode 100644
index 6db1c0c..0000000
--- a/ui/gfx/geometry/point_base.h
+++ /dev/null
@@ -1,87 +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 UI_GFX_GEOMETRY_POINT_BASE_H_
-#define UI_GFX_GEOMETRY_POINT_BASE_H_
-
-#include <string>
-
-#include "base/compiler_specific.h"
-#include "build/build_config.h"
-#include "ui/gfx/gfx_export.h"
-
-namespace gfx {
-
-// A point has an x and y coordinate.
-template<typename Class, typename Type, typename VectorClass>
-class GFX_EXPORT PointBase {
- public:
-  Type x() const { return x_; }
-  Type y() const { return y_; }
-
-  void SetPoint(Type x, Type y) {
-    x_ = x;
-    y_ = y;
-  }
-
-  void set_x(Type x) { x_ = x; }
-  void set_y(Type y) { y_ = y; }
-
-  void Offset(Type delta_x, Type delta_y) {
-    x_ += delta_x;
-    y_ += delta_y;
-  }
-
-  void operator+=(const VectorClass& vector) {
-    x_ += vector.x();
-    y_ += vector.y();
-  }
-
-  void operator-=(const VectorClass& vector) {
-    x_ -= vector.x();
-    y_ -= vector.y();
-  }
-
-  void SetToMin(const Class& other) {
-    x_ = x_ <= other.x_ ? x_ : other.x_;
-    y_ = y_ <= other.y_ ? y_ : other.y_;
-  }
-
-  void SetToMax(const Class& other) {
-    x_ = x_ >= other.x_ ? x_ : other.x_;
-    y_ = y_ >= other.y_ ? y_ : other.y_;
-  }
-
-  bool IsOrigin() const {
-    return x_ == 0 && y_ == 0;
-  }
-
-  VectorClass OffsetFromOrigin() const {
-    return VectorClass(x_, y_);
-  }
-
-  // A point is less than another point if its y-value is closer
-  // to the origin. If the y-values are the same, then point with
-  // the x-value closer to the origin is considered less than the
-  // other.
-  // This comparison is required to use Point in sets, or sorted
-  // vectors.
-  bool operator<(const Class& rhs) const {
-    return (y_ == rhs.y_) ? (x_ < rhs.x_) : (y_ < rhs.y_);
-  }
-
- protected:
-  PointBase(Type x, Type y) : x_(x), y_(y) {}
-  // Destructor is intentionally made non virtual and protected.
-  // Do not make this public.
-  ~PointBase() {}
-
- private:
-  Type x_;
-  Type y_;
-};
-
-}  // namespace gfx
-
-#endif  // UI_GFX_GEOMETRY_POINT_BASE_H_
diff --git a/ui/gfx/geometry/point_f.cc b/ui/gfx/geometry/point_f.cc
index 9c2ece2..0d15394 100644
--- a/ui/gfx/geometry/point_f.cc
+++ b/ui/gfx/geometry/point_f.cc
@@ -8,7 +8,15 @@
 
 namespace gfx {
 
-template class PointBase<PointF, float, Vector2dF>;
+void PointF::SetToMin(const PointF& other) {
+  x_ = x_ <= other.x_ ? x_ : other.x_;
+  y_ = y_ <= other.y_ ? y_ : other.y_;
+}
+
+void PointF::SetToMax(const PointF& other) {
+  x_ = x_ >= other.x_ ? x_ : other.x_;
+  y_ = y_ >= other.y_ ? y_ : other.y_;
+}
 
 std::string PointF::ToString() const {
   return base::StringPrintf("%f,%f", x(), y());
diff --git a/ui/gfx/geometry/point_f.h b/ui/gfx/geometry/point_f.h
index a0b6d33..f900c1c 100644
--- a/ui/gfx/geometry/point_f.h
+++ b/ui/gfx/geometry/point_f.h
@@ -8,19 +8,60 @@
 #include <iosfwd>
 #include <string>
 
-#include "ui/gfx/geometry/point_base.h"
 #include "ui/gfx/geometry/vector2d_f.h"
 #include "ui/gfx/gfx_export.h"
 
 namespace gfx {
 
 // A floating version of gfx::Point.
-class GFX_EXPORT PointF : public PointBase<PointF, float, Vector2dF> {
+class GFX_EXPORT PointF {
  public:
-  PointF() : PointBase<PointF, float, Vector2dF>(0, 0) {}
-  PointF(float x, float y) : PointBase<PointF, float, Vector2dF>(x, y) {}
+  PointF() : x_(0.f), y_(0.f) {}
+  PointF(float x, float y) : x_(x), y_(y) {}
   ~PointF() {}
 
+  float x() const { return x_; }
+  float y() const { return y_; }
+  void set_x(float x) { x_ = x; }
+  void set_y(float y) { y_ = y; }
+
+  void SetPoint(float x, float y) {
+    x_ = x;
+    y_ = y;
+  }
+
+  void Offset(float delta_x, float delta_y) {
+    x_ += delta_x;
+    y_ += delta_y;
+  }
+
+  void operator+=(const Vector2dF& vector) {
+    x_ += vector.x();
+    y_ += vector.y();
+  }
+
+  void operator-=(const Vector2dF& vector) {
+    x_ -= vector.x();
+    y_ -= vector.y();
+  }
+
+  void SetToMin(const PointF& other);
+  void SetToMax(const PointF& other);
+
+  bool IsOrigin() const { return x_ == 0 && y_ == 0; }
+
+  Vector2dF OffsetFromOrigin() const { return Vector2dF(x_, y_); }
+
+  // A point is less than another point if its y-value is closer
+  // to the origin. If the y-values are the same, then point with
+  // the x-value closer to the origin is considered less than the
+  // other.
+  // This comparison is required to use PointF in sets, or sorted
+  // vectors.
+  bool operator<(const PointF& rhs) const {
+    return (y_ == rhs.y_) ? (x_ < rhs.x_) : (y_ < rhs.y_);
+  }
+
   void Scale(float scale) {
     Scale(scale, scale);
   }
@@ -31,6 +72,10 @@
 
   // Returns a string representation of point.
   std::string ToString() const;
+
+ private:
+  float x_;
+  float y_;
 };
 
 inline bool operator==(const PointF& lhs, const PointF& rhs) {
@@ -67,10 +112,6 @@
   return ScalePoint(p, scale, scale);
 }
 
-#if !defined(COMPILER_MSVC) && !defined(__native_client__)
-extern template class PointBase<PointF, float, Vector2dF>;
-#endif
-
 // This is declared here for use in gtest-based unit tests but is defined in
 // the gfx_test_support target. Depend on that to use this in your unit test.
 // This should not be used in production code - call ToString() instead.
diff --git a/ui/gfx/geometry/point_unittest.cc b/ui/gfx/geometry/point_unittest.cc
index d0cdded..07a5d5b 100644
--- a/ui/gfx/geometry/point_unittest.cc
+++ b/ui/gfx/geometry/point_unittest.cc
@@ -5,7 +5,6 @@
 #include "base/basictypes.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/gfx/geometry/point.h"
-#include "ui/gfx/geometry/point_base.h"
 #include "ui/gfx/geometry/point_conversions.h"
 #include "ui/gfx/geometry/point_f.h"
 
diff --git a/ui/gfx/geometry/size.cc b/ui/gfx/geometry/size.cc
index 38ec4b3..d916ebd 100644
--- a/ui/gfx/geometry/size.cc
+++ b/ui/gfx/geometry/size.cc
@@ -12,20 +12,6 @@
 
 namespace gfx {
 
-template class SizeBase<Size, int>;
-
-#if defined(OS_MACOSX)
-Size::Size(const CGSize& s)
-    : SizeBase<Size, int>(s.width, s.height) {
-}
-
-Size& Size::operator=(const CGSize& s) {
-  set_width(s.width);
-  set_height(s.height);
-  return *this;
-}
-#endif
-
 #if defined(OS_WIN)
 SIZE Size::ToSIZE() const {
   SIZE s;
@@ -33,12 +19,34 @@
   s.cy = height();
   return s;
 }
-#elif defined(OS_MACOSX)
-CGSize Size::ToCGSize() const {
-  return CGSizeMake(width(), height());
+#endif
+
+#if defined(OS_MACOSX)
+Size& Size::operator=(const CGSize& s) {
+  set_width(s.width);
+  set_height(s.height);
+  return *this;
 }
 #endif
 
+int Size::GetArea() const {
+  return width() * height();
+}
+
+void Size::Enlarge(int grow_width, int grow_height) {
+  SetSize(width() + grow_width, height() + grow_height);
+}
+
+void Size::SetToMin(const Size& other) {
+  width_ = width() <= other.width() ? width() : other.width();
+  height_ = height() <= other.height() ? height() : other.height();
+}
+
+void Size::SetToMax(const Size& other) {
+  width_ = width() >= other.width() ? width() : other.width();
+  height_ = height() >= other.height() ? height() : other.height();
+}
+
 std::string Size::ToString() const {
   return base::StringPrintf("%dx%d", width(), height());
 }
diff --git a/ui/gfx/geometry/size.h b/ui/gfx/geometry/size.h
index 10b90a5..7f2a903 100644
--- a/ui/gfx/geometry/size.h
+++ b/ui/gfx/geometry/size.h
@@ -9,7 +9,6 @@
 #include <string>
 
 #include "base/compiler_specific.h"
-#include "ui/gfx/geometry/size_base.h"
 #include "ui/gfx/geometry/size_f.h"
 #include "ui/gfx/gfx_export.h"
 
@@ -24,12 +23,15 @@
 namespace gfx {
 
 // A size has width and height values.
-class GFX_EXPORT Size : public SizeBase<Size, int> {
+class GFX_EXPORT Size {
  public:
-  Size() : SizeBase<Size, int>(0, 0) {}
-  Size(int width, int height) : SizeBase<Size, int>(width, height) {}
+  Size() : width_(0), height_(0) {}
+  Size(int width, int height)
+      : width_(width < 0 ? 0 : width), height_(height < 0 ? 0 : height) {}
 #if defined(OS_MACOSX)
-  explicit Size(const CGSize& s);
+  explicit Size(const CGSize& s)
+      : width_(s.width < 0 ? 0 : s.width),
+        height_(s.height < 0 ? 0 : s.height) {}
 #endif
 
   ~Size() {}
@@ -41,14 +43,38 @@
 #if defined(OS_WIN)
   SIZE ToSIZE() const;
 #elif defined(OS_MACOSX)
-  CGSize ToCGSize() const;
+  CGSize ToCGSize() const { return CGSizeMake(width(), height()); }
 #endif
 
+  int width() const { return width_; }
+  int height() const { return height_; }
+
+  void set_width(int width) { width_ = width < 0 ? 0 : width; }
+  void set_height(int height) { height_ = height < 0 ? 0 : height; }
+
+  int GetArea() const;
+
+  void SetSize(int width, int height) {
+    set_width(width);
+    set_height(height);
+  }
+
+  void Enlarge(int grow_width, int grow_height);
+
+  void SetToMin(const Size& other);
+  void SetToMax(const Size& other);
+
+  bool IsEmpty() const { return !width() || !height(); }
+
   operator SizeF() const {
     return SizeF(width(), height());
   }
 
   std::string ToString() const;
+
+ private:
+  int width_;
+  int height_;
 };
 
 inline bool operator==(const Size& lhs, const Size& rhs) {
@@ -59,10 +85,6 @@
   return !(lhs == rhs);
 }
 
-#if !defined(COMPILER_MSVC) && !defined(__native_client__)
-extern template class SizeBase<Size, int>;
-#endif
-
 // This is declared here for use in gtest-based unit tests but is defined in
 // the gfx_test_support target. Depend on that to use this in your unit test.
 // This should not be used in production code - call ToString() instead.
diff --git a/ui/gfx/geometry/size_base.h b/ui/gfx/geometry/size_base.h
deleted file mode 100644
index 88a98ef..0000000
--- a/ui/gfx/geometry/size_base.h
+++ /dev/null
@@ -1,69 +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 UI_GFX_GEOMETRY_SIZE_BASE_H_
-#define UI_GFX_GEOMETRY_SIZE_BASE_H_
-
-#include "ui/gfx/gfx_export.h"
-
-namespace gfx {
-
-// A size has width and height values.
-template<typename Class, typename Type>
-class GFX_EXPORT SizeBase {
- public:
-  Type width() const { return width_; }
-  Type height() const { return height_; }
-
-  Type GetArea() const { return width_ * height_; }
-
-  void SetSize(Type width, Type height) {
-    set_width(width);
-    set_height(height);
-  }
-
-  void Enlarge(Type width, Type height) {
-    set_width(width_ + width);
-    set_height(height_ + height);
-  }
-
-  void set_width(Type width) {
-    width_ = width < 0 ? 0 : width;
-  }
-  void set_height(Type height) {
-    height_ = height < 0 ? 0 : height;
-  }
-
-  void SetToMin(const Class& other) {
-    width_ = width_ <= other.width_ ? width_ : other.width_;
-    height_ = height_ <= other.height_ ? height_ : other.height_;
-  }
-
-  void SetToMax(const Class& other) {
-    width_ = width_ >= other.width_ ? width_ : other.width_;
-    height_ = height_ >= other.height_ ? height_ : other.height_;
-  }
-
-  bool IsEmpty() const {
-    return (width_ == 0) || (height_ == 0);
-  }
-
- protected:
-  SizeBase(Type width, Type height)
-      : width_(width < 0 ? 0 : width),
-      height_(height < 0 ? 0 : height) {
-  }
-
-  // Destructor is intentionally made non virtual and protected.
-  // Do not make this public.
-  ~SizeBase() {}
-
- private:
-  Type width_;
-  Type height_;
-};
-
-}  // namespace gfx
-
-#endif  // UI_GFX_GEOMETRY_SIZE_BASE_H_
diff --git a/ui/gfx/geometry/size_f.cc b/ui/gfx/geometry/size_f.cc
index 10c1445..6d08e18 100644
--- a/ui/gfx/geometry/size_f.cc
+++ b/ui/gfx/geometry/size_f.cc
@@ -8,7 +8,23 @@
 
 namespace gfx {
 
-template class SizeBase<SizeF, float>;
+float SizeF::GetArea() const {
+  return width() * height();
+}
+
+void SizeF::Enlarge(float grow_width, float grow_height) {
+  SetSize(width() + grow_width, height() + grow_height);
+}
+
+void SizeF::SetToMin(const SizeF& other) {
+  width_ = width() <= other.width() ? width() : other.width();
+  height_ = height() <= other.height() ? height() : other.height();
+}
+
+void SizeF::SetToMax(const SizeF& other) {
+  width_ = width() >= other.width() ? width() : other.width();
+  height_ = height() >= other.height() ? height() : other.height();
+}
 
 std::string SizeF::ToString() const {
   return base::StringPrintf("%fx%f", width(), height());
diff --git a/ui/gfx/geometry/size_f.h b/ui/gfx/geometry/size_f.h
index 3057d41..66080f0 100644
--- a/ui/gfx/geometry/size_f.h
+++ b/ui/gfx/geometry/size_f.h
@@ -5,22 +5,43 @@
 #ifndef UI_GFX_GEOMETRY_SIZE_F_H_
 #define UI_GFX_GEOMETRY_SIZE_F_H_
 
+#include <cmath>
 #include <iosfwd>
 #include <string>
 
 #include "base/compiler_specific.h"
-#include "ui/gfx/geometry/size_base.h"
 #include "ui/gfx/gfx_export.h"
 
 namespace gfx {
 
 // A floating version of gfx::Size.
-class GFX_EXPORT SizeF : public SizeBase<SizeF, float> {
+class GFX_EXPORT SizeF {
  public:
-  SizeF() : SizeBase<SizeF, float>(0, 0) {}
-  SizeF(float width, float height) : SizeBase<SizeF, float>(width, height) {}
+  SizeF() : width_(0.f), height_(0.f) {}
+  SizeF(float width, float height)
+      : width_(fmaxf(0, width)), height_(fmaxf(0, height)) {}
   ~SizeF() {}
 
+  float width() const { return width_; }
+  float height() const { return height_; }
+
+  void set_width(float width) { width_ = fmaxf(0, width); }
+  void set_height(float height) { height_ = fmaxf(0, height); }
+
+  float GetArea() const;
+
+  void SetSize(float width, float height) {
+    set_width(width);
+    set_height(height);
+  }
+
+  void Enlarge(float grow_width, float grow_height);
+
+  void SetToMin(const SizeF& other);
+  void SetToMax(const SizeF& other);
+
+  bool IsEmpty() const { return !width() || !height(); }
+
   void Scale(float scale) {
     Scale(scale, scale);
   }
@@ -30,6 +51,10 @@
   }
 
   std::string ToString() const;
+
+ private:
+  float width_;
+  float height_;
 };
 
 inline bool operator==(const SizeF& lhs, const SizeF& rhs) {
@@ -46,10 +71,6 @@
   return ScaleSize(p, scale, scale);
 }
 
-#if !defined(COMPILER_MSVC) && !defined(__native_client__)
-extern template class SizeBase<SizeF, float>;
-#endif
-
 // This is declared here for use in gtest-based unit tests but is defined in
 // the gfx_test_support target. Depend on that to use this in your unit test.
 // This should not be used in production code - call ToString() instead.
diff --git a/ui/gfx/geometry/size_unittest.cc b/ui/gfx/geometry/size_unittest.cc
index 1589283..87a487c 100644
--- a/ui/gfx/geometry/size_unittest.cc
+++ b/ui/gfx/geometry/size_unittest.cc
@@ -4,7 +4,6 @@
 
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/gfx/geometry/size.h"
-#include "ui/gfx/geometry/size_base.h"
 #include "ui/gfx/geometry/size_conversions.h"
 #include "ui/gfx/geometry/size_f.h"
 
diff --git a/ui/gfx/gfx.gyp b/ui/gfx/gfx.gyp
index b385459..c0ff2d3 100644
--- a/ui/gfx/gfx.gyp
+++ b/ui/gfx/gfx.gyp
@@ -32,7 +32,6 @@
         'geometry/point.h',
         'geometry/point3_f.cc',
         'geometry/point3_f.h',
-        'geometry/point_base.h',
         'geometry/point_conversions.cc',
         'geometry/point_conversions.h',
         'geometry/point_f.cc',
@@ -53,7 +52,6 @@
         'geometry/scroll_offset.h',
         'geometry/size.cc',
         'geometry/size.h',
-        'geometry/size_base.h',
         'geometry/size_conversions.cc',
         'geometry/size_conversions.h',
         'geometry/size_f.cc',
diff --git a/ui/gfx/render_text.cc b/ui/gfx/render_text.cc
index 8c516c1..d7a6a55 100644
--- a/ui/gfx/render_text.cc
+++ b/ui/gfx/render_text.cc
@@ -393,21 +393,9 @@
 }
 
 RenderText* RenderText::CreateInstance() {
-  if (CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kEnableHarfBuzzRenderText)) {
-    return new RenderTextHarfBuzz;
-  }
-  if (CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kDisableHarfBuzzRenderText)) {
-    return CreateNativeInstance();
-  }
-
-// Disable on Chrome OS. Blocked on http://crbug.com/423791
-#if defined(OS_CHROMEOS)
-  return CreateNativeInstance();
-#else
-  return new RenderTextHarfBuzz;
-#endif
+  return CommandLine::ForCurrentProcess()->HasSwitch(
+      switches::kDisableHarfBuzzRenderText) ? CreateNativeInstance() :
+      new RenderTextHarfBuzz;
 }
 
 void RenderText::SetText(const base::string16& text) {
diff --git a/ui/gfx/render_text_win.cc b/ui/gfx/render_text_win.cc
index e76e6db..4a9848e 100644
--- a/ui/gfx/render_text_win.cc
+++ b/ui/gfx/render_text_win.cc
@@ -1032,8 +1032,10 @@
 
   // Try finding a fallback font using a meta file.
   // TODO(msw|asvitkine): Support RenderText's font_list()?
+  Font uniscribe_font;
   if (GetUniscribeFallbackFont(original_font, run_text, run_length,
-                               &current_font)) {
+                               &uniscribe_font)) {
+    current_font = uniscribe_font;
     missing_count = CountCharsWithMissingGlyphs(run,
         ShapeTextRunWithFont(run, current_font));
     if (missing_count == 0) {
@@ -1050,8 +1052,25 @@
   std::vector<std::string> fonts =
       GetFallbackFontFamilies(original_font.GetFontName());
   for (size_t i = 1; i < fonts.size(); ++i) {
+    current_font = Font(fonts[i], original_font.GetFontSize());
     missing_count = CountCharsWithMissingGlyphs(run,
-        ShapeTextRunWithFont(run, Font(fonts[i], original_font.GetFontSize())));
+        ShapeTextRunWithFont(run, current_font));
+    if (missing_count == 0) {
+      successful_substitute_fonts_[original_font.GetFontName()] = current_font;
+      return;
+    }
+    if (missing_count < best_partial_font_missing_char_count) {
+      best_partial_font_missing_char_count = missing_count;
+      best_partial_font = current_font;
+    }
+  }
+
+  // Try fonts in the fallback list of the Uniscribe font.
+  fonts = GetFallbackFontFamilies(uniscribe_font.GetFontName());
+  for (size_t i = 1; i < fonts.size(); ++i) {
+    current_font = Font(fonts[i], original_font.GetFontSize());
+    missing_count = CountCharsWithMissingGlyphs(run,
+      ShapeTextRunWithFont(run, current_font));
     if (missing_count == 0) {
       successful_substitute_fonts_[original_font.GetFontName()] = current_font;
       return;
diff --git a/ui/gfx/test/run_all_unittests.cc b/ui/gfx/test/run_all_unittests.cc
index 5282da1..2c2f4ee 100644
--- a/ui/gfx/test/run_all_unittests.cc
+++ b/ui/gfx/test/run_all_unittests.cc
@@ -17,6 +17,10 @@
 #include "ui/gfx/android/gfx_jni_registrar.h"
 #endif
 
+#if defined(OS_MACOSX) && !defined(OS_IOS)
+#include "base/test/mock_chrome_application_mac.h"
+#endif
+
 namespace {
 
 class GfxTestSuite : public base::TestSuite {
@@ -31,6 +35,10 @@
     gfx::android::RegisterJni(base::android::AttachCurrentThread());
 #endif
 
+#if defined(OS_MACOSX) && !defined(OS_IOS)
+    mock_cr_app::RegisterMockCrApp();
+#endif
+
     ui::RegisterPathProvider();
 
     base::FilePath ui_test_pak_path;
diff --git a/ui/gfx/test/ui_cocoa_test_helper.mm b/ui/gfx/test/ui_cocoa_test_helper.mm
index 7f50bb3..63e32c3 100644
--- a/ui/gfx/test/ui_cocoa_test_helper.mm
+++ b/ui/gfx/test/ui_cocoa_test_helper.mm
@@ -7,6 +7,7 @@
 #include "base/debug/debugger.h"
 #include "base/logging.h"
 #include "base/stl_util.h"
+#include "base/test/mock_chrome_application_mac.h"
 #include "base/test/test_timeouts.h"
 
 namespace {
@@ -16,6 +17,11 @@
 // to flag intentional leaks without having to suppress all calls to
 // potentially leaky functions.
 void NOINLINE ForceSystemLeaks() {
+  // If a test suite hasn't already initialized NSApp, register the mock one
+  // now.
+  if (!NSApp)
+    mock_cr_app::RegisterMockCrApp();
+
   // First NSCursor push always leaks.
   [[NSCursor openHandCursor] push];
   [NSCursor pop];
diff --git a/ui/gfx/win/direct_write.cc b/ui/gfx/win/direct_write.cc
index fcc185c..058f4be 100644
--- a/ui/gfx/win/direct_write.cc
+++ b/ui/gfx/win/direct_write.cc
@@ -7,6 +7,7 @@
 #include "base/basictypes.h"
 #include "base/command_line.h"
 #include "base/metrics/field_trial.h"
+#include "base/win/registry.h"
 #include "base/win/windows_version.h"
 #include "ui/gfx/switches.h"
 #include "ui/gfx/win/dpi.h"
@@ -38,6 +39,20 @@
   if (gfx::GetDPIScale() > 1.0f)
     return true;
 
+  // We have logic in renderer_font_platform_win.cc for falling back to safe
+  // font list if machine has more than 1750 fonts installed. Users have
+  // complained about this as safe font list is usually not sufficient.
+  // We now disable direct write (gdi) if we encounter more number
+  // of fonts than a threshold (currently 1750).
+  // Refer: crbug.com/421305
+  const wchar_t kWindowsFontsRegistryKey[] =
+      L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts";
+  base::win::RegistryValueIterator reg_iterator(HKEY_LOCAL_MACHINE,
+                                                kWindowsFontsRegistryKey);
+  const DWORD kMaxAllowedFontsBeforeFallbackToGDI = 1750;
+  if (reg_iterator.ValueCount() >= kMaxAllowedFontsBeforeFallbackToGDI)
+    return false;
+
   // Otherwise, check the field trial.
   const std::string group_name =
       base::FieldTrialList::FindFullName("DirectWrite");
diff --git a/ui/message_center/test/run_all_unittests.cc b/ui/message_center/test/run_all_unittests.cc
index 274b176..7c2c8cb 100644
--- a/ui/message_center/test/run_all_unittests.cc
+++ b/ui/message_center/test/run_all_unittests.cc
@@ -12,7 +12,9 @@
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/base/ui_base_paths.h"
 
-#if !defined(OS_MACOSX)
+#if defined(OS_MACOSX)
+#include "base/test/mock_chrome_application_mac.h"
+#else
 #include "ui/gl/gl_surface.h"
 #endif
 
@@ -24,7 +26,9 @@
 
  protected:
   virtual void Initialize() override {
-#if !defined(OS_MACOSX)
+#if defined(OS_MACOSX)
+    mock_cr_app::RegisterMockCrApp();
+#else
     gfx::GLSurface::InitializeOneOffForTests();
 #endif
     base::TestSuite::Initialize();
diff --git a/ui/views/cocoa/bridged_native_widget_unittest.mm b/ui/views/cocoa/bridged_native_widget_unittest.mm
index fb4c679..eb44b9f 100644
--- a/ui/views/cocoa/bridged_native_widget_unittest.mm
+++ b/ui/views/cocoa/bridged_native_widget_unittest.mm
@@ -7,6 +7,7 @@
 #import <Cocoa/Cocoa.h>
 
 #import "base/mac/foundation_util.h"
+#import "base/mac/mac_util.h"
 #import "base/mac/sdk_forward_declarations.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/message_loop/message_loop.h"
@@ -534,6 +535,9 @@
 // by the Widget code or elsewhere (e.g. by the user).
 TEST_F(BridgedNativeWidgetTest, FullscreenSynchronousState) {
   EXPECT_FALSE(widget_->IsFullscreen());
+  if (base::mac::IsOSSnowLeopard())
+    return;
+
   // Allow user-initiated fullscreen changes on the Window.
   [test_window()
       setCollectionBehavior:[test_window() collectionBehavior] |
@@ -594,6 +598,12 @@
   // Ensure this works without having to change collection behavior as for the
   // test above.
   widget_->SetFullscreen(true);
+  if (base::mac::IsOSSnowLeopard()) {
+    // On Snow Leopard, SetFullscreen() isn't implemented. But shouldn't crash.
+    EXPECT_FALSE(widget_->IsFullscreen());
+    return;
+  }
+
   EXPECT_TRUE(widget_->IsFullscreen());
   EXPECT_EQ(restored_bounds, widget_->GetRestoredBounds());
 
@@ -625,6 +635,9 @@
 // mashing Ctrl+Left/Right to keep OSX in a transition between Spaces to cause
 // the fullscreen transition to fail.
 TEST_F(BridgedNativeWidgetSimulateFullscreenTest, FailToEnterAndExit) {
+  if (base::mac::IsOSSnowLeopard())
+    return;
+
   base::scoped_nsobject<NSWindow> owned_window(
       [[BridgedNativeWidgetTestFullScreenWindow alloc]
           initWithContentRect:NSMakeRect(50, 50, 400, 300)
@@ -657,9 +670,11 @@
   EXPECT_EQ(1, [window ignoredToggleFullScreenCount]);
   EXPECT_FALSE(bridge()->target_fullscreen_state());
 
-  // Cocoa follows up with a failure notification.
-  [center postNotificationName:NSWindowDidFailToEnterFullScreenNotification
-                        object:window];
+  // Cocoa follows up with a failure message sent to the NSWindowDelegate (there
+  // is no equivalent notification for failure). Called via id so that this
+  // compiles on 10.6.
+  id window_delegate = [window delegate];
+  [window_delegate windowDidFailToEnterFullScreen:window];
   EXPECT_FALSE(bridge()->target_fullscreen_state());
 
   // Now perform a successful fullscreen operation.
@@ -675,10 +690,9 @@
                         object:window];
   EXPECT_FALSE(bridge()->target_fullscreen_state());
 
-  // On a failure, Cocoa sends a failure notification, but then just dumps the
-  // Window out of fullscreen anyway (in that order).
-  [center postNotificationName:NSWindowDidFailToExitFullScreenNotification
-                        object:window];
+  // On a failure, Cocoa sends a failure message, but then just dumps the window
+  // out of fullscreen anyway (in that order).
+  [window_delegate windowDidFailToExitFullScreen:window];
   EXPECT_FALSE(bridge()->target_fullscreen_state());
   [center postNotificationName:NSWindowDidExitFullScreenNotification
                         object:window];
diff --git a/url/url_canon.h b/url/url_canon.h
index 624eeaf..3b9f906 100644
--- a/url/url_canon.h
+++ b/url/url_canon.h
@@ -41,13 +41,13 @@
 
   // Accessor for returning a character at a given position. The input offset
   // must be in the valid range.
-  inline char at(int offset) const {
+  inline T at(int offset) const {
     return buffer_[offset];
   }
 
   // Sets the character at the given position. The given position MUST be less
   // than the length().
-  inline void set(int offset, int ch) {
+  inline void set(int offset, T ch) {
     buffer_[offset] = ch;
   }
 
diff --git a/url/url_canon_fileurl.cc b/url/url_canon_fileurl.cc
index 1322be7..6191f8f 100644
--- a/url/url_canon_fileurl.cc
+++ b/url/url_canon_fileurl.cc
@@ -40,7 +40,7 @@
 
   // Normalize Windows drive letters to uppercase
   if (spec[after_slashes] >= 'a' && spec[after_slashes] <= 'z')
-    output->push_back(spec[after_slashes] - 'a' + 'A');
+    output->push_back(static_cast<char>(spec[after_slashes] - 'a' + 'A'));
   else
     output->push_back(static_cast<char>(spec[after_slashes]));
 
diff --git a/url/url_canon_pathurl.cc b/url/url_canon_pathurl.cc
index e81a4af..0d23ccb 100644
--- a/url/url_canon_pathurl.cc
+++ b/url/url_canon_pathurl.cc
@@ -19,13 +19,13 @@
 template<typename CHAR, typename UCHAR>
 bool DoCanonicalizePathComponent(const CHAR* source,
                                  const Component& component,
-                                 CHAR seperator,
+                                 char separator,
                                  CanonOutput* output,
                                  Component* new_component) {
   bool success = true;
   if (component.is_valid()) {
-    if (seperator)
-      output->push_back(seperator);
+    if (separator)
+      output->push_back(separator);
     // Copy the path using path URL's more lax escaping rules (think for
     // javascript:). We convert to UTF-8 and escape non-ASCII, but leave all
     // ASCII characters alone. This helps readability of JavaStript.
@@ -64,7 +64,7 @@
   // We allow path URLs to have the path, query and fragment components, but we
   // will canonicalize each of the via the weaker path URL rules.
   success &= DoCanonicalizePathComponent<CHAR, UCHAR>(
-      source.path, parsed.path, 0, output, &new_parsed->path);
+      source.path, parsed.path, '\0', output, &new_parsed->path);
   success &= DoCanonicalizePathComponent<CHAR, UCHAR>(
       source.query, parsed.query, '?', output, &new_parsed->query);
   success &= DoCanonicalizePathComponent<CHAR, UCHAR>(